mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-29 13:18:12 +00:00
snapshot-20011119
This commit is contained in:
parent
bf47bce10b
commit
e36404ccca
@ -5600,7 +5600,7 @@ Apologies for any names omitted.
|
||||
|
||||
Feature: configurable parent domain matching for domain
|
||||
and hostname/address match lists: either .domain or the
|
||||
domain name itself.
|
||||
domain name itself. Files: util/match_ops.c util/match_list.c
|
||||
|
||||
Feature: added pretend-to-be-behind-PIX mode to the smtp-sink
|
||||
test program, in order to stress test some PIX bug workaround
|
||||
@ -5620,6 +5620,11 @@ Apologies for any names omitted.
|
||||
|
||||
20011115
|
||||
|
||||
Feature: mailbox_command_maps no longer requires that every
|
||||
user has an entry. If the user does not have a command
|
||||
entry, the local delivery agent tries the other delivery
|
||||
methods instead. File: local/mailbox.c.
|
||||
|
||||
Bugfix: reset the smtpd command transaction log between
|
||||
non-deliveries. File: smtpd/smtpd.c.
|
||||
|
||||
@ -5629,6 +5634,31 @@ Apologies for any names omitted.
|
||||
and eliminated one missing reset (Victor Duchovny, Morgan
|
||||
Stanley). File: smtpd/smtpd.c.
|
||||
|
||||
20011118
|
||||
|
||||
Cleanup: replaced unnecessary wrapper code by macros. Files:
|
||||
global/{string,domain,namadr}_list.[hc].
|
||||
|
||||
20011119
|
||||
|
||||
Feature: configurable parent domain matching strategy for
|
||||
transport map lookups. File: trivial-rewrite/transport.c.
|
||||
|
||||
New parent_domain_matches_subdomains parameter. This lists
|
||||
all the Postfix features where a domain name matches itself
|
||||
and all its subdomains (instead of requiring ".domain.name"
|
||||
for subdomain matches). Planning for future backwards
|
||||
compatibility :-) File: global/match_parent_style.c.
|
||||
|
||||
Workaround: simplified the PIX ".<CR><LF>" bug to always
|
||||
sleep for 10 seconds. File: smtp/smtp_proto.c.
|
||||
|
||||
20011120
|
||||
|
||||
Workaround: disable attribute string length restriction so
|
||||
that trivial-rewrite does not refuse to rewrite broken mail
|
||||
headers. Files: util/attr_scan*.c.
|
||||
|
||||
Open problems:
|
||||
|
||||
Medium: need in-process caching for map lookups. LDAP
|
||||
|
@ -1,7 +1,31 @@
|
||||
Snapshot 20011103 introduces a negligible amount of features and
|
||||
is all about revision of Postfix internals. With more than 70 pages
|
||||
of context diffs compared to the previous snapshot, this release
|
||||
is a baseline for upcoming feature changes.
|
||||
Incompatible changes with snapshot-20011121
|
||||
===========================================
|
||||
|
||||
The internal protocols have changed again, so you must "postfix
|
||||
reload" if upgrading from a previous release. The change is from
|
||||
base64 encoded strings to null-terminated strings.
|
||||
|
||||
Major changes with snapshot-20011121
|
||||
====================================
|
||||
|
||||
With host/domain name wildcard matching, the parent domain matching
|
||||
behavior is now configurable (that is, does "sub.domain.name" match
|
||||
the pattern "domain.name" or does it match the pattern ".domain.name").
|
||||
The new configuration parameter "parent_domain_matches_subdomains"
|
||||
specifies what Postfix features use the "sub.domain.name matches
|
||||
domain.name" approach. It is expected that eventually, all Postfix
|
||||
features will use ".domain.name" subdomain matching.
|
||||
|
||||
New "warn_if_reject" smtpd pseudo restriction that only warns if
|
||||
a restriction would reject mail.
|
||||
|
||||
Disgusting workaround for a well-known CISCO PIX firewall bug that
|
||||
causes the .<CR>LF> at the end of mail to be lost. The workaround
|
||||
has no effect for other mail deliveries.
|
||||
|
||||
mailbox_command_maps allows you to configure the external delivery
|
||||
command per user (local delivery agent only). This feature has
|
||||
precedence over mailbox_command and home_mailbox settings.
|
||||
|
||||
Major changes with snapshot-20011103
|
||||
====================================
|
||||
|
@ -80,4 +80,5 @@ flush.o: ../../include/maps.h
|
||||
flush.o: ../../include/domain_list.h
|
||||
flush.o: ../../include/match_list.h
|
||||
flush.o: ../../include/match_ops.h
|
||||
flush.o: ../../include/match_parent_style.h
|
||||
flush.o: ../../include/mail_server.h
|
||||
|
@ -160,6 +160,7 @@
|
||||
#include <mail_scan_dir.h>
|
||||
#include <maps.h>
|
||||
#include <domain_list.h>
|
||||
#include <match_parent_style.h>
|
||||
|
||||
/* Single server skeleton. */
|
||||
|
||||
@ -636,7 +637,8 @@ static void flush_service(VSTREAM *client_stream, char *unused_service,
|
||||
|
||||
static void pre_jail_init(char *unused_name, char **unused_argv)
|
||||
{
|
||||
flush_domains = domain_list_init(MATCH_FLAG_PARENT, var_fflush_domains);
|
||||
flush_domains = domain_list_init(match_parent_style(VAR_FFLUSH_DOMAINS),
|
||||
var_fflush_domains);
|
||||
}
|
||||
|
||||
/* main - pass control to the single-threaded skeleton */
|
||||
|
@ -19,7 +19,7 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \
|
||||
timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
|
||||
tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
|
||||
flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \
|
||||
verp_sender.c
|
||||
verp_sender.c match_parent_style.c
|
||||
OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
|
||||
debug_peer.o debug_process.o defer.o deliver_completed.o \
|
||||
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
|
||||
@ -40,7 +40,7 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
|
||||
timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
|
||||
tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
|
||||
flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \
|
||||
verp_sender.o
|
||||
verp_sender.o match_parent_style.o
|
||||
HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
|
||||
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
|
||||
deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
|
||||
@ -56,7 +56,8 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
|
||||
recipient_list.h record.h resolve_clnt.h resolve_local.h \
|
||||
rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
|
||||
sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
|
||||
mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h
|
||||
mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \
|
||||
match_parent_style.h
|
||||
TESTSRC = rec2stream.c stream2rec.c recdump.c
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
@ -321,6 +322,7 @@ debug_peer.o: namadr_list.h
|
||||
debug_peer.o: ../../include/match_list.h
|
||||
debug_peer.o: ../../include/match_ops.h
|
||||
debug_peer.o: debug_peer.h
|
||||
debug_peer.o: match_parent_style.h
|
||||
debug_process.o: debug_process.c
|
||||
debug_process.o: ../../include/sys_defs.h
|
||||
debug_process.o: ../../include/msg.h
|
||||
@ -723,6 +725,13 @@ mark_corrupt.o: ../../include/vbuf.h
|
||||
mark_corrupt.o: mail_queue.h
|
||||
mark_corrupt.o: ../../include/vstring.h
|
||||
mark_corrupt.o: mark_corrupt.h
|
||||
match_parent_style.o: match_parent_style.c
|
||||
match_parent_style.o: ../../include/sys_defs.h
|
||||
match_parent_style.o: string_list.h
|
||||
match_parent_style.o: ../../include/match_list.h
|
||||
match_parent_style.o: ../../include/match_ops.h
|
||||
match_parent_style.o: mail_params.h
|
||||
match_parent_style.o: match_parent_style.h
|
||||
mbox_conf.o: mbox_conf.c
|
||||
mbox_conf.o: ../../include/sys_defs.h
|
||||
mbox_conf.o: ../../include/name_mask.h
|
||||
@ -942,6 +951,7 @@ resolve_local.o: ../../include/match_ops.h
|
||||
resolve_local.o: mail_params.h
|
||||
resolve_local.o: own_inet_addr.h
|
||||
resolve_local.o: resolve_local.h
|
||||
resolve_local.o: match_parent_style.h
|
||||
rewrite_clnt.o: rewrite_clnt.c
|
||||
rewrite_clnt.o: ../../include/sys_defs.h
|
||||
rewrite_clnt.o: ../../include/msg.h
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include <mail_params.h>
|
||||
#include <namadr_list.h>
|
||||
#include <debug_peer.h>
|
||||
#include <match_parent_style.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@ -97,8 +98,9 @@ void debug_peer_init(void)
|
||||
* Finally.
|
||||
*/
|
||||
if (*var_debug_peer_list)
|
||||
debug_peer_list = namadr_list_init(MATCH_FLAG_PARENT,
|
||||
var_debug_peer_list);
|
||||
debug_peer_list =
|
||||
namadr_list_init(match_parent_style(VAR_DEBUG_PEER_LIST),
|
||||
var_debug_peer_list);
|
||||
}
|
||||
|
||||
/* debug_peer_check - see if this peer needs verbose logging */
|
||||
|
@ -38,11 +38,8 @@
|
||||
/* .RS
|
||||
/* .IP MATCH_FLAG_PARENT
|
||||
/* The hostname pattern foo.com matches itself and any name below
|
||||
/* the domain foo.com.
|
||||
/* .IP MATCH_FLAG_DOTPARENT
|
||||
/* The hostname pattern foo.com matches itself only.
|
||||
/* The hostname pattern .foo.com matches any name below the domain
|
||||
/* foo.com.
|
||||
/* the domain foo.com. If this flag is cleared, foo.com matches itself
|
||||
/* only, and .foo.com matches any name below the domain foo.com.
|
||||
/* .RE
|
||||
/* Specify MATCH_FLAG_NONE to request none of the above.
|
||||
/* The second argument is a list of domain patterns, or the name of
|
||||
@ -112,7 +109,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
if (argc != optind + 2)
|
||||
usage(argv[0]);
|
||||
list = domain_list_init(argv[optind]);
|
||||
list = domain_list_init(MATCH_FLAG_PARENT, argv[optind]);
|
||||
host = argv[optind + 1];
|
||||
vstream_printf("%s: %s\n", host, domain_list_match(list, host) ?
|
||||
"YES" : "NO");
|
||||
|
@ -64,6 +64,7 @@
|
||||
/* char *var_mynetworks_style;
|
||||
/* char *var_verp_delims;
|
||||
/* char *var_verp_filter;
|
||||
/* char *var_par_dom_match;
|
||||
/*
|
||||
/* char *var_import_environ;
|
||||
/* char *var_export_environ;
|
||||
@ -187,6 +188,7 @@ char *var_mynetworks_style;
|
||||
char *var_verp_delims;
|
||||
char *var_verp_filter;
|
||||
int var_in_flow_delay;
|
||||
char *var_par_dom_match;
|
||||
|
||||
char *var_import_environ;
|
||||
char *var_export_environ;
|
||||
@ -312,6 +314,7 @@ void mail_params_init()
|
||||
VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0,
|
||||
VAR_VERP_DELIMS, DEF_VERP_DELIMS, &var_verp_delims, 2, 2,
|
||||
VAR_VERP_FILTER, DEF_VERP_FILTER, &var_verp_filter, 1, 0,
|
||||
VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match, 0, 0,
|
||||
0,
|
||||
};
|
||||
static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
|
||||
|
@ -1321,6 +1321,21 @@ extern bool var_verp_bounce_off;
|
||||
#define DEF_IN_FLOW_DELAY "1s"
|
||||
extern int var_in_flow_delay;
|
||||
|
||||
/*
|
||||
* Backwards compatibility: foo.com matches itself and names below foo.com.
|
||||
*/
|
||||
#define VAR_PAR_DOM_MATCH "parent_domain_matches_subdomains"
|
||||
#define DEF_PAR_DOM_MATCH VAR_DEBUG_PEER_LIST "," \
|
||||
VAR_FFLUSH_DOMAINS "," \
|
||||
VAR_MYNETWORKS "," \
|
||||
VAR_PERM_MX_NETWORKS "," \
|
||||
VAR_QMQPD_CLIENTS "," \
|
||||
VAR_RELAY_DOMAINS "," \
|
||||
SMTPD_ACCESS_MAPS
|
||||
extern char *var_par_dom_match;
|
||||
|
||||
#define SMTPD_ACCESS_MAPS "smtpd_access_maps"
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
|
@ -15,7 +15,7 @@
|
||||
* Version of this program.
|
||||
*/
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "Snapshot-20011118"
|
||||
#define DEF_MAIL_VERSION "Snapshot-20011119"
|
||||
extern char *var_mail_version;
|
||||
|
||||
/* LICENSE
|
||||
|
72
postfix/src/global/match_parent_style.c
Normal file
72
postfix/src/global/match_parent_style.c
Normal file
@ -0,0 +1,72 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* match_parent_style 3
|
||||
/* SUMMARY
|
||||
/* parent domain matching control
|
||||
/* SYNOPSIS
|
||||
/* #include <match_parent_style.h>
|
||||
/*
|
||||
/* int match_parent_style(name)
|
||||
/* const char *name;
|
||||
/* DESCRIPTION
|
||||
/* This module queries configuration parameters for the policy that
|
||||
/* controls how wild-card parent domain names are used by various
|
||||
/* postfix lookup mechanisms.
|
||||
/*
|
||||
/* match_parent_style() looks up "name" in the
|
||||
/* parent_domain_matches_subdomain configuration parameter
|
||||
/* and returns either MATCH_FLAG_PARENT or MATCH_PARENT_NONE.
|
||||
/* DIAGNOSTICS
|
||||
/* Fatal error: out of memory, name listed under both parent wild card
|
||||
/* matching policies.
|
||||
/* SEE ALSO
|
||||
/* string_list(3) plain string matching
|
||||
/* domain_list(3) match host name patterns
|
||||
/* namadr_list(3) match host name/address patterns
|
||||
/* 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 <sys_defs.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <string_list.h>
|
||||
#include <mail_params.h>
|
||||
#include <match_parent_style.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
static STRING_LIST *match_par_dom_list;
|
||||
|
||||
int match_parent_style(const char *name)
|
||||
{
|
||||
int result;
|
||||
|
||||
/*
|
||||
* Initialize on the fly.
|
||||
*/
|
||||
if (match_par_dom_list == 0)
|
||||
match_par_dom_list =
|
||||
string_list_init(MATCH_FLAG_NONE, var_par_dom_match);
|
||||
|
||||
/*
|
||||
* Look up the parent domain matching policy.
|
||||
*/
|
||||
if (string_list_match(match_par_dom_list, name))
|
||||
result = MATCH_FLAG_PARENT;
|
||||
else
|
||||
result = 0;
|
||||
return (result);
|
||||
}
|
35
postfix/src/global/match_parent_style.h
Normal file
35
postfix/src/global/match_parent_style.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef _MATCH_PARENT_STYLE_H_INCLUDED_
|
||||
#define _MATCH_PARENT_STYLE_H_INCLUDED_
|
||||
|
||||
/*++
|
||||
/* NAME
|
||||
/* match_parent_style 3h
|
||||
/* SUMMARY
|
||||
/* parent domain matching control
|
||||
/* SYNOPSIS
|
||||
/* #include <match_parent_style.h>
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
#include <match_ops.h>
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern int match_parent_style(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
|
@ -39,16 +39,13 @@
|
||||
/* pattern. The matching process is case insensitive.
|
||||
/*
|
||||
/* namadr_list_init() performs initializations. The first
|
||||
/* argument is the bit-wise OR of zero or mor of the
|
||||
/* argument is the bit-wise OR of zero or more of the
|
||||
/* following:
|
||||
/* .RS
|
||||
/* .IP MATCH_FLAG_PARENT
|
||||
/* The hostname pattern foo.com matches itself and any name below
|
||||
/* the domain foo.com.
|
||||
/* .IP MATCH_FLAG_DOTPARENT
|
||||
/* The hostname pattern foo.com matches itself only.
|
||||
/* The hostname pattern .foo.com matches any name below the domain
|
||||
/* foo.com.
|
||||
/* The hostname pattern foo.com matches itself and any name below
|
||||
/* the domain foo.com. If this flag is cleared, foo.com matches itself
|
||||
/* only, and .foo.com matches any name below the domain foo.com.
|
||||
/* .RE
|
||||
/* Specify MATCH_FLAG_NONE to request none of the above.
|
||||
/* The second argument is a list of patterns, or the absolute
|
||||
@ -109,22 +106,22 @@ main(int argc, char **argv)
|
||||
msg_vstream_init(argv[0], VSTREAM_ERR);
|
||||
|
||||
while ((ch = GETOPT(argc, argv, "v")) > 0) {
|
||||
switch (ch) {
|
||||
case 'v':
|
||||
msg_verbose++;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
switch (ch) {
|
||||
case 'v':
|
||||
msg_verbose++;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
if (argc != optind + 3)
|
||||
usage(argv[0]);
|
||||
list = namadr_list_init(argv[optind]);
|
||||
usage(argv[0]);
|
||||
list = namadr_list_init(MATCH_FLAG_PARENT, argv[optind]);
|
||||
host = argv[optind + 1];
|
||||
addr = argv[optind + 2];
|
||||
vstream_printf("%s/%s: %s\n", host, addr,
|
||||
namadr_list_match(list, host, addr) ?
|
||||
"YES" : "NO");
|
||||
namadr_list_match(list, host, addr) ?
|
||||
"YES" : "NO");
|
||||
vstream_fflush(VSTREAM_OUT);
|
||||
namadr_list_free(list);
|
||||
}
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include <mail_params.h>
|
||||
#include <own_inet_addr.h>
|
||||
#include <resolve_local.h>
|
||||
#include <match_parent_style.h>
|
||||
|
||||
/* Application-specific */
|
||||
|
||||
|
@ -98,7 +98,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
if (argc != optind + 2)
|
||||
usage(argv[0]);
|
||||
list = string_list_init(argv[optind]);
|
||||
list = string_list_init(MATCH_FLAG_NONE, argv[optind]);
|
||||
string = argv[optind + 1];
|
||||
vstream_printf("%s: %s\n", string, string_list_match(list, string) ?
|
||||
"YES" : "NO");
|
||||
|
@ -92,6 +92,7 @@ qmqpd.o: ../../include/namadr_list.h
|
||||
qmqpd.o: ../../include/match_list.h
|
||||
qmqpd.o: ../../include/match_ops.h
|
||||
qmqpd.o: ../../include/quote_822_local.h
|
||||
qmqpd.o: ../../include/match_parent_style.h
|
||||
qmqpd.o: ../../include/mail_server.h
|
||||
qmqpd.o: qmqpd.h
|
||||
qmqpd_peer.o: qmqpd_peer.c
|
||||
|
@ -135,6 +135,7 @@
|
||||
#include <mail_stream.h>
|
||||
#include <namadr_list.h>
|
||||
#include <quote_822_local.h>
|
||||
#include <match_parent_style.h>
|
||||
|
||||
/* Single-threaded server skeleton. */
|
||||
|
||||
@ -643,7 +644,9 @@ static void pre_accept(char *unused_name, char **unused_argv)
|
||||
static void pre_jail_init(char *unused_name, char **unused_argv)
|
||||
{
|
||||
debug_peer_init();
|
||||
qmqpd_clients = namadr_list_init(MATCH_FLAG_PARENT, var_qmqpd_clients);
|
||||
qmqpd_clients =
|
||||
namadr_list_init(match_parent_style(VAR_QMQPD_CLIENTS),
|
||||
var_qmqpd_clients);
|
||||
}
|
||||
|
||||
/* main - the main program */
|
||||
|
@ -663,8 +663,7 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
smtp_fputs("", 0, session->stream);
|
||||
if ((state->features & SMTP_FEATURE_MAYBEPIX) != 0) {
|
||||
vstream_fflush(session->stream);/* hurts performance */
|
||||
sock_empty_wait(vstream_fileno(session->stream),
|
||||
session->stream->timeout / 2);
|
||||
sleep(10); /* not to mention this */
|
||||
}
|
||||
if (vstream_ferror(state->src))
|
||||
msg_fatal("queue file read error");
|
||||
|
@ -189,6 +189,7 @@ smtpd_check.o: ../../include/own_inet_addr.h
|
||||
smtpd_check.o: ../../include/mail_conf.h
|
||||
smtpd_check.o: ../../include/maps.h
|
||||
smtpd_check.o: ../../include/mail_addr_find.h
|
||||
smtpd_check.o: ../../include/match_parent_style.h
|
||||
smtpd_check.o: smtpd.h
|
||||
smtpd_check.o: ../../include/mail_stream.h
|
||||
smtpd_check.o: smtpd_sasl_glue.h
|
||||
|
@ -289,6 +289,7 @@
|
||||
#include <mail_conf.h>
|
||||
#include <maps.h>
|
||||
#include <mail_addr_find.h>
|
||||
#include <match_parent_style.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@ -339,6 +340,11 @@ static DOMAIN_LIST *relay_domains;
|
||||
static NAMADR_LIST *mynetworks;
|
||||
static NAMADR_LIST *perm_mx_networks;
|
||||
|
||||
/*
|
||||
* How to do parent domain wildcard matching, if any.
|
||||
*/
|
||||
static int access_parent_style;
|
||||
|
||||
/*
|
||||
* Pre-parsed restriction lists.
|
||||
*/
|
||||
@ -456,10 +462,9 @@ static int has_required(ARGV *restrictions, char **required)
|
||||
rest += 1;
|
||||
continue;
|
||||
}
|
||||
for (reqd = required; *reqd; reqd++) {
|
||||
for (reqd = required; *reqd; reqd++)
|
||||
if (strcmp(*rest, *reqd) == 0)
|
||||
return (1);
|
||||
}
|
||||
if ((expansion = (ARGV *) htable_find(smtpd_rest_classes, *rest)) != 0)
|
||||
if (has_required(expansion, required))
|
||||
return (1);
|
||||
@ -486,8 +491,8 @@ static void fail_required(char *name, char **required)
|
||||
*/
|
||||
example = vstring_alloc(10);
|
||||
for (reqd = required; *reqd; reqd++)
|
||||
vstring_sprintf_append(example, "%s%s", *reqd,
|
||||
reqd[1] == 0 ? "" : reqd[2] == 0 ? " or " : ", ");
|
||||
vstring_sprintf_append(example, "%s%s", *reqd,
|
||||
reqd[1] == 0 ? "" : reqd[2] == 0 ? " or " : ", ");
|
||||
msg_fatal("parameter \"%s\": specify at least one working instance of: %s",
|
||||
name, STR(example));
|
||||
}
|
||||
@ -510,9 +515,15 @@ void smtpd_check_init(void)
|
||||
/*
|
||||
* Pre-open access control lists before going to jail.
|
||||
*/
|
||||
mynetworks = namadr_list_init(MATCH_FLAG_PARENT, var_mynetworks);
|
||||
relay_domains = domain_list_init(MATCH_FLAG_PARENT, var_relay_domains);
|
||||
perm_mx_networks = namadr_list_init(MATCH_FLAG_PARENT, var_perm_mx_networks);
|
||||
mynetworks =
|
||||
namadr_list_init(match_parent_style(VAR_MYNETWORKS),
|
||||
var_mynetworks);
|
||||
relay_domains =
|
||||
domain_list_init(match_parent_style(VAR_RELAY_DOMAINS),
|
||||
var_relay_domains);
|
||||
perm_mx_networks =
|
||||
namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS),
|
||||
var_perm_mx_networks);
|
||||
|
||||
/*
|
||||
* Pre-parse and pre-open the recipient maps.
|
||||
@ -530,6 +541,8 @@ void smtpd_check_init(void)
|
||||
relocated_maps = maps_create(VAR_RELOCATED_MAPS, var_relocated_maps,
|
||||
DICT_FLAG_LOCK);
|
||||
|
||||
access_parent_style = match_parent_style(SMTPD_ACCESS_MAPS);
|
||||
|
||||
/*
|
||||
* error_text is used for returning error responses.
|
||||
*/
|
||||
@ -1562,7 +1575,7 @@ static int check_domain_access(SMTPD_STATE *state, const char *table,
|
||||
|
||||
if ((dict = dict_handle(table)) == 0)
|
||||
msg_panic("%s: dictionary not found: %s", myname, table);
|
||||
for (name = low_domain; /* void */ ; name = next + 1) {
|
||||
for (name = low_domain; /* void */ ; name = next) {
|
||||
if (flags == 0 || (flags & dict->flags) != 0) {
|
||||
if ((value = dict_get(dict, name)) != 0)
|
||||
CHK_DOMAIN_RETURN(check_table_result(state, table, value,
|
||||
@ -1571,8 +1584,10 @@ static int check_domain_access(SMTPD_STATE *state, const char *table,
|
||||
if (dict_errno != 0)
|
||||
msg_fatal("%s: table lookup problem", table);
|
||||
}
|
||||
if ((next = strchr(name, '.')) == 0)
|
||||
if ((next = strchr(name + 1, '.')) == 0)
|
||||
break;
|
||||
if (access_parent_style == MATCH_FLAG_PARENT)
|
||||
next += 1;
|
||||
flags = PARTIAL;
|
||||
}
|
||||
CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO, MISSED);
|
||||
@ -2456,6 +2471,7 @@ char *var_virt_mailbox_maps;
|
||||
char *var_relocated_maps;
|
||||
char *var_local_rcpt_maps;
|
||||
char *var_perm_mx_networks;
|
||||
char *var_par_dom_match;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
@ -2477,7 +2493,8 @@ static STRING_TABLE string_table[] = {
|
||||
VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps,
|
||||
VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocated_maps,
|
||||
VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps,
|
||||
VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks, 0, 0,
|
||||
VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks,
|
||||
VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match,
|
||||
0,
|
||||
};
|
||||
|
||||
@ -2815,13 +2832,17 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if (strcasecmp(args->argv[0], "mynetworks") == 0) {
|
||||
namadr_list_free(mynetworks);
|
||||
mynetworks = namadr_list_init(MATCH_FLAG_PARENT, args->argv[1]);
|
||||
mynetworks =
|
||||
namadr_list_init(match_parent_style(VAR_MYNETWORKS),
|
||||
args->argv[1]);
|
||||
resp = 0;
|
||||
break;
|
||||
}
|
||||
if (strcasecmp(args->argv[0], "relay_domains") == 0) {
|
||||
domain_list_free(relay_domains);
|
||||
relay_domains = domain_list_init(MATCH_FLAG_PARENT, args->argv[1]);
|
||||
relay_domains =
|
||||
domain_list_init(match_parent_style(VAR_RELAY_DOMAINS),
|
||||
args->argv[1]);
|
||||
resp = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -62,12 +62,14 @@
|
||||
|
||||
#include <mail_params.h>
|
||||
#include <maps.h>
|
||||
#include <match_parent_style.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "transport.h"
|
||||
|
||||
static MAPS *transport_path;
|
||||
static int transport_match_parent_style;
|
||||
|
||||
/* transport_init - pre-jail initialization */
|
||||
|
||||
@ -77,6 +79,7 @@ void transport_init(void)
|
||||
msg_panic("transport_init: repeated call");
|
||||
transport_path = maps_create("transport", var_transport_maps,
|
||||
DICT_FLAG_LOCK);
|
||||
transport_match_parent_style = match_parent_style(VAR_TRANSPORT_MAPS);
|
||||
}
|
||||
|
||||
/* transport_lookup - map a transport domain */
|
||||
@ -85,6 +88,7 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop)
|
||||
{
|
||||
char *low_domain = lowercase(mystrdup(domain));
|
||||
const char *name;
|
||||
const char *next;
|
||||
const char *value;
|
||||
const char *host;
|
||||
char *saved_value;
|
||||
@ -113,7 +117,7 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop)
|
||||
* Specify if a key is partial or full, to avoid matching partial keys with
|
||||
* regular expressions.
|
||||
*/
|
||||
for (name = low_domain; name != 0; name = strchr(name + 1, '.')) {
|
||||
for (name = low_domain; /* void */; name = next) {
|
||||
if ((value = maps_find(transport_path, name, maps_flag)) != 0) {
|
||||
saved_value = mystrdup(value);
|
||||
if ((host = split_at(saved_value, ':')) == 0 || *host == 0)
|
||||
@ -132,6 +136,10 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop)
|
||||
} else if (dict_errno != 0) {
|
||||
msg_fatal("transport table lookup problem");
|
||||
}
|
||||
if ((next = strchr(name + 1, '.')) == 0)
|
||||
break;
|
||||
if (transport_match_parent_style == MATCH_FLAG_PARENT)
|
||||
next++;
|
||||
maps_flag = PARTIAL;
|
||||
}
|
||||
myfree(low_domain);
|
||||
|
@ -1,227 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* attr_print 3
|
||||
/* SUMMARY
|
||||
/* send attributes over byte stream
|
||||
/* SYNOPSIS
|
||||
/* #include <attr.h>
|
||||
/*
|
||||
/* int attr_print(fp, flags, type, name, ...)
|
||||
/* VSTREAM fp;
|
||||
/* int flags;
|
||||
/* int type;
|
||||
/* char *name;
|
||||
/*
|
||||
/* int attr_vprint(fp, flags, ap)
|
||||
/* VSTREAM fp;
|
||||
/* int flags;
|
||||
/* va_list ap;
|
||||
/* DESCRIPTION
|
||||
/* attr_print() takes zero or more (name, value) simple attributes
|
||||
/* or (name, count, value) list attributes, and converts its input
|
||||
/* to a byte stream that can be recovered with attr_scan(). The stream
|
||||
/* is not flushed.
|
||||
/*
|
||||
/* attr_vprint() provides an alternate interface that is convenient
|
||||
/* for calling from within variadoc functions.
|
||||
/*
|
||||
/* Attributes are sent in the requested order as specified with the
|
||||
/* attr_print() argument list. This routine satisfies the formatting
|
||||
/* rules as outlined in attr_scan(3).
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP fp
|
||||
/* Stream to write the result to.
|
||||
/* .IP flags
|
||||
/* The bit-wise OR of zero or more of the following.
|
||||
/* .RS
|
||||
/* .IP ATTR_FLAG_MORE
|
||||
/* After sending the requested attributes, leave the output stream in
|
||||
/* a state that is usable for more attribute sending operations on
|
||||
/* the same output attribute list.
|
||||
/* By default, attr_print() automatically appends an attribute list
|
||||
/* terminator when it has sent the last requested attribute.
|
||||
/* .RE
|
||||
/* .IP type
|
||||
/* The type determines the arguments that follow.
|
||||
/* .RS
|
||||
/* .IP "ATTR_TYPE_NUM (char *, int)"
|
||||
/* This argument is followed by an attribute name and an integer.
|
||||
/* .IP "ATTR_TYPE_STR (char *, char *)"
|
||||
/* This argument is followed by an attribute name and a null-terminated
|
||||
/* string.
|
||||
/* .IP "ATTR_TYPE_HASH (HTABLE *)"
|
||||
/* The content of the hash table is sent as a sequence of string-valued
|
||||
/* attributes with names equal to the hash table lookup key.
|
||||
/* .IP ATTR_TYPE_END
|
||||
/* This terminates the attribute list.
|
||||
/* .RE
|
||||
/* DIAGNOSTICS
|
||||
/* The result value is 0 in case of success, VSTREAM_EOF in case
|
||||
/* of trouble.
|
||||
/*
|
||||
/* Panic: interface violation. All system call errors are fatal.
|
||||
/* SEE ALSO
|
||||
/* attr_scan(3) recover attributes from byte stream
|
||||
/* 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 <sys_defs.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <mymalloc.h>
|
||||
#include <vstream.h>
|
||||
#include <htable.h>
|
||||
#include <base64_code.h>
|
||||
#include <attr.h>
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
/* attr_print_str - encode and send attribute information */
|
||||
|
||||
static void attr_print_str(VSTREAM *fp, const char *str, int len)
|
||||
{
|
||||
static VSTRING *base64_buf;
|
||||
|
||||
if (base64_buf == 0)
|
||||
base64_buf = vstring_alloc(10);
|
||||
|
||||
base64_encode(base64_buf, str, len);
|
||||
vstream_fputs(STR(base64_buf), fp);
|
||||
}
|
||||
|
||||
static void attr_print_num(VSTREAM *fp, unsigned num)
|
||||
{
|
||||
static VSTRING *plain;
|
||||
|
||||
if (plain == 0)
|
||||
plain = vstring_alloc(10);
|
||||
|
||||
vstring_sprintf(plain, "%u", num);
|
||||
attr_print_str(fp, STR(plain), LEN(plain));
|
||||
}
|
||||
|
||||
/* attr_vprint - send attribute list to stream */
|
||||
|
||||
int attr_vprint(VSTREAM *fp, int flags, va_list ap)
|
||||
{
|
||||
const char *myname = "attr_print";
|
||||
int attr_type;
|
||||
char *attr_name;
|
||||
unsigned int_val;
|
||||
char *str_val;
|
||||
HTABLE_INFO **ht_info_list;
|
||||
HTABLE_INFO **ht;
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (flags & ~ATTR_FLAG_ALL)
|
||||
msg_panic("%s: bad flags: 0x%x", myname, flags);
|
||||
|
||||
/*
|
||||
* Iterate over all (type, name, value) triples, and produce output on
|
||||
* the fly.
|
||||
*/
|
||||
while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) {
|
||||
switch (attr_type) {
|
||||
case ATTR_TYPE_NUM:
|
||||
attr_name = va_arg(ap, char *);
|
||||
attr_print_str(fp, attr_name, strlen(attr_name));
|
||||
int_val = va_arg(ap, int);
|
||||
VSTREAM_PUTC(':', fp);
|
||||
attr_print_num(fp, (unsigned) int_val);
|
||||
if (msg_verbose)
|
||||
msg_info("send attr %s = %u", attr_name, int_val);
|
||||
break;
|
||||
case ATTR_TYPE_STR:
|
||||
attr_name = va_arg(ap, char *);
|
||||
attr_print_str(fp, attr_name, strlen(attr_name));
|
||||
str_val = va_arg(ap, char *);
|
||||
VSTREAM_PUTC(':', fp);
|
||||
attr_print_str(fp, str_val, strlen(str_val));
|
||||
if (msg_verbose)
|
||||
msg_info("send attr %s = %s", attr_name, str_val);
|
||||
break;
|
||||
case ATTR_TYPE_HASH:
|
||||
ht_info_list = htable_list(va_arg(ap, HTABLE *));
|
||||
for (ht = ht_info_list; *ht; ht++) {
|
||||
attr_print_str(fp, ht[0]->key, strlen(ht[0]->key));
|
||||
VSTREAM_PUTC(':', fp);
|
||||
attr_print_str(fp, ht[0]->value, strlen(ht[0]->value));
|
||||
if (msg_verbose)
|
||||
msg_info("send attr name %s value %s",
|
||||
ht[0]->key, ht[0]->value);
|
||||
if (ht[1] != 0)
|
||||
VSTREAM_PUTC('\n', fp);
|
||||
}
|
||||
myfree((char *) ht_info_list);
|
||||
break;
|
||||
default:
|
||||
msg_panic("%s: unknown type code: %d", myname, attr_type);
|
||||
}
|
||||
VSTREAM_PUTC('\n', fp);
|
||||
}
|
||||
if ((flags & ATTR_FLAG_MORE) == 0)
|
||||
VSTREAM_PUTC('\n', fp);
|
||||
return (vstream_ferror(fp));
|
||||
}
|
||||
|
||||
int attr_print(VSTREAM *fp, int flags,...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, flags);
|
||||
ret = attr_vprint(fp, flags, ap);
|
||||
va_end(ap);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
/*
|
||||
* Proof of concept test program. Mirror image of the attr_scan test
|
||||
* program.
|
||||
*/
|
||||
#include <msg_vstream.h>
|
||||
|
||||
int main(int unused_argc, char **argv)
|
||||
{
|
||||
HTABLE *table = htable_create(1);
|
||||
|
||||
msg_vstream_init(argv[0], VSTREAM_ERR);
|
||||
msg_verbose = 1;
|
||||
htable_enter(table, "foo-name", mystrdup("foo-value"));
|
||||
htable_enter(table, "bar-name", mystrdup("bar-value"));
|
||||
attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711,
|
||||
ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee",
|
||||
ATTR_TYPE_HASH, table,
|
||||
ATTR_TYPE_END);
|
||||
attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711,
|
||||
ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee",
|
||||
ATTR_TYPE_END);
|
||||
if (vstream_fflush(VSTREAM_OUT) != 0)
|
||||
msg_fatal("write error: %m");
|
||||
|
||||
htable_free(table, myfree);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,460 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* attr_scan 3
|
||||
/* SUMMARY
|
||||
/* recover attributes from byte stream
|
||||
/* SYNOPSIS
|
||||
/* #include <attr.h>
|
||||
/*
|
||||
/* int attr_scan(fp, flags, type, name, ...)
|
||||
/* VSTREAM fp;
|
||||
/* int flags;
|
||||
/* int type;
|
||||
/* char *name;
|
||||
/*
|
||||
/* int attr_vscan(fp, flags, ap)
|
||||
/* VSTREAM fp;
|
||||
/* int flags;
|
||||
/* va_list ap;
|
||||
/* DESCRIPTION
|
||||
/* attr_scan() takes zero or more (name, value) request attributes
|
||||
/* and recovers the attribute values from the byte stream that was
|
||||
/* possibly generated by attr_print().
|
||||
/*
|
||||
/* attr_vscan() provides an alternative interface that is convenient
|
||||
/* for calling from within a variadic function.
|
||||
/*
|
||||
/* The input stream is formatted as follows, where (item)* stands
|
||||
/* for zero or more instances of the specified item, and where
|
||||
/* (item1 | item2) stands for choice:
|
||||
/*
|
||||
/* .in +5
|
||||
/* attr-list :== simple-attr* newline
|
||||
/* .br
|
||||
/* simple-attr :== attr-name colon attr-value newline
|
||||
/* .br
|
||||
/* attr-name :== any base64 encoded string
|
||||
/* .br
|
||||
/* attr-value :== any base64 encoded string
|
||||
/* .br
|
||||
/* colon :== the ASCII colon character
|
||||
/* .br
|
||||
/* newline :== the ASCII newline character
|
||||
/* .in
|
||||
/*
|
||||
/* All attribute names and attribute values are sent as base64-encoded
|
||||
/* strings. Each base64 encoding must be no longer than 2*var_line_limit
|
||||
/* characters. The formatting rules aim to make implementations in PERL
|
||||
/* and other languages easy.
|
||||
/*
|
||||
/* Normally, attributes must be received in the sequence as specified with
|
||||
/* the attr_scan() argument list. The input stream may contain additional
|
||||
/* attributes at any point in the input stream, including additional
|
||||
/* instances of requested attributes.
|
||||
/*
|
||||
/* Additional input attributes or input attribute instances are silently
|
||||
/* skipped over, unless the ATTR_FLAG_EXTRA processing flag is specified
|
||||
/* (see below). This allows for some flexibility in the evolution of
|
||||
/* protocols while still providing the option of being strict where
|
||||
/* this is desirable.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP fp
|
||||
/* Stream to recover the input attributes from.
|
||||
/* .IP flags
|
||||
/* The bit-wise OR of zero or more of the following.
|
||||
/* .RS
|
||||
/* .IP ATTR_FLAG_MISSING
|
||||
/* Log a warning when the input attribute list terminates before all
|
||||
/* requested attributes are recovered. It is always an error when the
|
||||
/* input stream ends without the newline attribute list terminator.
|
||||
/* .IP ATTR_FLAG_EXTRA
|
||||
/* Log a warning and stop attribute recovery when the input stream
|
||||
/* contains an attribute that was not requested. This includes the
|
||||
/* case of additional instances of a requested attribute.
|
||||
/* .IP ATTR_FLAG_MORE
|
||||
/* After recovering the requested attributes, leave the input stream
|
||||
/* in a state that is usable for more attr_scan() operations from the
|
||||
/* same input attribute list.
|
||||
/* By default, attr_scan() skips forward past the input attribute list
|
||||
/* terminator.
|
||||
/* .IP ATTR_FLAG_STRICT
|
||||
/* For convenience, this value combines both ATTR_FLAG_MISSING and
|
||||
/* ATTR_FLAG_EXTRA.
|
||||
/* .IP ATTR_FLAG_NONE
|
||||
/* For convenience, this value requests none of the above.
|
||||
/* .RE
|
||||
/* .IP type
|
||||
/* The type argument determines the arguments that follow.
|
||||
/* .RS
|
||||
/* .IP "ATTR_TYPE_NUM (char *, int *)"
|
||||
/* This argument is followed by an attribute name and an integer pointer.
|
||||
/* .IP "ATTR_TYPE_STR (char *, VSTRING *)"
|
||||
/* This argument is followed by an attribute name and a VSTRING pointer.
|
||||
/* .IP "ATTR_TYPE_HASH (HTABLE *)"
|
||||
/* All further input attributes are processed as string attributes.
|
||||
/* No specific attribute sequence is enforced.
|
||||
/* All attributes up to the attribute list terminator are read,
|
||||
/* but only the first instance of each attribute is stored.
|
||||
/* .sp
|
||||
/* The attribute string values are stored in the hash table under
|
||||
/* keys equal to the attribute name (obtained from the input stream).
|
||||
/* Values from the input stream are added to the hash table. Existing
|
||||
/* hash table entries are not replaced.
|
||||
/* .sp
|
||||
/* N.B. This construct must be followed by an ATTR_TYPE_END argument.
|
||||
/* .IP ATTR_TYPE_END
|
||||
/* This argument terminates the requested attribute list.
|
||||
/* .RE
|
||||
/* BUGS
|
||||
/* ATTR_TYPE_HASH accepts attributes with arbitrary names from possibly
|
||||
/* untrusted sources. This is unsafe, unless the resulting table is
|
||||
/* queried only with known to be good attribute names.
|
||||
/* DIAGNOSTICS
|
||||
/* attr_scan() and attr_vscan() return -1 when malformed input is
|
||||
/* detected (string too long, incomplete line, missing end marker).
|
||||
/* Otherwise, the result value is the number of attributes that were
|
||||
/* successfully recovered from the input stream (a hash table counts
|
||||
/* as the number of entries stored into the table).
|
||||
/*
|
||||
/* Panic: interface violation. All system call errors are fatal.
|
||||
/* SEE ALSO
|
||||
/* attr_print(3) send attributes over byte stream.
|
||||
/* 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 <sys_defs.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <mymalloc.h>
|
||||
#include <vstream.h>
|
||||
#include <vstring.h>
|
||||
#include <htable.h>
|
||||
#include <base64_code.h>
|
||||
#include <attr.h>
|
||||
|
||||
/* Application specific. */
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
/* attr_scan_string - pull a string from the input stream */
|
||||
|
||||
static int attr_scan_string(VSTREAM *fp, VSTRING *plain_buf, const char *context)
|
||||
{
|
||||
static VSTRING *base64_buf = 0;
|
||||
extern int var_line_limit; /* XXX */
|
||||
int limit = var_line_limit * 2;
|
||||
int ch;
|
||||
|
||||
if (base64_buf == 0)
|
||||
base64_buf = vstring_alloc(10);
|
||||
|
||||
VSTRING_RESET(base64_buf);
|
||||
while ((ch = VSTREAM_GETC(fp)) != ':' && ch != '\n') {
|
||||
if (ch == VSTREAM_EOF) {
|
||||
msg_warn("premature end-of-input from %s while reading %s",
|
||||
VSTREAM_PATH(fp), context);
|
||||
return (-1);
|
||||
}
|
||||
VSTRING_ADDCH(base64_buf, ch);
|
||||
if (LEN(base64_buf) > limit) {
|
||||
msg_warn("string length > %d characters from %s while reading %s",
|
||||
limit, VSTREAM_PATH(fp), context);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
VSTRING_TERMINATE(base64_buf);
|
||||
if (base64_decode(plain_buf, STR(base64_buf), LEN(base64_buf)) == 0) {
|
||||
msg_warn("malformed base64 data from %s: %.100s",
|
||||
VSTREAM_PATH(fp), STR(base64_buf));
|
||||
return (-1);
|
||||
}
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s", context, *STR(plain_buf) ? STR(plain_buf) : "(end)");
|
||||
return (ch);
|
||||
}
|
||||
|
||||
/* attr_scan_number - pull a number from the input stream */
|
||||
|
||||
static int attr_scan_number(VSTREAM *fp, unsigned *ptr, VSTRING *str_buf,
|
||||
const char *context)
|
||||
{
|
||||
char junk = 0;
|
||||
int ch;
|
||||
|
||||
if ((ch = attr_scan_string(fp, str_buf, context)) < 0)
|
||||
return (-1);
|
||||
if (sscanf(STR(str_buf), "%u%c", ptr, &junk) != 1 || junk != 0) {
|
||||
msg_warn("malformed numerical data from %s while reading %s: %.100s",
|
||||
VSTREAM_PATH(fp), context, STR(str_buf));
|
||||
return (-1);
|
||||
}
|
||||
return (ch);
|
||||
}
|
||||
|
||||
/* attr_vscan - receive attribute list from stream */
|
||||
|
||||
int attr_vscan(VSTREAM *fp, int flags, va_list ap)
|
||||
{
|
||||
const char *myname = "attr_scan";
|
||||
static VSTRING *str_buf = 0;
|
||||
static VSTRING *name_buf = 0;
|
||||
int wanted_type = -1;
|
||||
char *wanted_name;
|
||||
unsigned int *number;
|
||||
VSTRING *string;
|
||||
HTABLE *hash_table;
|
||||
int ch;
|
||||
int conversions;
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (flags & ~ATTR_FLAG_ALL)
|
||||
msg_panic("%s: bad flags: 0x%x", myname, flags);
|
||||
|
||||
/*
|
||||
* Initialize.
|
||||
*/
|
||||
if (str_buf == 0) {
|
||||
str_buf = vstring_alloc(10);
|
||||
name_buf = vstring_alloc(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over all (type, name, value) triples.
|
||||
*/
|
||||
for (conversions = 0; /* void */ ; conversions++) {
|
||||
|
||||
/*
|
||||
* Determine the next attribute type and attribute name on the
|
||||
* caller's wish list.
|
||||
*
|
||||
* If we're reading into a hash table, we already know that the
|
||||
* attribute value is string-valued, and we get the attribute name
|
||||
* from the input stream instead. This is secure only when the
|
||||
* resulting table is queried with known to be good attribute names.
|
||||
*/
|
||||
if (wanted_type != ATTR_TYPE_HASH) {
|
||||
wanted_type = va_arg(ap, int);
|
||||
if (wanted_type == ATTR_TYPE_END) {
|
||||
if ((flags & ATTR_FLAG_MORE) != 0)
|
||||
return (conversions);
|
||||
wanted_name = "(list terminator)";
|
||||
} else if (wanted_type == ATTR_TYPE_HASH) {
|
||||
wanted_name = "(any attribute name or list terminator)";
|
||||
hash_table = va_arg(ap, HTABLE *);
|
||||
if (va_arg(ap, int) !=ATTR_TYPE_END)
|
||||
msg_panic("%s: ATTR_TYPE_HASH not followed by ATTR_TYPE_END",
|
||||
myname);
|
||||
} else {
|
||||
wanted_name = va_arg(ap, char *);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate the next attribute of interest in the input stream.
|
||||
*/
|
||||
for (;;) {
|
||||
|
||||
/*
|
||||
* Get the name of the next attribute. Hitting EOF is always bad.
|
||||
* Hitting the end-of-input early is OK if the caller is prepared
|
||||
* to deal with missing inputs.
|
||||
*/
|
||||
if (msg_verbose)
|
||||
msg_info("%s: wanted attribute: %s",
|
||||
VSTREAM_PATH(fp), wanted_name);
|
||||
if ((ch = attr_scan_string(fp, name_buf,
|
||||
"input attribute name")) == VSTREAM_EOF)
|
||||
return (-1);
|
||||
if (ch == '\n' && LEN(name_buf) == 0) {
|
||||
if (wanted_type == ATTR_TYPE_END
|
||||
|| wanted_type == ATTR_TYPE_HASH)
|
||||
return (conversions);
|
||||
if ((flags & ATTR_FLAG_MISSING) != 0)
|
||||
msg_warn("missing attribute %s in input from %s",
|
||||
wanted_name, VSTREAM_PATH(fp));
|
||||
return (conversions);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the caller asks for this attribute.
|
||||
*/
|
||||
if (wanted_type == ATTR_TYPE_HASH
|
||||
|| (wanted_type != ATTR_TYPE_END
|
||||
&& strcmp(wanted_name, STR(name_buf)) == 0))
|
||||
break;
|
||||
if ((flags & ATTR_FLAG_EXTRA) != 0) {
|
||||
msg_warn("spurious attribute %s in input from %s",
|
||||
STR(name_buf), VSTREAM_PATH(fp));
|
||||
return (conversions);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip over this attribute. The caller does not ask for it.
|
||||
*/
|
||||
while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n')
|
||||
/* void */ ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the requested conversion. If the target attribute is a
|
||||
* non-array type, disallow sending a multi-valued attribute, and
|
||||
* disallow sending no value. If the target attribute is an array
|
||||
* type, allow the sender to send a zero-element array (i.e. no value
|
||||
* at all). XXX Need to impose a bound on the number of array
|
||||
* elements.
|
||||
*/
|
||||
switch (wanted_type) {
|
||||
case ATTR_TYPE_NUM:
|
||||
if (ch != ':') {
|
||||
msg_warn("missing value for number attribute %s from %s",
|
||||
STR(name_buf), VSTREAM_PATH(fp));
|
||||
return (-1);
|
||||
}
|
||||
number = va_arg(ap, unsigned int *);
|
||||
if ((ch = attr_scan_number(fp, number, str_buf,
|
||||
"input attribute value")) < 0)
|
||||
return (-1);
|
||||
if (ch != '\n') {
|
||||
msg_warn("multiple values for attribute %s from %s",
|
||||
STR(name_buf), VSTREAM_PATH(fp));
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
case ATTR_TYPE_STR:
|
||||
if (ch != ':') {
|
||||
msg_warn("missing value for string attribute %s from %s",
|
||||
STR(name_buf), VSTREAM_PATH(fp));
|
||||
return (-1);
|
||||
}
|
||||
string = va_arg(ap, VSTRING *);
|
||||
if ((ch = attr_scan_string(fp, string,
|
||||
"input attribute value")) < 0)
|
||||
return (-1);
|
||||
if (ch != '\n') {
|
||||
msg_warn("multiple values for attribute %s from %s",
|
||||
STR(name_buf), VSTREAM_PATH(fp));
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
case ATTR_TYPE_HASH:
|
||||
if (ch != ':') {
|
||||
msg_warn("missing value for string attribute %s from %s",
|
||||
STR(name_buf), VSTREAM_PATH(fp));
|
||||
return (-1);
|
||||
}
|
||||
if ((ch = attr_scan_string(fp, str_buf,
|
||||
"input attribute value")) < 0)
|
||||
return (-1);
|
||||
if (ch != '\n') {
|
||||
msg_warn("multiple values for attribute %s from %s",
|
||||
STR(name_buf), VSTREAM_PATH(fp));
|
||||
return (-1);
|
||||
}
|
||||
if (htable_locate(hash_table, STR(name_buf)) != 0) {
|
||||
if ((flags & ATTR_FLAG_EXTRA) != 0) {
|
||||
msg_warn("duplicate attribute %s in input from %s",
|
||||
STR(name_buf), VSTREAM_PATH(fp));
|
||||
return (conversions);
|
||||
}
|
||||
} else {
|
||||
htable_enter(hash_table, STR(name_buf),
|
||||
mystrdup(STR(str_buf)));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
msg_panic("%s: unknown type code: %d", myname, wanted_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* attr_scan - read attribute list from stream */
|
||||
|
||||
int attr_scan(VSTREAM *fp, int flags,...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, flags);
|
||||
ret = attr_vscan(fp, flags, ap);
|
||||
va_end(ap);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
/*
|
||||
* Proof of concept test program. Mirror image of the attr_scan test
|
||||
* program.
|
||||
*/
|
||||
#include <msg_vstream.h>
|
||||
|
||||
int var_line_limit = 2048;
|
||||
|
||||
int main(int unused_argc, char **used_argv)
|
||||
{
|
||||
VSTRING *str_val = vstring_alloc(1);
|
||||
HTABLE *table = htable_create(1);
|
||||
HTABLE_INFO **ht_info_list;
|
||||
HTABLE_INFO **ht;
|
||||
int int_val;
|
||||
int ret;
|
||||
|
||||
msg_verbose = 1;
|
||||
msg_vstream_init(used_argv[0], VSTREAM_ERR);
|
||||
if ((ret = attr_scan(VSTREAM_IN,
|
||||
ATTR_FLAG_STRICT,
|
||||
ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val,
|
||||
ATTR_TYPE_STR, ATTR_NAME_STR, str_val,
|
||||
ATTR_TYPE_HASH, table,
|
||||
ATTR_TYPE_END)) > 2) {
|
||||
vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val);
|
||||
vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val));
|
||||
ht_info_list = htable_list(table);
|
||||
for (ht = ht_info_list; *ht; ht++)
|
||||
vstream_printf("(hash) %s %s\n", ht[0]->key, ht[0]->value);
|
||||
myfree((char *) ht_info_list);
|
||||
} else {
|
||||
vstream_printf("return: %d\n", ret);
|
||||
}
|
||||
if ((ret = attr_scan(VSTREAM_IN,
|
||||
ATTR_FLAG_STRICT,
|
||||
ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val,
|
||||
ATTR_TYPE_STR, ATTR_NAME_STR, str_val,
|
||||
ATTR_TYPE_END)) == 2) {
|
||||
vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val);
|
||||
vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val));
|
||||
ht_info_list = htable_list(table);
|
||||
for (ht = ht_info_list; *ht; ht++)
|
||||
vstream_printf("(hash) %s %s\n", ht[0]->key, ht[0]->value);
|
||||
myfree((char *) ht_info_list);
|
||||
} else {
|
||||
vstream_printf("return: %d\n", ret);
|
||||
}
|
||||
if (vstream_fflush(VSTREAM_OUT) != 0)
|
||||
msg_fatal("write error: %m");
|
||||
|
||||
vstring_free(str_val);
|
||||
htable_free(table, myfree);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
@ -157,7 +157,7 @@ static int attr_scan0_string(VSTREAM *fp, VSTRING *plain_buf, const char *contex
|
||||
int limit = var_line_limit * 2;
|
||||
int ch;
|
||||
|
||||
if ((ch = vstring_get_null_bound(plain_buf, fp, limit)) == VSTREAM_EOF) {
|
||||
if ((ch = vstring_get_null(plain_buf, fp)) == VSTREAM_EOF) {
|
||||
msg_warn("premature end-of-input from %s while reading %s",
|
||||
VSTREAM_PATH(fp), context);
|
||||
return (-1);
|
||||
|
@ -172,11 +172,13 @@ static int attr_scan64_string(VSTREAM *fp, VSTRING *plain_buf, const char *conte
|
||||
return (-1);
|
||||
}
|
||||
VSTRING_ADDCH(base64_buf, ch);
|
||||
#if 0
|
||||
if (LEN(base64_buf) > limit) {
|
||||
msg_warn("string length > %d characters from %s while reading %s",
|
||||
limit, VSTREAM_PATH(fp), context);
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
VSTRING_TERMINATE(base64_buf);
|
||||
if (base64_decode(plain_buf, STR(base64_buf), LEN(base64_buf)) == 0) {
|
||||
|
@ -107,6 +107,7 @@ int inet_trigger(const char *service, const char *buf, int len, int timeout)
|
||||
msg_warn("%s: connect to %s: %m", myname, service);
|
||||
return (-1);
|
||||
}
|
||||
close_on_exec(fd, CLOSE_ON_EXEC);
|
||||
ip = (struct inet_trigger *) mymalloc(sizeof(*ip));
|
||||
ip->fd = fd;
|
||||
ip->service = mystrdup(service);
|
||||
|
@ -54,7 +54,7 @@ int make_dirs(const char *path, int perms)
|
||||
int saved_ch;
|
||||
struct stat st;
|
||||
int ret;
|
||||
mode_t saved_mode;
|
||||
mode_t saved_mode = 0;
|
||||
|
||||
/*
|
||||
* Initialize. Make a copy of the path that we can safely clobber.
|
||||
|
@ -34,10 +34,8 @@
|
||||
/* .RS
|
||||
/* .IP MATCH_FLAG_PARENT
|
||||
/* The hostname pattern foo.com matches any name within the domain
|
||||
/* foo.com.
|
||||
/* .IP MATCH_FLAG_DOTPARENT
|
||||
/* The hostname pattern .foo.com matches any name under foo.com.
|
||||
/* The pattern foo.com matches itself only.
|
||||
/* foo.com. If this flag is cleared, foo.com matches itself
|
||||
/* only, and .foo.com matches any name below the domain foo.com.
|
||||
/* .RE
|
||||
/* Specify MATCH_FLAG_NONE to request none of the above.
|
||||
/* The pattern_list argument specifies a list of patterns. The third
|
||||
|
@ -34,10 +34,9 @@
|
||||
/* of the named host. The flags argument specifies the bit-wise OR
|
||||
/* of zero or more of the following:
|
||||
/* .IP MATCH_FLAG_PARENT
|
||||
/* The pattern foo.com matches any name within the domain foo.com.
|
||||
/* .IP MATCH_FLAG_DOTPARENT
|
||||
/* The pattern .foo.com matches any name under foo.com. The pattern
|
||||
/* foo.com matches itself only.
|
||||
/* The hostname pattern foo.com matches itself and any name below
|
||||
/* the domain foo.com. If this flag is cleared, foo.com matches itself
|
||||
/* only, and .foo.com matches any name below the domain foo.com.
|
||||
/* .RE
|
||||
/* Specify MATCH_FLAG_NONE to request none of the above.
|
||||
/*
|
||||
@ -140,25 +139,15 @@ int match_hostname(int flags, const char *name, const char *pattern)
|
||||
if (strchr(pattern, ':') != 0) {
|
||||
temp = lowercase(mystrdup(name));
|
||||
match = 0;
|
||||
if (flags & MATCH_FLAG_PARENT) {
|
||||
for (entry = temp; /* void */ ; entry = next + 1) {
|
||||
if ((match = (dict_lookup(pattern, entry) != 0)) != 0)
|
||||
break;
|
||||
if (dict_errno != 0)
|
||||
msg_fatal("%s: table lookup problem", pattern);
|
||||
if ((next = strchr(entry, '.')) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flags & MATCH_FLAG_DOTPARENT) {
|
||||
for (entry = temp; /* void */ ; entry = next) {
|
||||
if ((match = (dict_lookup(pattern, entry) != 0)) != 0)
|
||||
break;
|
||||
if (dict_errno != 0)
|
||||
msg_fatal("%s: table lookup problem", pattern);
|
||||
if ((next = strchr(entry, '.')) == 0)
|
||||
break;
|
||||
}
|
||||
for (entry = temp; /* void */ ; entry = next) {
|
||||
if ((match = (dict_lookup(pattern, entry) != 0)) != 0)
|
||||
break;
|
||||
if (dict_errno != 0)
|
||||
msg_fatal("%s: table lookup problem", pattern);
|
||||
if ((next = strchr(entry + 1, '.')) == 0)
|
||||
break;
|
||||
if (flags & MATCH_FLAG_PARENT)
|
||||
next += 1;
|
||||
}
|
||||
myfree(temp);
|
||||
return (match);
|
||||
@ -179,10 +168,9 @@ int match_hostname(int flags, const char *name, const char *pattern)
|
||||
pd = name + strlen(name) - strlen(pattern);
|
||||
if (pd > name && pd[-1] == '.' && strcasecmp(pd, pattern) == 0)
|
||||
return (1);
|
||||
}
|
||||
if (flags & MATCH_FLAG_DOTPARENT) {
|
||||
} else if (pattern[0] == '.') {
|
||||
pd = name + strlen(name) - strlen(pattern);
|
||||
if (pd > name && pd[-1] == '.' && strcasecmp(pd - 1, pattern) == 0)
|
||||
if (pd > name && strcasecmp(pd, pattern) == 0)
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,7 @@
|
||||
|
||||
#define MATCH_FLAG_NONE 0
|
||||
#define MATCH_FLAG_PARENT (1<<0)
|
||||
#define MATCH_FLAG_DOTPARENT (1<<1)
|
||||
#define MATCH_FLAG_ALL (MATCH_FLAG_PARENT|MATCH_FLAG_DOTPARENT)
|
||||
#define MATCH_FLAG_ALL (MATCH_FLAG_PARENT)
|
||||
|
||||
extern int match_string(int, const char *, const char *);
|
||||
extern int match_hostname(int, const char *, const char *);
|
||||
|
@ -103,6 +103,7 @@ int stream_trigger(const char *service, const char *buf, int len, int timeou
|
||||
msg_warn("%s: connect to %s: %m", myname, service);
|
||||
return (-1);
|
||||
}
|
||||
close_on_exec(fd, CLOSE_ON_EXEC);
|
||||
|
||||
/*
|
||||
* Stash away context.
|
||||
|
@ -104,6 +104,7 @@ int unix_trigger(const char *service, const char *buf, int len, int timeout)
|
||||
msg_warn("%s: connect to %s: %m", myname, service);
|
||||
return (-1);
|
||||
}
|
||||
close_on_exec(fd, CLOSE_ON_EXEC);
|
||||
|
||||
/*
|
||||
* Stash away context.
|
||||
|
Loading…
x
Reference in New Issue
Block a user