-TMAI_SERVNAME_STR
-TMAI_SERVPORT_STR
-TMAPS
+-TMAP_SEARCH
-TMASTER_INT_WATCH
-TMASTER_PROC
-TMASTER_SERV
Incompatibility: this may change the appearance of logging,
and the way that check_client_access will match subnets of
an IPv6 address.
+
+20190516
+
+ Initial search order support for check_ccert_access. The
+ default behavior is backwards-compatible. This is work in
+ progress; see the RELEASE_NOTES for examples. Files:
+ global/map_search.[hc], smtpd/smtpd_check.c.
+
+20190517
+
+ Bugfix: postconf mis-parsed text starting with "{" such as
+ "check_ccert_access { inline:{a=b} { search_order=c,d } }".
+ Fixed by adding another level of recursion. File:
+ postconf/postconf_dbms.c.
the software under the license of their choice. Those who are more
comfortable with the IPL can continue with that license.
+Major changes with snapshot 20190516
+====================================
+
+Search order support for check_ccert_access. Search order support
+for other tables is in design (canonical_maps, virtual_alias_maps,
+transport_maps, etc.).
+
+The following check_ccert_access setting uses the built-in search
+order: it first looks up the client certificate fingerprint, then
+the client certificate public-key fingerprint, and it stops when a
+decision is made.
+
+/etc/postfix/main.cf:
+ smtpd_mumble_restrictions =
+ ...
+ check_ccert_access hash:/etc/postfix/ccert-access
+ ...
+
+The following setting, with explicit search order, produces the
+exact same result:
+
+/etc/postfix/main.cf:
+ smtpd_mumble_restrictions =
+ ...
+ check_ccert_access {
+ hash:/etc/postfix/ccert-access {
+ search_order = cert_fingerprint, pubkey_fingerprint } }
+ ...
+
+The check_ccert_access search order also supports the subject and
+issuer properties. Support is planned for rfc822name and smtputf8mailbox.
+
Incompatibility with snapshot 20190427
======================================
mkmap_fail.c haproxy_srvr.c dsn_filter.c dynamicmaps.c uxtext.c \
smtputf8.c mail_conf_over.c mail_parm_split.c midna_adomain.c \
mail_addr_form.c quote_flags.c maillog_client.c \
- normalize_mailhost_addr.c
+ normalize_mailhost_addr.c map_search.c
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
mkmap_fail.o haproxy_srvr.o dsn_filter.o dynamicmaps.o uxtext.o \
smtputf8.o attr_override.o mail_parm_split.o midna_adomain.o \
$(NON_PLUGIN_MAP_OBJ) mail_addr_form.o quote_flags.o maillog_client.o \
- normalize_mailhost_addr.o
+ normalize_mailhost_addr.o map_search.o
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
verify_sender_addr.h dict_memcache.h memcache_proto.h server_acl.h \
haproxy_srvr.h dsn_filter.h dynamicmaps.h uxtext.h smtputf8.h \
attr_override.h mail_parm_split.h midna_adomain.h mail_addr_form.h \
- maillog_client.h normalize_mailhost_addr.h
+ maillog_client.h normalize_mailhost_addr.h map_search.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
data_redirect addr_match_list safe_ultostr verify_sender_addr \
mail_version mail_dict server_acl uxtext mail_parm_split \
fold_addr smtp_reply_footer mail_addr_map normalize_mailhost_addr \
- haproxy_srvr
+ haproxy_srvr map_search
LIBS = ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
LIB_DIR = ../../lib
haproxy_srvr: haproxy_srvr.c $(LIB) $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+map_search: map_search.c $(LIB) $(LIBS)
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+
tests: tok822_test mime_tests strip_addr_test tok822_limit_test \
xtext_test scache_multi_test ehlo_mask_test \
namadr_list_test mail_conf_time_test header_body_checks_tests \
safe_ultostr_test mail_parm_split_test fold_addr_test \
smtp_reply_footer_test off_cvt_test mail_addr_crunch_test \
mail_addr_find_test mail_addr_map_test quote_822_local_test \
- normalize_mailhost_addr_test haproxy_srvr_test
+ normalize_mailhost_addr_test haproxy_srvr_test map_search_test
mime_tests: mime_test mime_nest mime_8bit mime_dom mime_trunc mime_cvt \
mime_cvt2 mime_cvt3 mime_garb1 mime_garb2 mime_garb3 mime_garb4
diff /dev/null haproxy_srvr.tmp
rm -f haproxy_srvr.tmp
+map_search_test: update map_search map_search.ref
+ -$(SHLIB_ENV) $(VALGRIND) ./map_search >map_search.tmp 2>&1
+ diff map_search.ref map_search.tmp
+ rm -f map_search.tmp
+
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
maillog_client.o: mail_proto.h
maillog_client.o: maillog_client.c
maillog_client.o: maillog_client.h
+map_search.o: ../../include/check_arg.h
+map_search.o: ../../include/htable.h
+map_search.o: ../../include/msg.h
+map_search.o: ../../include/mymalloc.h
+map_search.o: ../../include/name_code.h
+map_search.o: ../../include/stringops.h
+map_search.o: ../../include/sys_defs.h
+map_search.o: ../../include/vbuf.h
+map_search.o: ../../include/vstring.h
+map_search.o: map_search.c
+map_search.o: map_search.h
maps.o: ../../include/argv.h
maps.o: ../../include/check_arg.h
maps.o: ../../include/dict.h
namadr_list.o: namadr_list.h
normalize_mailhost_addr.o: ../../include/check_arg.h
normalize_mailhost_addr.o: ../../include/inet_proto.h
+normalize_mailhost_addr.o: ../../include/msg.h
normalize_mailhost_addr.o: ../../include/myaddrinfo.h
normalize_mailhost_addr.o: ../../include/mymalloc.h
normalize_mailhost_addr.o: ../../include/stringops.h
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20190427"
+#define MAIL_RELEASE_DATE "20190517"
#define MAIL_VERSION_NUMBER "3.5"
#ifdef SNAPSHOT
--- /dev/null
+/*++
+/* NAME
+/* map_search_search 3
+/* SUMMARY
+/* lookup table search list support
+/* SYNOPSIS
+/* #include <map_search_search.h>
+/*
+/* typedef struct {
+/* .in +4
+/* char *map_type_name; /* type:name, owned */
+/* char *search_order; /* null or owned */
+/* .in -4
+/* } MAP_SEARCH;
+/*
+/* void map_search_init(
+/* const NAME_CODE *search_actions)
+/*
+/* const MAP_SEARCH *map_search_create(
+/* const char *map_spec)
+/*
+/* const MAP_SEARCH *map_search_lookup(
+/* const char *map_spec);
+/* DESCRIPTION
+/* This module implements configurable search order support
+/* for Postfix lookup tables.
+/*
+/* map_search_init() must be called once, before other functions
+/* in this module.
+/*
+/* map_search_create() creates a MAP_SEARCH instance for
+/* map_spec, ignoring duplicate requests.
+/*
+/* map_search_lookup() looks up the MAP_SEARCH instance that
+/* was created by map_search_create().
+/*
+/* Arguments:
+/* .IP search_actions
+/* The mapping from search action string form to numeric form.
+/* The numbers must be in the range [1..126] (inclusive). The
+/* value 0 is reserved for the MAP_SEARCH.serch_order terminator,
+/* and the value MAP_SEARCH_CODE_UNKNOWN is reserved for the
+/* 'not found' result. The argument is copied (the pointer
+/* value, not the table).
+/* .IP map_spec
+/* lookup table and optional search order: either maptype:mapname,
+/* or { maptype:mapname, { search = name, name }}. The search
+/* attribute is optional. The comma is equivalent to whitespace.
+/* DIAGNOSTICS
+/* map_search_create() returns a null pointer when a map_spec
+/* is a) malformed, b) specifies an unexpected attribute name,
+/* c) the search attrubite contains an unknown name. Thus,
+/* map_search_create() will never return a search_order that
+/* contains the value MAP_SEARCH_CODE_UNKNOWN.
+/*
+/* Panic: interface violations. Fatal errors: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <string.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+ /*
+ * Utility library.
+ */
+#include <htable.h>
+#include <msg.h>
+#include <mymalloc.h>
+#include <name_code.h>
+#include <stringops.h>
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+#include <map_search.h>
+
+ /*
+ * Application-specific.
+ */
+static HTABLE *map_search_table;
+static const NAME_CODE *map_search_actions;
+
+#define STR(x) vstring_str(x)
+
+/* map_search_init - one-time initialization */
+
+void map_search_init(const NAME_CODE *search_actions)
+{
+ if (map_search_table != 0 || map_search_actions != 0)
+ msg_panic("map_search_init: multiple calls");
+ map_search_table = htable_create(100);
+ map_search_actions = search_actions;
+}
+
+/* map_search_create - store MAP_SEARCH instance */
+
+const MAP_SEARCH *map_search_create(const char *map_spec)
+{
+ char *copy_of_map_spec = 0;
+ char *bp = 0;
+ const char *const_err;
+ char *heap_err = 0;
+ VSTRING *search_order = 0;
+ const char *map_type_name;
+ char *attr_name_val = 0;
+ char *attr_name = 0;
+ char *attr_value = 0;
+ MAP_SEARCH *map_search;
+ char *atom;
+ int code;
+
+ /*
+ * Sanity check.
+ */
+ if (map_search_table == 0 || map_search_actions == 0)
+ msg_panic("map_search_create: missing initialization");
+
+ /*
+ * Allow exact duplicates. This won't catch duplicates that differ only
+ * in their use of whitespace or comma.
+ */
+ if ((map_search =
+ (MAP_SEARCH *) htable_find(map_search_table, map_spec)) != 0)
+ return (map_search);
+
+ /*
+ * Macro for readability and safety. Let the compiler worry about code
+ * duplication and redundant conditions.
+ */
+#define MAP_SEARCH_CREATE_RETURN(x) do { \
+ if (copy_of_map_spec) myfree(copy_of_map_spec); \
+ if (heap_err) myfree(heap_err); \
+ if (search_order) vstring_free(search_order); \
+ return (x); \
+ } while (0)
+
+ /*
+ * Long form specifies maptype_mapname and optional search attribute.
+ */
+ if (*map_spec == CHARS_BRACE[0]) {
+ bp = copy_of_map_spec = mystrdup(map_spec);
+ if ((heap_err = extpar(&bp, CHARS_BRACE, EXTPAR_FLAG_STRIP)) != 0) {
+ msg_warn("malformed map specification: '%s'", heap_err);
+ MAP_SEARCH_CREATE_RETURN(0);
+ } else if ((map_type_name = mystrtok(&bp, CHARS_COMMA_SP)) == 0) {
+ msg_warn("empty map specification: '%s'", map_spec);
+ MAP_SEARCH_CREATE_RETURN(0);
+ }
+ } else {
+ map_type_name = map_spec;
+ }
+
+ /*
+ * Sanity check the map spec before parsing attributes.
+ */
+ if (strchr(map_type_name, ':') == 0) {
+ msg_warn("malformed map specification: '%s'", map_spec);
+ msg_warn("expected maptype:mapname instead of '%s'", map_type_name);
+ MAP_SEARCH_CREATE_RETURN(0);
+ }
+
+ /*
+ * Parse the attribute list. XXX This does not detect multiple attributes
+ * with the same attribute name.
+ */
+ if (bp != 0) {
+ while ((attr_name_val = mystrtokq(&bp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) {
+ if (*attr_name_val == CHARS_BRACE[0]) {
+ if ((heap_err = extpar(&attr_name_val, CHARS_BRACE,
+ EXTPAR_FLAG_STRIP)) != 0) {
+ msg_warn("malformed map attribute: %s", heap_err);
+ MAP_SEARCH_CREATE_RETURN(0);
+ }
+ }
+ msg_info("split_nameval(\"%s\"", attr_name_val);
+ if ((const_err = split_nameval(attr_name_val, &attr_name,
+ &attr_value)) != 0) {
+ msg_warn("malformed map attribute in '%s': '%s'",
+ map_spec, const_err);
+ MAP_SEARCH_CREATE_RETURN(0);
+ }
+ if (strcasecmp(attr_name, MAP_SEARCH_ATTR_NAME_SEARCH) != 0) {
+ msg_warn("unknown map attribute in '%s': '%s'",
+ map_spec, attr_name);
+ MAP_SEARCH_CREATE_RETURN(0);
+ }
+ }
+ }
+
+ /*
+ * Parse the search list if any.
+ */
+ if (attr_name != 0) {
+ search_order = vstring_alloc(10);
+ while ((atom = mystrtok(&attr_value, CHARS_COMMA_SP)) != 0) {
+ if ((code = name_code(map_search_actions, NAME_CODE_FLAG_NONE,
+ atom)) == MAP_SEARCH_CODE_UNKNOWN) {
+ msg_warn("unknown search type '%s' in '%s'", atom, map_spec);
+ MAP_SEARCH_CREATE_RETURN(0);
+ }
+ VSTRING_ADDCH(search_order, code);
+ }
+ VSTRING_TERMINATE(search_order);
+ }
+
+ /*
+ * Bundle up the result.
+ */
+ map_search = (MAP_SEARCH *) mymalloc(sizeof(*map_search));
+ map_search->map_type_name = mystrdup(map_type_name);
+ if (search_order) {
+ map_search->search_order = vstring_export(search_order);
+ search_order = 0;
+ } else {
+ map_search->search_order = 0;
+ }
+
+ /*
+ * Save the ACL to cache.
+ */
+ (void) htable_enter(map_search_table, map_spec, map_search);
+
+ MAP_SEARCH_CREATE_RETURN(map_search);
+}
+
+/* map_search_lookup - lookup MAP_SEARCH instance */
+
+const MAP_SEARCH *map_search_lookup(const char *map_spec)
+{
+
+ /*
+ * Sanity check.
+ */
+ if (map_search_table == 0 || map_search_actions == 0)
+ msg_panic("map_search_lookup: missing initialization");
+
+ return ((MAP_SEARCH *) htable_find(map_search_table, map_spec));
+}
+
+ /*
+ * Test driver.
+ */
+#ifdef TEST
+#include <stdlib.h>
+
+ /*
+ * Test search actions.
+ */
+#define TEST_NAME_1 "one"
+#define TEST_NAME_2 "two"
+#define TEST_CODE_1 1
+#define TEST_CODE_2 2
+
+#define BAD_NAME "bad"
+
+static const NAME_CODE search_actions[] = {
+ TEST_NAME_1, TEST_CODE_1,
+ TEST_NAME_2, TEST_CODE_2,
+ 0, MAP_SEARCH_CODE_UNKNOWN,
+};
+
+/* Helpers to simplify tests. */
+
+static const char *string_or_null(const char *s)
+{
+ return (s ? s : "(null)");
+}
+
+static char *escape_order(VSTRING *buf, const char *seach_order)
+{
+ return (STR(escape(buf, seach_order, strlen(seach_order))));
+}
+
+int main(int argc, char **argv)
+{
+ /* Test cases with inputs and expected outputs. */
+ typedef struct TEST_CASE {
+ const char *map_spec;
+ int exp_return; /* 0=fail, 1=success */
+ const char *exp_map_type_name; /* 0 or match */
+ const char *exp_search_order; /* 0 or match */
+ } TEST_CASE;
+ static TEST_CASE test_cases[] = {
+ {"type", 0, 0, 0},
+ {"type:name", 1, "type:name", 0},
+ {"{type:name}", 1, "type:name", 0},
+ {"{type:name", 0, 0, 0}, /* } */
+ {"{type}", 0, 0, 0},
+ {"{type:name foo}", 0, 0, 0},
+ {"{type:name foo=bar}", 0, 0, 0},
+ {"{type:name search_order=}", 1, "type:name", ""},
+ {"{type:name search_order=one, two}", 0, 0, 0},
+ {"{type:name {search_order=one, two}}", 1, "type:name", "\01\02"},
+ {"{type:name {search_order=one, two, bad}}", 0, 0, 0},
+ {"{inline:{a=b} {search_order=one, two}}", 1, "inline:{a=b}", "\01\02"},
+ {0},
+ };
+ TEST_CASE *test_case;
+
+ /* Actual results. */
+ const MAP_SEARCH *map_search_from_create;
+ const MAP_SEARCH *map_search_from_create_2nd;
+ const MAP_SEARCH *map_search_from_lookup;
+
+ /* Findings. */
+ int tests_failed = 0;
+ int test_failed;
+
+ /* Scratch */
+ VSTRING *expect_escaped = vstring_alloc(100);
+ VSTRING *actual_escaped = vstring_alloc(100);
+
+ map_search_init(search_actions);
+
+ for (tests_failed = 0, test_case = test_cases; test_case->map_spec;
+ tests_failed += test_failed, test_case++) {
+ test_failed = 0;
+ msg_info("test case %d: '%s'",
+ (int) (test_case - test_cases), test_case->map_spec);
+ map_search_from_create = map_search_create(test_case->map_spec);
+ if (!test_case->exp_return != !map_search_from_create) {
+ if (map_search_from_create)
+ msg_warn("test case %d return expected %s actual {%s, %s}",
+ (int) (test_case - test_cases),
+ test_case->exp_return ? "success" : "fail",
+ map_search_from_create->map_type_name,
+ escape_order(actual_escaped,
+ map_search_from_create->search_order));
+ else
+ msg_warn("test case %d return expected %s actual %s",
+ (int) (test_case - test_cases), "success",
+ map_search_from_create ? "success" : "fail");
+ test_failed = 1;
+ continue;
+ }
+ if (test_case->exp_return == 0)
+ continue;
+ map_search_from_lookup = map_search_lookup(test_case->map_spec);
+ if (map_search_from_create != map_search_from_lookup) {
+ msg_warn("test case %d map_search_lookup expected=%p actual=%p",
+ (int) (test_case - test_cases),
+ map_search_from_create, map_search_from_lookup);
+ test_failed = 1;
+ }
+ map_search_from_create_2nd = map_search_create(test_case->map_spec);
+ if (map_search_from_create != map_search_from_create_2nd) {
+ msg_warn("test case %d repeated map_search_create "
+ "expected=%p actual=%p",
+ (int) (test_case - test_cases),
+ map_search_from_create, map_search_from_create_2nd);
+ test_failed = 1;
+ }
+ if (strcmp(string_or_null(test_case->exp_map_type_name),
+ string_or_null(map_search_from_create->map_type_name))) {
+ msg_warn("test case %d map_type_name expected=%s actual=%s",
+ (int) (test_case - test_cases),
+ string_or_null(test_case->exp_map_type_name),
+ string_or_null(map_search_from_create->map_type_name));
+ test_failed = 1;
+ }
+ if (strcmp(string_or_null(test_case->exp_search_order),
+ string_or_null(map_search_from_create->search_order))) {
+ msg_warn("test case %d search_order expected=%s actual=%s",
+ (int) (test_case - test_cases),
+ escape_order(expect_escaped,
+ string_or_null(test_case->exp_search_order)),
+ escape_order(actual_escaped,
+ string_or_null(map_search_from_create->search_order)));
+ test_failed = 1;
+ }
+ }
+ vstring_free(expect_escaped);
+ vstring_free(actual_escaped);
+
+ if (tests_failed)
+ msg_info("tests failed: %d", tests_failed);
+ exit(tests_failed != 0);
+}
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* map_search 3h
+/* SUMMARY
+/* lookup table search list support
+/* SYNOPSIS
+/* #include <map_search.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <name_code.h>
+
+ /*
+ * External interface.
+ *
+ * The map_search module maintains one lookup table with MAP_SEARCH results,
+ * indexed by the unparsed form of a map specification. The conversion from
+ * unparsed form to MAP_SEARCH result is controlled by a NAME_CODE mapping,
+ * Since one lokoup table can support only one mapping per unparsed name,
+ * every MAP_SEARCH result in the lookup table must be built using the same
+ * NAME_CODE table.
+ *
+ * Alternative 1: no lookup table. Allow the user to specicy the NAME_CODE
+ * mapping in the map_search_create() request (in addition to the unparsed
+ * form), and let the MAP_SEARCH user store each MAP_SEARCH pointer. But
+ * that would clumsify code that wants to use MAP_SEARCH functionality.
+ *
+ * Alternative 2: one lookup table per NAME_CODE mapping. Change
+ * map_search_init() to return a pointer to {HTABLE *, NAME_CODE *}, and
+ * require that the MAP_SEARCH user pass that pointer to other
+ * map_search_xxx() calls (in addition to the unparsed forms). That would be
+ * about as clumsy as Alternative 1.
+ *
+ * Alternative 3: one lookup table, distinct lookup keys per NAME_CODE table
+ * and map_spec. The caller specifies both the map_spec and the NAME_CODE
+ * mapping when it calls map_seach_create() and map_search_find(). The
+ * implementation securely prepends the name_code argument to the map_spec
+ * argument and uses the result as the table lookup key.
+ *
+ * Alternative 1 is not suitable for the smtpd_mumble_restrictions parser,
+ * which instantiates MAP_SEARCH instances without knowing which specific
+ * access feature is involved. It uses a NAME_CODE mapping that contains the
+ * superset of what all smtpd_mumble_restrictions features need. The
+ * downside is delayed error notification.
+ */
+typedef struct {
+ char *map_type_name; /* "type:name", owned */
+ char *search_order; /* null or owned */
+} MAP_SEARCH;
+
+extern void map_search_init(const NAME_CODE *);
+extern const MAP_SEARCH *map_search_create(const char *);
+extern const MAP_SEARCH *map_search_lookup(const char *);
+
+#define MAP_SEARCH_ATTR_NAME_SEARCH "search_order"
+
+#define MAP_SEARCH_CODE_UNKNOWN 127
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
--- /dev/null
+unknown: test case 0: 'type'
+unknown: warning: malformed map specification: 'type'
+unknown: warning: expected maptype:mapname instead of 'type'
+unknown: test case 1: 'type:name'
+unknown: test case 2: '{type:name}'
+unknown: test case 3: '{type:name'
+unknown: warning: malformed map specification: 'missing '}' in "{type:name"'
+unknown: test case 4: '{type}'
+unknown: warning: malformed map specification: '{type}'
+unknown: warning: expected maptype:mapname instead of 'type'
+unknown: test case 5: '{type:name foo}'
+unknown: split_nameval("foo"
+unknown: warning: malformed map attribute in '{type:name foo}': 'missing '=' after attribute name'
+unknown: test case 6: '{type:name foo=bar}'
+unknown: split_nameval("foo=bar"
+unknown: warning: unknown map attribute in '{type:name foo=bar}': 'foo'
+unknown: test case 7: '{type:name search_order=}'
+unknown: split_nameval("search_order="
+unknown: test case 8: '{type:name search_order=one, two}'
+unknown: split_nameval("search_order=one"
+unknown: split_nameval("two"
+unknown: warning: malformed map attribute in '{type:name search_order=one, two}': 'missing '=' after attribute name'
+unknown: test case 9: '{type:name {search_order=one, two}}'
+unknown: split_nameval("search_order=one, two"
+unknown: test case 10: '{type:name {search_order=one, two, bad}}'
+unknown: split_nameval("search_order=one, two, bad"
+unknown: warning: unknown search type 'bad' in '{type:name {search_order=one, two, bad}}'
+unknown: test case 11: '{inline:{a=b} {search_order=one, two}}'
+unknown: split_nameval("search_order=one, two"
rm -f $@
(echo "# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE"; \
echo "# TEXT HERE JUST SHOWS DEFAULT SETTINGS BUILT INTO POSTFIX."; \
- echo "#"; $(SHLIB_ENV) ./$(PROG) -d -c ../../conf) | \
+ echo "#"; $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -d -c ../../conf) | \
egrep -v '^(myhostname|mydomain|mynetworks|process_name|process_id) ' >$@
$(OBJS): ../../conf/makedefs.out
test31 test32 test33 test34 test35 test36 test37 test39 test40 test41 \
test42 test43 test44 test45 test46 test47 test48 test49 test50 test51 \
test52 test53 test54 test55 test56 test57 test58 test59 test60 test61 \
- test62 test63 test64 test65 test66 test67 test68 test69
+ test62 test63 test64 test65 test66 test67 test68 test69 test70
root_tests:
echo smtpd_restriction_classes = foo bar >> main.cf
echo foo = yes >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test1.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test1.tmp 2>&1
diff test1.ref test1.tmp
rm -f main.cf master.cf test1.tmp
echo restriction_classes = foo bar >> main.cf
echo foo = yes >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test2.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test2.tmp 2>&1
diff test2.ref test2.tmp
rm -f main.cf master.cf test2.tmp
echo 'bar = $$foo' >> main.cf
echo 'always_bcc = $$bar' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test3.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test3.tmp 2>&1
diff test3.ref test3.tmp
rm -f main.cf master.cf test3.tmp
echo smtpd unix - n n - 0 smtpd >> master.cf
echo ' -o always_bcc=$$bar' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test4.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test4.tmp 2>&1
diff test4.ref test4.tmp
rm -f main.cf master.cf test4.tmp
echo ' -o foo=xxx -o bar=yyy -o baz=zzz' >> master.cf
echo '#smtpd2 unix - n n - 0 smtpd' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test4b.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test4b.tmp 2>&1
diff test4b.ref test4b.tmp
rm -f main.cf master.cf test4b.tmp
echo smtpd unix - n n - 0 smtpd >> master.cf
echo ' -o bar=yes -o always_bcc=$$bar -o' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test5.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test5.tmp 2>&1
diff test5.ref test5.tmp
rm -f main.cf master.cf test5.tmp
touch main.cf master.cf
echo whatevershebrings unix - n n - 0 pipe >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . 2>&1 | grep whatevershebrings >test6.tmp
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . 2>&1 | grep whatevershebrings >test6.tmp
diff test6.ref test6.tmp
rm -f main.cf master.cf test6.tmp
touch main.cf master.cf
echo whatevershebrings unix - n n - 0 spawn >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . 2>&1 | grep whatevershebrings >test7.tmp
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . 2>&1 | grep whatevershebrings >test7.tmp
diff test7.ref test7.tmp
rm -f main.cf master.cf test7.tmp
echo whatevershebrings inet - n n - 0 spawn >> master.cf
echo whatevershebrings_time_limit=1 >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . 2>&1 | grep whatevershebrings >test8.tmp
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . 2>&1 | grep whatevershebrings >test8.tmp
diff test8.ref test8.tmp
rm -f main.cf master.cf test8.tmp
echo foo inet - n n - 0 spawn >> master.cf
echo bar unix - n n - 0 spawn >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . -M '*'/inet >test9.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -M '*'/inet >test9.tmp 2>&1
diff test9.ref test9.tmp
rm -f main.cf master.cf test9.tmp
echo foo inet - n n - 0 spawn >> master.cf
echo bar unix - n n - 0 spawn >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . -M bar/inet foo/unix >test10.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -M bar/inet foo/unix >test10.tmp 2>&1
diff test10.ref test10.tmp
rm -f main.cf master.cf test10.tmp
echo foo inet - n n - 0 spawn >> master.cf
echo bar unix - n n - 0 spawn >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . -M >test11.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -M >test11.tmp 2>&1
diff test11.ref test11.tmp
rm -f main.cf master.cf test11.tmp
echo foo inet - n n - 0 spawn >> master.cf
echo ' -o always_bcc=$$bar -o' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . -M >test12.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -M >test12.tmp 2>&1
diff test12.ref test12.tmp
rm -f main.cf master.cf test12.tmp
echo foo inet - n n - 0 spawn >> master.cf
echo ' -o smtpd_restriction_classes=bar' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test13.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test13.tmp 2>&1
diff test13.ref test13.tmp
rm -f main.cf master.cf test13.tmp
echo foo inet - n n - 0 spawn >> master.cf
echo ' -o bar=yes -o baz=xx' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test14.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test14.tmp 2>&1
diff test14.ref test14.tmp
rm -f main.cf master.cf test14.tmp
echo foo inet - n n - 0 spawn >> master.cf
echo ' -o bar=yes -o always_bcc=$$bar$$baz' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test15.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test15.tmp 2>&1
diff test15.ref test15.tmp
rm -f main.cf master.cf test15.tmp
test16: $(PROG) test16.ref
rm -f main.cf master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test16.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test16.tmp 2>&1
diff test16.ref test16.tmp
rm -f main.cf master.cf test16.tmp
test17: $(PROG) test17.ref
rm -f main.cf master.cf
touch -t 197101010000 main.cf
- -$(SHLIB_ENV) ./$(PROG) -Mc . >test17.tmp 2>&1; exit 0
+ -$(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc . >test17.tmp 2>&1; exit 0
diff test17.ref test17.tmp
rm -f main.cf master.cf test17.tmp
echo virtual_maps=xxx >> main.cf
echo smtpd_client_connection_limit_exceptions=yyy >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test18.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test18.tmp 2>&1
diff test18.ref test18.tmp
rm -f main.cf master.cf test18.tmp
echo forward_path='$$'aaaa >> main.cf
echo default_rbl_reply='$$'bbbb >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test19.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test19.tmp 2>&1
diff test19.ref test19.tmp
rm -f main.cf master.cf test19.tmp
echo foo inet - n n - 0 spawn >> master.cf
echo ' -o always_bcc=$$bar$$baz' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfc . >test20.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc . >test20.tmp 2>&1
diff test20.ref test20.tmp
rm -f main.cf master.cf test20.tmp
echo forward_path = xxxxxxxxxxxxx xxxxxxxxxxxxxx xxxxxxxxxxxx \
xxxxxxxxxxxxx xxxxxxxxxxxxxx >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nfc . >test21.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nfc . >test21.tmp 2>&1
diff test21.ref test21.tmp
rm -f main.cf master.cf test21.tmp
touch main.cf master.cf
echo whatevershebrings unix - n n - 0 smtp >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . 2>&1 | grep whatevershebrings >test22.tmp
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . 2>&1 | grep whatevershebrings >test22.tmp
diff test22.ref test22.tmp
rm -f main.cf master.cf test22.tmp
echo whatevershebrings unix - n n - 0 smtp >> master.cf
echo ' -o always_bcc=$$name' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . -nC builtin >test23.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -nC builtin >test23.tmp 2>&1
diff test23.ref test23.tmp
rm -f main.cf master.cf test23.tmp
echo whatevershebrings unix - n n - 0 smtp >> master.cf
echo ' -o always_bcc=$$name' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . -nC user >test24.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -nC user >test24.tmp 2>&1
diff test24.ref test24.tmp
rm -f main.cf master.cf test24.tmp
echo whatevershebrings unix - n n - 0 smtp >> master.cf
echo ' -o always_bcc=$$name' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . -C service 2>&1 | grep whatevershebrings >test25.tmp
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -C service 2>&1 | grep whatevershebrings >test25.tmp
diff test25.ref test25.tmp
rm -f main.cf master.cf test25.tmp
echo whatevershebrings unix - n n - 0 smtp >> master.cf
echo ' -o always_bcc=$$name' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . -C all >test26.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . -C all >test26.tmp 2>&1
diff test26.ref test26.tmp
rm -f main.cf master.cf test26.tmp
echo whatevershebrings unix - n n - 0 smtp >> master.cf
echo ' -o always_bcc=$$name' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c . -C all 2>&1 | grep whatevershebrings >test27.tmp
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -C all 2>&1 | grep whatevershebrings >test27.tmp
diff test27.ref test27.tmp
rm -f main.cf master.cf test27.tmp
echo 'aap_domain = whatever' >> main.cf
echo 'aa_domain = whatever' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test28.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test28.tmp 2>&1
diff test28.ref test28.tmp
rm -f main.cf master.cf test28.tmp
echo 'memcachefoo_domain = bar' >> main.cf
echo 'memcachefoo_domainx = bar' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test29.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test29.tmp 2>&1
diff test29.ref test29.tmp
rm -f main.cf master.cf test29.tmp
echo ' -oheader_checks=$$p3' >> master.cf
echo ' -oheaderx_checks=$$p4' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test30.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test30.tmp 2>&1
diff test30.ref test30.tmp
rm -f main.cf master.cf test30.tmp
echo 'smtpd_helo_restrictions=whatever' >> main.cf
echo 'smtpd_sender_restrictions=$$smtpd_helo_restrictions' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nxc . >test31.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nxc . >test31.tmp 2>&1
diff test31.ref test31.tmp
rm -f main.cf master.cf test31.tmp
touch main.cf master.cf
echo 'relay_domains=whatever' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -xc . fast_flush_domains >test32.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -xc . fast_flush_domains >test32.tmp 2>&1
diff test32.ref test32.tmp
rm -f main.cf master.cf test32.tmp
echo 'mydestination=whatever' >> main.cf
echo 'always_bcc=$$relay_domains' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -xc . always_bcc >test33.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -xc . always_bcc >test33.tmp 2>&1
diff test33.ref test33.tmp
rm -f main.cf master.cf test33.tmp
echo 'process_name=xxx' >> main.cf
echo 'process_id=yyy' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -xc . mydestination process_name >test34.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -xc . mydestination process_name >test34.tmp 2>&1
diff test34.ref test34.tmp
rm -f main.cf master.cf test34.tmp
echo ' -o process_name=aaa' >> master.cf
echo ' -o process_id=bbb' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -xc . process_name >test35.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -xc . process_name >test35.tmp 2>&1
diff test35.ref test35.tmp
rm -f main.cf master.cf test35.tmp
echo 'mydestination=$$virtual_mapx' >> main.cf
echo 'virtual_alias_maps=$$virtual_maps' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nxc . >test36.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nxc . >test36.tmp 2>&1
diff test36.ref test36.tmp
rm -f main.cf master.cf test36.tmp
echo ' -o always_bcc=$$aaa' >> master.cf
echo ' -o aaa=ccc' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfxc . >test37.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfxc . >test37.tmp 2>&1
diff test37.ref test37.tmp
rm -f main.cf master.cf test37.tmp
echo bar inet - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfc . '*'/unix >test39.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc . '*'/unix >test39.tmp 2>&1
diff test39.ref test39.tmp
rm -f main.cf master.cf test39.tmp
echo ' -vo ccc=$$aaa' >> master.cf
echo ' -v -oddd=$$ccc' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfxc . '*'/unix >test40.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfxc . '*'/unix >test40.tmp 2>&1
diff test40.ref test40.tmp
rm -f main.cf master.cf test40.tmp
echo bar unix - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Pc . bar/unix/xxx=yyy bar/unix/aaa=bbb >test41.tmp 2>&1
- $(SHLIB_ENV) ./$(PROG) -Mfc. >>test41.tmp 2>&1
- $(SHLIB_ENV) ./$(PROG) -Pc . bar/unix/xxx=YYY bar/unix/aaa=BBB >>test41.tmp 2>&1
- $(SHLIB_ENV) ./$(PROG) -Mfc. >>test41.tmp 2>&1
- $(SHLIB_ENV) ./$(PROG) -Pc . >>test41.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Pc . bar/unix/xxx=yyy bar/unix/aaa=bbb >test41.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >>test41.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Pc . bar/unix/xxx=YYY bar/unix/aaa=BBB >>test41.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >>test41.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Pc . >>test41.tmp 2>&1
diff test41.ref test41.tmp
rm -f main.cf master.cf test41.tmp
echo bar unix - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Pc . bar/unix/xxx=yyy bar/unix/aaa=bbb >test42.tmp 2>&1
- $(SHLIB_ENV) ./$(PROG) -Mfc. >>test42.tmp 2>&1
- $(SHLIB_ENV) ./$(PROG) -Pc . >>test42.tmp 2>&1
- $(SHLIB_ENV) ./$(PROG) -PXc. bar/unix/xxx bar/unix/aaa >>test42.tmp 2>&1
- $(SHLIB_ENV) ./$(PROG) -Mfc. >>test42.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Pc . bar/unix/xxx=yyy bar/unix/aaa=bbb >test42.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >>test42.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Pc . >>test42.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -PXc. bar/unix/xxx bar/unix/aaa >>test42.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >>test42.tmp 2>&1
diff test42.ref test42.tmp
rm -f main.cf master.cf test42.tmp
echo bar unix - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Fc . bar/unix/chroot=y bar/unix/command='aa -stuffobb=cc dd' >test43.tmp 2>&1
- $(SHLIB_ENV) ./$(PROG) -Mfc. >>test43.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Fc . bar/unix/chroot=y bar/unix/command='aa -stuffobb=cc dd' >test43.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >>test43.tmp 2>&1
diff test43.ref test43.tmp
rm -f main.cf master.cf test43.tmp
echo bar unix - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mc . bar/unix='xx inet - n n - 0 aa -stuffobb=cc dd' >test44.tmp 2>&1
- $(SHLIB_ENV) ./$(PROG) -Mfc. >>test44.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc . bar/unix='xx inet - n n - 0 aa -stuffobb=cc dd' >test44.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >>test44.tmp 2>&1
diff test44.ref test44.tmp
rm -f main.cf master.cf test44.tmp
echo bar xxxx - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfc. >test45.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >test45.tmp 2>&1 || true
diff test45.ref test45.tmp
rm -f main.cf master.cf test45.tmp
echo bar inet X n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfc. >test46.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >test46.tmp 2>&1 || true
diff test46.ref test46.tmp
rm -f main.cf master.cf test46.tmp
echo bar inet - X n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfc. >test47.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >test47.tmp 2>&1 || true
diff test47.ref test47.tmp
rm -f main.cf master.cf test47.tmp
echo bar inet - n X - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfc. >test48.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >test48.tmp 2>&1 || true
diff test48.ref test48.tmp
rm -f main.cf master.cf test48.tmp
echo bar inet - n n X 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfc. >test49.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >test49.tmp 2>&1 || true
diff test49.ref test49.tmp
rm -f main.cf master.cf test49.tmp
echo bar inet - n n - X other >> master.cf
echo baz unix - n n - 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfc. >test50.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >test50.tmp 2>&1 || true
diff test50.ref test50.tmp
rm -f main.cf master.cf test50.tmp
echo bar inet - n n X? 0 other >> master.cf
echo baz unix - n n 0? 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfc. >test51.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >test51.tmp 2>&1 || true
diff test51.ref test51.tmp
rm -f main.cf master.cf test51.tmp
echo bar inet - n n 0 0 other >> master.cf
echo baz unix - n n 0 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -MXc. bar/inet foo/unix xxx/yyy
- $(SHLIB_ENV) ./$(PROG) -Mfc. >test52.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -MXc. bar/inet foo/unix xxx/yyy
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >test52.tmp 2>&1 || true
diff test52.ref test52.tmp
rm -f main.cf master.cf test52.tmp
echo bar inet - n n 0 0 other >> master.cf
echo baz unix - n n 0 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -M#c. bar/inet xxx/yyy
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -M#c. bar/inet xxx/yyy
diff test53.ref master.cf
rm -f main.cf master.cf test53.tmp
echo bar inet - n n 0 0 other >> master.cf
echo baz unix - n n 0 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -M#c. bar/inet foo/unix
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -M#c. bar/inet foo/unix
diff test54.ref master.cf
rm -f main.cf master.cf test54.tmp
echo bar inet - n n 0 0 other >> master.cf
echo baz unix - n n 0 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -M#c. bar/inet baz/unix
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -M#c. bar/inet baz/unix
diff test55.ref master.cf
rm -f main.cf master.cf test55.tmp
echo " -o second" >> master.cf
echo baz unix - n n 0 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -M#c. bar/inet xxx/yyy
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -M#c. bar/inet xxx/yyy
diff test56.ref master.cf
rm -f main.cf master.cf test56.tmp
echo 't1 = Postfix 2.11 $${{$${x?bug:x}} == {bug}?in}compatible' >> main.cf
echo 't2 = $$t1' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nxc. >test57.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nxc. >test57.tmp 2>&1
diff test57.ref test57.tmp
rm -f main.cf master.cf test57.tmp
echo 'yy_backup = bbb' >> main.cf
echo 'yy_bogus = bbb' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./postconf -nc. >test58.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./postconf -nc. >test58.tmp 2>&1 || true
diff test58.ref test58.tmp
rm -f main.cf master.cf test58.tmp
echo " { arg3a arg3b " >> master.cf
echo baz unix - n n 0 0 other >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Mfc. >test59.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mfc. >test59.tmp 2>&1 || true
diff test59.ref test59.tmp
rm -f main.cf master.cf test59.tmp
echo foo unix - n n - 0 other >> master.cf
echo ' -o always_bcc=bar' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Fhc. >test60.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Fhc. >test60.tmp 2>&1 || true
diff test60.ref test60.tmp
rm -f main.cf master.cf test60.tmp
echo foo unix - n n - 0 other >> master.cf
echo ' -o always_bcc=bar' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -Phc. >test61.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Phc. >test61.tmp 2>&1 || true
diff test61.ref test61.tmp
rm -f main.cf master.cf test61.tmp
echo foo unix - n n - 0 other >> master.cf
echo ' -o always_bcc=bar' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -FHc. >test62.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -FHc. >test62.tmp 2>&1 || true
diff test62.ref test62.tmp
rm -f main.cf master.cf test62.tmp
echo foo unix - n n - 0 other >> master.cf
echo ' -o always_bcc=bar' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -PHc. >test63.tmp 2>&1 || true
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -PHc. >test63.tmp 2>&1 || true
diff test63.ref test63.tmp
rm -f main.cf master.cf test63.tmp
touch main.cf master.cf
echo 'relayhost = relay-from-main.cf' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c. relayhost >test64.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c. relayhost >test64.tmp 2>&1
diff test64.ref test64.tmp
rm -f main.cf master.cf test64.tmp
touch main.cf master.cf
echo 'relayhost = relay-from-main.cf' >> main.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c. -o relayhost=relay-from-cmd-line relayhost >test65.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c. -o relayhost=relay-from-cmd-line relayhost >test65.tmp 2>&1
diff test65.ref test65.tmp
rm -f main.cf master.cf test65.tmp
echo " " memcache:`pwd`/test66.cf >> main.cf
echo junk = junk >> test66.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c. 2>test66.tmp >/dev/null
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c. 2>test66.tmp >/dev/null
sed "s;PWD;`pwd`;" test66.ref | diff - test66.tmp
rm -f main.cf master.cf test66.tmp test66.cf
echo ' -o test2_process_name=$$process_name' >> master.cf
echo ' -o test2_service_name=$$service_name' >> master.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -xMfc. >test67.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -xMfc. >test67.tmp 2>&1
diff test67.ref test67.tmp
rm -f main.cf master.cf test67.tmp
echo " " memcache:`pwd`/test68.cf >> main.cf
echo junk = junk >> test68.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -c. 2>test68.tmp >/dev/null
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c. 2>test68.tmp >/dev/null
sed "s;PWD;`pwd`;" test68.ref | diff - test68.tmp
rm -f main.cf master.cf test68.tmp test68.cf
echo ' -o body_checks=$$ldap/test69.cf' >> master.cf
echo junk = junk >> test69.cf
touch -t 197101010000 main.cf
- $(SHLIB_ENV) ./$(PROG) -nc . >test69.tmp 2>&1
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test69.tmp 2>&1
sed "s;PWD;`pwd`;" test69.ref | diff - test69.tmp
rm -f main.cf master.cf test69.tmp test69.cf
+# Nasty nesting. Prove that the ldap table is detected. If support for
+# legacy table syntax is dropped, replace ldap:xyz with ldap:`pwd`/xyz
+# and update the good/bad parameter name tests.
+
+test70: $(PROG) test70.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ echo "smtpd_client_restrictions = check_sender_access {" >>main.cf
+ echo " pipemap:{ldap:used} { search_order = foo, bar } }" >>main.cf
+ echo "used_server_host = 127.0.0.1" >>main.cf
+ echo "unused_server_host = 127.0.0.1" >>main.cf
+ touch -t 197101010000 main.cf
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test70.tmp 2>&1
+ diff test70.ref test70.tmp
+ rm -f main.cf master.cf test70.tmp test70.cf
+
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
* database or some other text.
*/
while ((db_type = mystrtokq(&str_value, CHARS_COMMA_SP, CHARS_BRACE)) != 0) {
+ if (*db_type == CHARS_BRACE[0]) {
+ if ((err = extpar(&db_type, CHARS_BRACE, EXTPAR_FLAG_NONE)) != 0) {
+ /* XXX Encapsulate this in pcf_warn() function. */
+ if (local_scope)
+ msg_warn("%s:%s: %s",
+ MASTER_CONF_FILE, local_scope->name_space, err);
+ else
+ msg_warn("%s: %s", MAIN_CONF_FILE, err);
+ myfree(err);
+ }
+ pcf_register_dbms_helper(db_type, flag_parameter, local_scope);
+ continue;
+ }
/*
* Skip over "proxy:" maptypes, to emulate the proxymap(8) server's
msg_warn("%s: %s", MAIN_CONF_FILE, err);
myfree(err);
}
- pcf_register_dbms_helper(prefix, flag_parameter,
- local_scope);
+ pcf_register_dbms_helper(prefix, flag_parameter, local_scope);
+ continue;
} else {
for (dp = pcf_dbms_info; dp->db_type != 0; dp++) {
if (strcmp(db_type, dp->db_type) == 0) {
--- /dev/null
+config_directory = .
+smtpd_client_restrictions = check_sender_access { pipemap:{ldap:used} { search_order = foo, bar } }
+used_server_host = 127.0.0.1
+./postconf: warning: ./main.cf: unused parameter: unused_server_host=127.0.0.1
smtpd_check.o: ../../include/mail_params.h
smtpd_check.o: ../../include/mail_proto.h
smtpd_check.o: ../../include/mail_stream.h
+smtpd_check.o: ../../include/map_search.h
smtpd_check.o: ../../include/maps.h
smtpd_check.o: ../../include/match_list.h
smtpd_check.o: ../../include/match_parent_style.h
#include <valid_utf8_hostname.h>
#include <midna_domain.h>
#include <mynetworks.h>
+#include <name_code.h>
/* DNS library. */
#include <xtext.h>
#include <smtp_stream.h>
#include <attr_override.h>
+#include <map_search.h>
/* Application-specific. */
#define smtpd_policy_def_action_offset 0
#define smtpd_policy_context_offset 1
+ /*
+ * Search order names must be distinct, non-empty, and non-null.
+ */
+#define SMTPD_ACL_SEARCH_NAME_CERT_FPRINT "cert_fingerprint"
+#define SMTPD_ACL_SEARCH_NAME_PKEY_FPRINT "pubkey_fingerprint"
+#define SMTPD_ACL_SEARCH_NAME_CERT_ISSUER "issuer"
+#define SMTPD_ACL_SEARCH_NAME_CERT_SUBJECT "subject"
+
+ /*
+ * Search order tokens must be distinct, and 1..126 inclusive, so that they
+ * can be stored in a character string without concerns about signed versus
+ * unsigned. Code 127 is reserved by map_search(3).
+ */
+#define SMTPD_ACL_SEARCH_CODE_CERT_FPRINT 1
+#define SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT 2
+#define SMTPD_ACL_SEARCH_CODE_CERT_ISSUER 3
+#define SMTPD_ACL_SEARCH_CODE_CERT_SUBJECT 4
+
+ /*
+ * Mapping from search-list names and to search-list codes.
+ */
+static const NAME_CODE search_actions[] = {
+ SMTPD_ACL_SEARCH_NAME_CERT_FPRINT, SMTPD_ACL_SEARCH_CODE_CERT_FPRINT,
+ SMTPD_ACL_SEARCH_NAME_PKEY_FPRINT, SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT,
+ SMTPD_ACL_SEARCH_NAME_CERT_ISSUER, SMTPD_ACL_SEARCH_CODE_CERT_ISSUER,
+ SMTPD_ACL_SEARCH_NAME_CERT_SUBJECT, SMTPD_ACL_SEARCH_CODE_CERT_SUBJECT,
+ 0, MAP_SEARCH_CODE_UNKNOWN,
+};
+
/* policy_client_register - register policy service endpoint */
static void policy_client_register(const char *name)
char *bp = saved_checks;
char *name;
char *last = 0;
+ const MAP_SEARCH *map_search;
/*
* Pre-parse the restriction list, and open any dictionaries that we
while ((name = mystrtokq(&bp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) {
argv_add(argv, name, (char *) 0);
if ((flags & SMTPD_CHECK_PARSE_POLICY)
- && last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0)
+ && last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0) {
policy_client_register(name);
- else if ((flags & SMTPD_CHECK_PARSE_MAPS) && strchr(name, ':') != 0) {
- command_map_register(name);
+ } else if ((flags & SMTPD_CHECK_PARSE_MAPS)
+ && (*name == *CHARS_BRACE || strchr(name, ':') != 0)) {
+ if ((map_search = map_search_create(name)) != 0)
+ command_map_register(map_search->map_type_name);
}
last = name;
}
smtpd_rbl_byte_cache = ctable_create(1000, rbl_byte_pagein,
rbl_byte_pageout, (void *) 0);
+ /*
+ * Initialize access map search list support before parsing restriction
+ * lists.
+ */
+ map_search_init(search_actions);
+
/*
* Pre-parse the restriction lists. At the same time, pre-open tables
* before going to jail.
/* check_ccert_access - access for TLS clients by certificate fingerprint */
-
-static int check_ccert_access(SMTPD_STATE *state, const char *table,
+static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec,
const char *def_acl)
{
int result = SMTPD_CHECK_DUNNO;
#ifdef USE_TLS
const char *myname = "check_ccert_access";
int found;
+ const MAP_SEARCH *acl;
+ const char default_search[] = {
+ SMTPD_ACL_SEARCH_CODE_CERT_FPRINT,
+ SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT,
+ 0,
+ };
+ const char *search_order;
+
+ /*
+ * Look up the acl search list. If there is no ACL then we don't have a
+ * table to check.
+ */
+ if ((acl = map_search_lookup(acl_spec)) == 0) {
+ msg_warn("See earlier parsing error messages for '%s", acl_spec);
+ return (smtpd_check_reject(state, MAIL_ERROR_SOFTWARE, 451, "4.3.5",
+ "Server configuration error"));
+ }
+ if ((search_order = acl->search_order) == 0)
+ search_order = default_search;
+ if (msg_verbose)
+ msg_info("%s: search_order length=%d",
+ myname, strlen(search_order));
/*
* When directly checking the fingerprint, it is OK if the issuing CA is
* not trusted.
*/
if (TLS_CERT_IS_PRESENT(state->tls_context)) {
- int i;
- char *prints[2];
-
- prints[0] = state->tls_context->peer_cert_fprint;
- prints[1] = state->tls_context->peer_pkey_fprint;
-
- for (i = 0; i < 2; ++i) {
+ const char *action;
+ const char *match_this;
+ const char *known_action;
+
+ for (action = search_order; *action; action++) {
+ switch (*action) {
+ case SMTPD_ACL_SEARCH_CODE_CERT_FPRINT:
+ match_this = state->tls_context->peer_cert_fprint;
+ break;
+ case SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT:
+ match_this = state->tls_context->peer_pkey_fprint;
+ break;
+ case SMTPD_ACL_SEARCH_CODE_CERT_ISSUER:
+ match_this = state->tls_context->issuer_CN;
+ break;
+ case SMTPD_ACL_SEARCH_CODE_CERT_SUBJECT:
+ match_this = state->tls_context->peer_CN;
+ break;
+ default:
+ known_action = str_name_code(search_actions, *action);
+ if (known_action == 0)
+ msg_panic("%s: unknown action #%d in '%s'",
+ myname, *action, acl_spec);
+ msg_warn("%s: unexpected action '%s' in '%s'",
+ myname, known_action, acl_spec);
+ return (smtpd_check_reject(state, MAIL_ERROR_SOFTWARE,
+ 451, "4.3.5",
+ "Server configuration error"));
+ }
if (msg_verbose)
- msg_info("%s: %s", myname, prints[i]);
+ msg_info("%s: look up %s %s",
+ myname, str_name_code(search_actions, *action),
+ match_this);
/*
- * Regexp tables don't make sense for certificate fingerprints.
- * That may be so, but we can't ignore the entire
- * check_ccert_access request without logging a warning.
- *
* Log the peer CommonName when access is denied. Non-printable
* characters will be neutered by smtpd_check_reject(). The SMTP
* client name and address are always syslogged as part of a
- * "reject" event.
+ * "reject" event. XXX Should log the thing that is rejected
+ * (fingerprint etc.) or would that give away too much?
*/
- result = check_access(state, table, prints[i],
+ result = check_access(state, acl->map_type_name, match_this,
DICT_FLAG_NONE, &found,
state->tls_context->peer_CN,
SMTPD_NAME_CCERT, def_acl);
if (result != SMTPD_CHECK_DUNNO)
break;
}
+ } else {
+ if (msg_verbose)
+ msg_info("%s: no client certfificate", myname);
}
#endif
return (result);