19990324
Bugfix: missing map name in check_xxx_access restrictions
- could casue a segmentation error. Lamont Jones, Hewlett-
+ could cause a segmentation error. Lamont Jones, Hewlett-
Packard.
Feature: forward_path configuration parameter (default:
Based on initial code by Philip A. Prindeville, Mirapoint,
Inc., USA. Files: local/dotforward.c.
+19990325
+
+ Workaround: Solaris NIS alias maps need special entries
+ (YP_MASTER_NAME, YP_LAST_MODIFIED). What's worse, normal
+ keys/values include a null byte at the end, but the YP_XXX
+ ones don't. File: postalias/postalias.c.
+
+ Compatibility: Solaris NIS apparently does include a null
+ byte at the end of keys and values. File: util/sys_defs.h.
+
+ Feature: library support for config parameters that are
+ not $name expanded at program start-up. This was needed
+ for forward_path, and will also be needed to make message
+ headers customizable.
+
+ Bugfix: pcre didn't handle \\ right. Lamont Jones, Hewlett-
+ Packard. File: util/dict_pcre.c.
+
Future:
Planned: must be able to list the same hash table in
#
#local_command_shell = /some/where/smrsh -c
+# The forward_path parameter specifies a search list. The first file
+# that is found is used. In the path you can specify $user (login
+# name), $home (home directory), $recipient_delimiter, and $extension
+# (address extension).
+#
+#forward_path = /var/forward/$user
+forward_path = $home/.forward$recipient_delimiter$extension,$home/.forward
+
# The allow_mail_to_commands parameter restricts mail delivery to
# external commands. The default is to disallow delivery to "|command"
# in :include: files.
#
# reject_unknown_client:reject the request if the client hostname is unknown.
# permit_mynetworks: permit if the client address matches $mynetworks.
+# check_client_access maptype:mapname
# maptype:mapname: look up client name, parent domains, client address,
# or networks obtained by stripping octets.
# Reject if result is REJECT or "[45]xx text"
# The default is to permit everything. The following restrictions
# are available:
#
-# reject_unknown_client:reject the request if the client hostname is unknown.
# permit_mynetworks: permit if the client address matches $mynetworks.
+# reject_unknown_client:reject the request if the client hostname is unknown.
+# reject_maps_rbl:reject if the client is listed under $maps_rbl_domains.
# reject_invalid_hostname: reject HELO hostname with bad syntax.
-# reject_unknown_hostname: reject HELO hostname without DNS A record.
+# reject_unknown_hostname: reject HELO hostname without DNS A or MX record.
# reject_non_fqdn_hostname: reject HELO hostname that is not in FQDN form
+# check_helo_access maptype:mapname
# maptype:mapname: look up HELO hostname or parent domains.
# Reject if result is REJECT or "[45]xx text"
# Permit otherwise.
# The default is to permit any sender address. The following
# restrictions are available:
#
-# reject_unknown_client:reject the request if the client hostname is unknown.
# permit_mynetworks: permit if the client address matches $mynetworks.
-# reject_unknown_address:reject if the sender domain has no A or MX record.
+# reject_unknown_client:reject the request if the client hostname is unknown.
+# reject_maps_rbl:reject if the client is listed under $maps_rbl_domains.
+# reject_invalid_hostname: reject HELO hostname with bad syntax.
+# reject_unknown_hostname: reject HELO hostname without DNS A or MX record.
+# reject_unknown_sender_domain:reject sender domain without A or MX record.
+# check_sender_access maptype:mapname
# maptype:mapname: look up sender address, parent domain, or localpart@.
# Reject if result is REJECT or "[45]xx text"
# Permit otherwise.
#
# The following restrictions are available:
#
-# reject_unknown_client:reject the request if the client hostname is unknown.
# permit_mynetworks: permit if the client address matches $mynetworks.
+# reject_unknown_client:reject the request if the client hostname is unknown.
+# reject_maps_rbl:reject if the client is listed under $maps_rbl_domains.
+# reject_invalid_hostname: reject HELO hostname with bad syntax.
+# reject_unknown_hostname: reject HELO hostname without DNS A or MX record.
# check_relay_domains: permit only mail from/to domains in $relay_domains.
# permit_mx_backup: accept mail for sites that list me as MX host.
+# reject_unknown_recipient_domain: reject domains without A or MX record.
+# check_recipient_access maptype:mapname
# maptype:mapname: look up recipient address, parent domain, or localpart@.
# Reject if result is REJECT or "[45]xx text"
# Permit otherwise.
resolve_clnt.c resolve_local.c rewrite_clnt.c sent.c smtp_stream.c \
split_addr.c string_list.c sys_exits.c timed_ipc.c tok822_find.c \
tok822_node.c tok822_parse.c tok822_resolve.c tok822_rewrite.c \
- tok822_tree.c clnt_stream.c deliver_pass.c
+ tok822_tree.c clnt_stream.c deliver_pass.c config_raw.c
OBJS = been_here.o bounce.o canon_addr.o clean_env.o cleanup_strerror.o \
config.o config_bool.o config_int.o config_str.o debug_peer.o \
debug_process.o defer.o deliver_completed.o deliver_flock.o \
resolve_clnt.o resolve_local.o rewrite_clnt.o sent.o smtp_stream.o \
split_addr.o string_list.o sys_exits.o timed_ipc.o tok822_find.o \
tok822_node.o tok822_parse.o tok822_resolve.o tok822_rewrite.o \
- tok822_tree.o clnt_stream.o deliver_pass.o
+ tok822_tree.o clnt_stream.o deliver_pass.o config_raw.o
HDRS = been_here.h bounce.h canon_addr.h clean_env.h cleanup_user.h \
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
deliver_flock.h deliver_request.h domain_list.h dot_lockfile.h \
config_int.o: ../include/vbuf.h
config_int.o: ../include/stringops.h
config_int.o: config.h
+config_raw.o: config_raw.c
+config_raw.o: ../include/sys_defs.h
+config_raw.o: ../include/msg.h
+config_raw.o: ../include/mymalloc.h
+config_raw.o: config.h
config_str.o: config_str.c
config_str.o: ../include/sys_defs.h
config_str.o: ../include/msg.h
extern char *get_config_str(const char *, const char *, int, int);
extern int get_config_int(const char *, int, int, int);
extern int get_config_bool(const char *, int);
+extern char *get_config_raw(const char *, const char *, int, int);
extern int get_config_int2(const char *, const char *, int, int, int);
extern char *get_config_str_fn(const char *, const char *(*) (void), int, int);
extern int get_config_int_fn(const char *, int (*) (void), int, int);
extern int get_config_bool_fn(const char *, int (*) (void));
+extern char *get_config_raw_fn(const char *, const char *(*) (void), int, int);
/*
* Update dictionary.
extern void get_config_str_table(CONFIG_STR_TABLE *);
extern void get_config_int_table(CONFIG_INT_TABLE *);
extern void get_config_bool_table(CONFIG_BOOL_TABLE *);
+extern void get_config_raw_table(CONFIG_STR_TABLE *);
/*
* Tables to initialize parameters from the global configuration file or
extern void get_config_str_fn_table(CONFIG_STR_FN_TABLE *);
extern void get_config_int_fn_table(CONFIG_INT_FN_TABLE *);
extern void get_config_bool_fn_table(CONFIG_BOOL_FN_TABLE *);
+extern void get_config_raw_fn_table(CONFIG_STR_FN_TABLE *);
/* LICENSE
/* .ad
--- /dev/null
+/*++
+/* NAME
+/* config_raw 3
+/* SUMMARY
+/* raw string-valued global configuration parameter support
+/* SYNOPSIS
+/* #include <config.h>
+/*
+/* char *get_config_raw(name, defval, min, max)
+/* const char *name;
+/* const char *defval;
+/* int min;
+/* int max;
+/*
+/* char *get_config_raw_fn(name, defval, min, max)
+/* const char *name;
+/* const char *(*defval)(void);
+/* int min;
+/* int max;
+/*
+/* void get_config_raw_table(table)
+/* CONFIG_STR_TABLE *table;
+/*
+/* void get_config_raw_fn_table(table)
+/* CONFIG_STR_TABLE *table;
+/* DESCRIPTION
+/* This module implements support for string-valued global
+/* configuration parameters that are loaded without $name expansion.
+/*
+/* get_config_raw() looks up the named entry in the global
+/* configuration dictionary. The default value is returned when
+/* no value was found. String results should be passed to myfree()
+/* when no longer needed. \fImin\fR is zero or specifies a lower
+/* bound on the string length; \fImax\fR is zero or specifies an
+/* upper limit on the string length.
+/*
+/* get_config_raw_fn() is similar but specifies a function that
+/* provides the default value. The function is called only when
+/* the default value is used.
+/*
+/* get_config_raw_table() and get_config_raw_fn_table() read
+/* lists of variables, as directed by their table arguments. A table
+/* must be terminated by a null entry.
+/* DIAGNOSTICS
+/* Fatal errors: bad string length.
+/* SEE ALSO
+/* config(3) generic config parameter support
+/* 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 <stdlib.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+
+/* Global library. */
+
+#include "config.h"
+
+/* check_config_raw - validate string length */
+
+static void check_config_raw(const char *name, const char *strval,
+ int min, int max)
+{
+ int len = strlen(strval);
+
+ if (min && len < min)
+ msg_fatal("bad string length (%d < %d): %s = %s",
+ len, min, name, strval);
+ if (max && len > max)
+ msg_fatal("bad string length (%d > %d): %s = %s",
+ len, max, name, strval);
+}
+
+/* get_config_raw - evaluate string-valued configuration variable */
+
+char *get_config_raw(const char *name, const char *defval,
+ int min, int max)
+{
+ const char *strval;
+
+ if ((strval = config_lookup(name)) == 0) {
+ strval = defval;
+ config_update(name, strval);
+ }
+ check_config_raw(name, strval, min, max);
+ return (mystrdup(strval));
+}
+
+/* get_config_raw_fn - evaluate string-valued configuration variable */
+
+typedef const char *(*stupid_indent_str) (void);
+
+char *get_config_raw_fn(const char *name, stupid_indent_str defval,
+ int min, int max)
+{
+ const char *strval;
+
+ if ((strval = config_lookup(name)) == 0) {
+ strval = defval();
+ config_update(name, strval);
+ }
+ check_config_raw(name, strval, min, max);
+ return (mystrdup(strval));
+}
+
+/* get_config_raw_table - look up table of strings */
+
+void get_config_raw_table(CONFIG_STR_TABLE *table)
+{
+ while (table->name) {
+ if (table->target[0])
+ myfree(table->target[0]);
+ table->target[0] = get_config_raw(table->name, table->defval,
+ table->min, table->max);
+ table++;
+ }
+}
+
+/* get_config_raw_fn_table - look up strings, defaults are functions */
+
+void get_config_raw_fn_table(CONFIG_STR_FN_TABLE *table)
+{
+ while (table->name) {
+ if (table->target[0])
+ myfree(table->target[0]);
+ table->target[0] = get_config_raw_fn(table->name, table->defval,
+ table->min, table->max);
+ table++;
+ }
+}
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-19990324"
+#define DEF_MAIL_VERSION "Snapshot-19990325"
extern char *var_mail_version;
/* LICENSE
VSTRING_RESET(path);
mac_parse(lhs, dotforward_parse_callback, (char *) &fw_context);
if (fw_context.failures == 0) {
- lookup_status = lstat_as(STR(path), &st,
- usr_attr.uid, usr_attr.gid);
+ lookup_status =
+ lstat_as(STR(path), &st, usr_attr.uid, usr_attr.gid);
if (msg_verbose)
msg_info("%s: path %s status %d", myname,
STR(path), lookup_status);
0,
};
- /*
- * XXX We need to extend the config_XXX() interface to request no $name
- * expansion in a given value or in the default value.
- */
- static CONFIG_STR_TABLE straight_str_table[] = {
+ /* Suppress $name expansion upon loading. */
+ static CONFIG_STR_TABLE raw_table[] = {
VAR_FORWARD_PATH, DEF_FORWARD_PATH, &var_forward_path, 0, 0,
0,
};
single_server_main(argc, argv, local_service,
MAIL_SERVER_INT_TABLE, int_table,
MAIL_SERVER_STR_TABLE, str_table,
+ MAIL_SERVER_RAW_TABLE, raw_table,
MAIL_SERVER_BOOL_TABLE, bool_table,
MAIL_SERVER_POST_INIT, post_init,
0);
#define OPENED_ATTR(attr) attr.queue_id, attr.sender
#define COPY_ATTR(attr) attr.sender, attr.delivered, attr.fp
-#define MSG_LOG_STATE(m, s) \
+#define MSG_LOG_STATE(m, p) \
msg_info("%s[%d]: local %s recip %s exten %s deliver %s", m, \
- s.level, \
- s.msg_attr.local ? s.msg_attr.local : "" , \
- s.msg_attr.recipient ? s.msg_attr.recipient : "", \
- s.msg_attr.extension ? s.msg_attr.extension : "", \
- s.msg_attr.delivered ? s.msg_attr.delivered : "")
+ p.level, \
+ p.msg_attr.local ? p.msg_attr.local : "" , \
+ p.msg_attr.recipient ? p.msg_attr.recipient : "", \
+ p.msg_attr.extension ? p.msg_attr.extension : "", \
+ p.msg_attr.delivered ? p.msg_attr.delivered : "")
/*
* "inner" nodes of the delivery graph.
#define MAIL_SERVER_INT_TABLE 1
#define MAIL_SERVER_STR_TABLE 2
#define MAIL_SERVER_BOOL_TABLE 3
+#define MAIL_SERVER_RAW_TABLE 4
#define MAIL_SERVER_PRE_INIT 10
#define MAIL_SERVER_POST_INIT 11
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
/* are allowed.
+/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_STR_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed. Raw parameters are not subjected to $name
+/* evaluation.
/* .IP "MAIL_SERVER_PRE_INIT (void *(void))"
/* A pointer to a function that is called once
/* by the skeleton after it has read the global configuration file
case MAIL_SERVER_BOOL_TABLE:
get_config_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
break;
+ case MAIL_SERVER_RAW_TABLE:
+ get_config_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
+ break;
case MAIL_SERVER_PRE_INIT:
pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
break;
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
/* are allowed.
+/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_STR_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed. Raw parameters are not subjected to $name
+/* evaluation.
/* .IP "MAIL_SERVER_PRE_INIT (void *(void))"
/* A pointer to a function that is called once
/* by the skeleton after it has read the global configuration file
case MAIL_SERVER_BOOL_TABLE:
get_config_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
break;
+ case MAIL_SERVER_RAW_TABLE:
+ get_config_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
+ break;
case MAIL_SERVER_PRE_INIT:
pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
break;
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
/* are allowed.
+/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_STR_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed. Raw parameters are not subjected to $name
+/* evaluation.
/* .IP "MAIL_SERVER_PRE_INIT (void *(void))"
/* A pointer to a function that is called once
/* by the skeleton after it has read the global configuration file
case MAIL_SERVER_BOOL_TABLE:
get_config_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
break;
+ case MAIL_SERVER_RAW_TABLE:
+ get_config_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
+ break;
case MAIL_SERVER_PRE_INIT:
pre_init = va_arg(ap, MAIL_SERVER_INIT_FN);
break;
postalias.o: ../include/readline.h
postalias.o: ../include/stringops.h
postalias.o: ../include/split_at.h
+postalias.o: ../include/get_hostname.h
postalias.o: ../include/tok822.h
postalias.o: ../include/resolve_clnt.h
postalias.o: ../include/config.h
#include <readline.h>
#include <stringops.h>
#include <split_at.h>
+#include <get_hostname.h>
/* Global library. */
*/
mkmap_append(mkmap, "@", "@");
+ /*
+ * NIS compatibility: add time and master info.
+ */
+ vstring_sprintf(value_buffer, "%010ld", (long) time((time_t *) 0));
+ mkmap_append(mkmap, "YP_LAST_MODIFIED", STR(value_buffer));
+ mkmap_append(mkmap, "YP_MASTER_NAME", get_hostname());
+
/*
* Close the alias database, and release the lock.
*/
/*
* Optionally append a null byte to key and value.
*/
- if (dict_dbm->flags & DICT_DBM_TRY1NULL) {
+ if ((dict_dbm->flags & DICT_DBM_TRY1NULL)
+ && strcmp(name, "YP_MASTER_NAME") != 0
+ && strcmp(name, "YP_LAST_MODIFIED") != 0) {
dbm_key.dsize++;
dbm_value.dsize++;
}
/* Search for second delimiter, handling backslash escape */
while (*p) {
- if (*p == re_delimiter &&
- (p > vstring_str(line_buffer) && *(p - 1) != '\\'))
+ if (*p == '\\') {
+ ++p;
+ if (*p == 0)
+ break;
+ } else if (*p == re_delimiter)
break;
++p;
}
else
pcre_list->next = pl;
pcre_list = pl;
- }
+}
- vstring_free(line_buffer);
- vstream_fclose(map_fp);
+vstring_free(line_buffer);
+vstream_fclose(map_fp);
- return (&dict_pcre->dict);
+return (&dict_pcre->dict);
}
#endif /* HAS_PCRE */
#define GETTIMEOFDAY(t) gettimeofday(t)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb"
#define FIONREAD_IN_SYS_FILIO_H
-#define DBM_NO_TRAILING_NULL
#define USE_STATVFS
#define STATVFS_IN_SYS_STATVFS_H
-#define STREAM_CONNECTIONS /* connld module */
+#define STREAM_CONNECTIONS /* avoid UNIX-domain sockets */
#define LOCAL_LISTEN stream_listen
#define LOCAL_ACCEPT stream_accept
#define LOCAL_CONNECT stream_connect