Wish list:
+ Factor out the new get_nested_dict_name() function from
+ proxymap.c, make it a library function, and reuse it in
+ postconf_dbms.c.
+
Convert the proxymap protol into "server speaks first".
Fix code that still uses "long" for data_size and data_offset,
and that uses "%ld" in sscanf().
- A smart query services for live Postfix tables that outputs JSON?
+ A smart query service for live Postfix tables that outputs JSON?
proxy_read_maps needs a dedicated matcher that looks
inside pipemap:{}. Maybe steal some code from postconf.
(virtual_mailbox_maps or reject unverified_recipient), and
virtual_transport.
- In addition to the xxx_per_record_deadline, specify
- a minimum data rate for the DATA stage.
-
Make smtpd_relay_before_recipient_restrictions settable
in smtpd_checks tests.
requests for unsupported functionality; return an error status,
instead of terminating.
- Inline regexp/pcre/cidr table support. If the table name is
- a string inside {}, then split the string on comma (ignoring
- commas inside {}), write each resulting fragment as one line to
- a VSTRING buffer, and open that buffer as a memory file.
-
Add a robust dnssec_probe regression test (success and fail)
that does not break existing regression tests.
#include <htable.h>
#include <stringops.h>
#include <dict.h>
+#include <dict_pipe.h>
+#include <dict_union.h>
/* Global library. */
#define STR(x) vstring_str(x)
#define VSTREQ(x,y) (strcmp(STR(x),y) == 0)
+/* get_nested_dict_name - return nested dictionary name pointer, or null */
+
+static char *get_nested_dict_name(char *type_name)
+{
+ const struct {
+ const char *type_col;
+ ssize_t type_col_len
+ } *prefix, prefixes[] = {
+ DICT_TYPE_UNION ":", (sizeof(DICT_TYPE_UNION ":") - 1),
+ DICT_TYPE_PIPE ":", (sizeof(DICT_TYPE_PIPE ":") - 1),
+ };
+
+#define COUNT_OF(x) (sizeof(x)/sizeof((x)[0]))
+
+ for (prefix = prefixes; prefix < prefixes + COUNT_OF(prefixes); prefix++) {
+ if (strncmp(type_name, prefix->type_col, prefix->type_col_len) == 0)
+ return (type_name + prefix->type_col_len);
+ }
+ return (0);
+}
+
/* proxy_map_find - look up or open table */
static DICT *proxy_map_find(const char *map_type_name, int request_flags,
return (dict_open(map, open_flags, dict_flags));
}
-/* post_jail_init - initialization after privilege drop */
+/* authorize_proxied_maps - recursively authorize maps */
-static void post_jail_init(char *service_name, char **unused_argv)
+static void authorize_proxied_maps(char *bp)
{
const char *sep = CHARS_COMMA_SP;
const char *parens = CHARS_BRACE;
- char *saved_filter;
- char *bp;
char *type_name;
- /*
- * Are we proxy writer?
- */
- if (strcmp(service_name, MAIL_SERVICE_PROXYWRITE) == 0)
- proxy_writer = 1;
- else if (strcmp(service_name, MAIL_SERVICE_PROXYMAP) != 0)
- msg_fatal("service name must be one of %s or %s",
- MAIL_SERVICE_PROXYMAP, MAIL_SERVICE_PROXYMAP);
-
- /*
- * Pre-allocate buffers.
- */
- request = vstring_alloc(10);
- request_map = vstring_alloc(10);
- request_key = vstring_alloc(10);
- request_value = vstring_alloc(10);
- map_type_name_flags = vstring_alloc(10);
-
- /*
- * Prepare the pre-approved list of proxied tables.
- */
- saved_filter = bp = mystrdup(proxy_writer ? var_proxy_write_maps :
- var_proxy_read_maps);
- proxy_auth_maps = htable_create(13);
while ((type_name = mystrtokq(&bp, sep, parens)) != 0) {
+ char *nested_info;
+
/* Maybe { maptype:mapname attr=value... } */
if (*type_name == parens[0]) {
char *err;
if ((type_name = mystrtokq(&type_name, sep, parens)) == 0)
continue;
}
+ /* Recurse into nested map (pipemap, unionmap). */
+ if ((nested_info = get_nested_dict_name(type_name)) != 0) {
+ char *err;
+
+ if (*nested_info != parens[0])
+ continue;
+ /* Warn about blatant syntax error. */
+ if ((err = extpar(&nested_info, parens, EXTPAR_FLAG_NONE)) != 0) {
+ msg_warn("bad %s parameter value: %s",
+ PROXY_MAP_PARAM_NAME(proxy_writer), err);
+ myfree(err);
+ continue;
+ }
+ authorize_proxied_maps(nested_info);
+ continue;
+ }
if (strncmp(type_name, PROXY_COLON, PROXY_COLON_LEN))
continue;
do {
PROXY_MAP_PARAM_NAME(proxy_writer));
}
}
+}
+
+/* post_jail_init - initialization after privilege drop */
+
+static void post_jail_init(char *service_name, char **unused_argv)
+{
+ char *saved_filter;
+
+ /*
+ * Are we proxy writer?
+ */
+ if (strcmp(service_name, MAIL_SERVICE_PROXYWRITE) == 0)
+ proxy_writer = 1;
+ else if (strcmp(service_name, MAIL_SERVICE_PROXYMAP) != 0)
+ msg_fatal("service name must be one of %s or %s",
+ MAIL_SERVICE_PROXYMAP, MAIL_SERVICE_PROXYMAP);
+
+ /*
+ * Pre-allocate buffers.
+ */
+ request = vstring_alloc(10);
+ request_map = vstring_alloc(10);
+ request_key = vstring_alloc(10);
+ request_value = vstring_alloc(10);
+ map_type_name_flags = vstring_alloc(10);
+
+ /*
+ * Prepare the pre-approved list of proxied tables.
+ */
+ saved_filter = mystrdup(proxy_writer ? var_proxy_write_maps :
+ var_proxy_read_maps);
+ proxy_auth_maps = htable_create(13);
+ authorize_proxied_maps(saved_filter);
myfree(saved_filter);
/*