Berkeley DB create and read buffer size controls. Files:
util/dict_db.[hc], global/mail_params.[hc], global/mkmap_db.c.
+20020507
+
+ Cleanup: simplified the hash/btree cache management code.
+ The caches are now per table instead of shared, and the
+ default read cache size is reduced to 128 kBytes. File:
+ util/dict_db.c.
+
+20020508
+
+ Bugfix: close an obscure source routing relaying loophole
+ involving postfix-style virtual domains. Problem reported
+ by Victor Duchovny. File: smtpd/smtpd_check.c.
+
+ Bugfix: mail_addr_map() used the "wrong" @ character in
+ addresses with multiple @. Victor Duchovny. File:
+ global/mail_addr_map.c.
+
+ Bugfix: for address localpart quoting, now quote @ as a
+ special character everywhere, except when resolving addresses.
+ Previously, the @ was nowhere quoted as a special character,
+ not even in SMTP commands. Files: global/quote_82[12]_local.c
+ and clients.
+
Open problems:
Low: sendmail does not store null command-line recipients.
Postfix provides two configuration parameters that control how much
buffering memory Berkeley DB will use.
-- berkeley_db_create_buffer_size (default: 16 MBytes). This setting
-is used by the postalias and postmap commands. For "hash" files
-performance degrades rapidly unless the memory pool is O(file size).
-For "btree" files peformance is good with sorted input even for
-small memory pools, but with random input degrades rapidly unless
-the memory pool is O(file size).
-
-- berkeley_db_read_buffer_size (default: 256 kBytes). This setting
-is used by all other Postfix programs. The buffer size is adequate
-for reading.
+- berkeley_db_create_buffer_size (default: 16 MBytes per table).
+This setting is used by the postalias and postmap commands. For
+"hash" files, create performance degrades rapidly unless the memory
+pool is O(file size). For "btree" files, create peformance is good
+with sorted input even for small memory pools, but with random
+input degrades rapidly unless the memory pool is O(file size).
+
+- berkeley_db_read_buffer_size (default: 128 kBytes per table).
+This setting is used by all other Postfix programs. The buffer size
+is adequate for reading. If the cache is smaller than the table,
+random read performance is hardly cache size dependent, except with
+btree tables, where the cache size must be large enough to contain
+the entire path from the root node. Empirical evidence shows that
+64 kBytes may be sufficient. We double the size to play safe, and
+to anticipate changes in implementation and bloat.
via localhost port 10025, and that submits SMTP mail back into
Postfix via localhost port 10026.
- ..................................
- : Postfix :
- ----->smtpd \ /local---->
- : -cleanup->queue- :
- ---->pickup / ^ | \smtp----->
- : | v :
- : smtpd smtp :
- : 10026 | :
- ......................|...........
- ^ |
- | v
- ....|............
- : | 10025 :
- : filter :
- : :
- .................
+ ...................................
+ : Postfix :
+ ----->smtpd \ :
+ : -cleanup-\ /local---->
+ ---->pickup / -queue- :
+ : cleanup2/ | \smtp----->
+ : ^ v :
+ : | v :
+ : smtpd smtp :
+ : 10026 | :
+ .......................|...........
+ ^ |
+ | v
+ ....|.............
+ : | 10025 :
+ : filter :
+ : :
+ ..................
To enable content filtering in this manner, specify in main.cf a
new parameter:
-o content_filter=
-o local_recipient_maps=
-o myhostname=localhost.domain.name
+ -o disable_dns_lookups=yes
+ -o cleanup_service=cleanup2
+ cleanup2 unix n - n - 0 cleanup
+ -o header_checks=
+ -o body_checks=
-This is just another SMTP server. It is configured NOT to request
-content filtering for incoming mail. The server has the same process
-limit as the filter master.cf entry.
+This is just another SMTP server. The "-o content_filter=" requests
+no content filtering for incoming mail. The server has the same
+process limit as the "filter" master.cf entry.
The "-o local_recipient_maps=" is a safety in case you have specified
-local_recipient_maps in the main.cf file. That setting could
-interfere with content filtering.
+local_recipient_maps in the main.cf file. That could interfere with
+content filtering.
-The SMTP server is configured to use a different hostname in the
-greeting message (this is necessary for testing when I simply use
-no filtering program and let the SMTP content filtering interfaces
-talk directly to each other).
+The "-o myhostname=localhost.domain.name" avoids a possible problem
+if the content filter is picky about the hostname that Postfix
+sends in SMTP server replies.
+
+The "-o disable_dns_lookups=yes" turns off unnecessary DNS lookups
+that would only slow things down.
+
+The "-o cleanup_service=cleanup2" specifies that mail received via
+the secondary SMTP server should be send into the cleanup2 service.
+
+As the master.cf entry above shows, the cleanup2 service is like
+the normal cleanup server, but with some features turned off: no
+processing of header patterns, and no processing of body message
+patterns. This can save you some precious CPU cycles.
#
daemon_timeout = 18000s
+# The berkeley_db_create_buffer_size parameter specifies the per-table
+# I/O buffer size for programs that create Berkeley DB hash or btree
+# tables. Specify a byte count. The default buffer size is 16 MBytes.
+#
+berkeley_db_create_buffer_size = 16777216
+
+# The berkeley_db_read_buffer_size parameter specifies the per-table
+# I/O buffer size for programs that read Berkeley DB hash or btree
+# tables. Specify a byte count. The default buffer size is 128
+# kBytes.
+#
+berkeley_db_read_buffer_size = 131072
+
# The default_database_type parameter specifies the default database
# type to use in postalias(1) and postmap(1) commands. On many UNIX
# systems the default type is either `dbm' or `hash'. The default is
bounce_append_service.o: ../../include/stringops.h
bounce_append_service.o: ../../include/mail_queue.h
bounce_append_service.o: ../../include/quote_822_local.h
+bounce_append_service.o: ../../include/quote_flags.h
bounce_append_service.o: ../../include/deliver_flock.h
bounce_append_service.o: ../../include/myflock.h
bounce_append_service.o: bounce_service.h
bounce_notify_util.o: ../../include/line_wrap.h
bounce_notify_util.o: ../../include/mail_queue.h
bounce_notify_util.o: ../../include/quote_822_local.h
+bounce_notify_util.o: ../../include/quote_flags.h
bounce_notify_util.o: ../../include/mail_params.h
bounce_notify_util.o: ../../include/is_header.h
bounce_notify_util.o: ../../include/record.h
if (*recipient)
vstream_fprintf(log, "<%s>: ",
- printable(vstring_str(quote_822_local(in_buf, recipient)), '?'));
+ printable(vstring_str(quote_822_local(in_buf, recipient,
+ QUOTE_FLAG_8BITCLEAN)), '?'));
else
vstream_fprintf(log, "<>: ");
vstream_fputs(printable(why, '?'), log);
"Subject: Delayed Mail (still being retried)");
}
post_mail_fprintf(bounce, "To: %s",
- STR(quote_822_local(bounce_info->buf, dest)));
+ STR(quote_822_local(bounce_info->buf, dest,
+ QUOTE_FLAG_8BITCLEAN)));
/*
* MIME header.
cleanup_map11.o: ../../include/mail_addr_map.h
cleanup_map11.o: ../../include/maps.h
cleanup_map11.o: ../../include/quote_822_local.h
+cleanup_map11.o: ../../include/quote_flags.h
cleanup_map11.o: cleanup.h
cleanup_map11.o: ../../include/tok822.h
cleanup_map11.o: ../../include/resolve_clnt.h
cleanup_map1n.o: ../../include/maps.h
cleanup_map1n.o: ../../include/cleanup_user.h
cleanup_map1n.o: ../../include/quote_822_local.h
+cleanup_map1n.o: ../../include/quote_flags.h
cleanup_map1n.o: ../../include/been_here.h
cleanup_map1n.o: cleanup.h
cleanup_map1n.o: ../../include/tok822.h
cleanup_masquerade.o: ../../include/tok822.h
cleanup_masquerade.o: ../../include/resolve_clnt.h
cleanup_masquerade.o: ../../include/quote_822_local.h
+cleanup_masquerade.o: ../../include/quote_flags.h
cleanup_masquerade.o: cleanup.h
cleanup_masquerade.o: ../../include/vstream.h
cleanup_masquerade.o: ../../include/maps.h
cleanup_message.o: ../../include/resolve_clnt.h
cleanup_message.o: ../../include/header_opts.h
cleanup_message.o: ../../include/quote_822_local.h
+cleanup_message.o: ../../include/quote_flags.h
cleanup_message.o: ../../include/mail_params.h
cleanup_message.o: ../../include/mail_date.h
cleanup_message.o: ../../include/mail_addr.h
cleanup_rewrite.o: ../../include/resolve_clnt.h
cleanup_rewrite.o: ../../include/rewrite_clnt.h
cleanup_rewrite.o: ../../include/quote_822_local.h
+cleanup_rewrite.o: ../../include/quote_flags.h
cleanup_rewrite.o: cleanup.h
cleanup_rewrite.o: ../../include/vstream.h
cleanup_rewrite.o: ../../include/argv.h
/* void */ ;
}
+ /*
+ * Log something to make timeout errors easier to debug.
+ */
+ if (vstream_ftimeout(src))
+ msg_warn("%s: read timeout on %s",
+ state->queue_id, VSTREAM_PATH(src));
+
/*
* Finish this message, and report the result status to the client.
*/
* checking in one place, instead of having error handling code all over
* the place.
*/
- quote_822_local(temp, STR(addr));
+ quote_822_local(temp, STR(addr), QUOTE_FLAG_8BITCLEAN);
cleanup_map11_external(state, temp, maps, propagate);
unquote_822_local(addr, STR(temp));
vstring_free(temp);
state->queue_id, maps->title, addr);
break;
}
- quote_822_local(state->temp1, argv->argv[arg]);
+ quote_822_local(state->temp1, argv->argv[arg],
+ QUOTE_FLAG_8BITCLEAN);
if ((lookup = mail_addr_map(maps, STR(state->temp1), propagate)) != 0) {
saved_lhs = mystrdup(argv->argv[arg]);
for (i = 0; i < lookup->argc; i++) {
{
VSTRING *temp = vstring_alloc(100);
- quote_822_local(temp, STR(addr));
+ quote_822_local(temp, STR(addr), QUOTE_FLAG_8BITCLEAN);
cleanup_masquerade_external(temp, masq_domains);
unquote_822_local(addr, STR(temp));
cleanup_extract_internal(state->header_buf, *tpp);
}
vstring_sprintf(state->header_buf, "%s: ", hdr_opts->name);
+ /* XXX should quote_822_local the address local parts. */
tok822_externalize(state->header_buf, tree, TOK822_STR_HEAD);
myfree((char *) addr_list);
tok822_free_tree(tree);
cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
}
vstring_sprintf(state->header_buf, "%s: ", hdr_opts->name);
+ /* XXX should quote_822_local the address local parts. */
tok822_externalize(state->header_buf, tree, TOK822_STR_HEAD);
myfree((char *) addr_list);
tok822_free_tree(tree);
if ((state->headers_seen & (1 << (state->resent[0] ?
HDR_RESENT_FROM : HDR_FROM))) == 0) {
quote_822_local(state->temp1, *state->sender ?
- state->sender : MAIL_ADDR_MAIL_DAEMON);
+ state->sender : MAIL_ADDR_MAIL_DAEMON,
+ QUOTE_FLAG_8BITCLEAN);
vstring_sprintf(state->temp2, "%sFrom: %s",
state->resent, vstring_str(state->temp1));
if (*state->sender && state->fullname && *state->fullname) {
VSTRING *dst = vstring_alloc(100);
VSTRING *src = vstring_alloc(100);
- quote_822_local(src, addr);
+ quote_822_local(src, addr, QUOTE_FLAG_8BITCLEAN);
cleanup_rewrite_external(dst, STR(src));
unquote_822_local(result, STR(dst));
vstring_free(dst);
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 \
- match_parent_style.h
+ match_parent_style.h quote_flags.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
mail_copy.o: ../../include/vstring_vstream.h
mail_copy.o: ../../include/stringops.h
mail_copy.o: quote_822_local.h
+mail_copy.o: quote_flags.h
mail_copy.o: record.h
mail_copy.o: rec_type.h
mail_copy.o: mail_queue.h
mail_params.o: ../../include/vstring.h
mail_params.o: ../../include/vbuf.h
mail_params.o: ../../include/safe.h
+mail_params.o: ../../include/dict_db.h
+mail_params.o: ../../include/dict.h
+mail_params.o: ../../include/vstream.h
+mail_params.o: ../../include/argv.h
mail_params.o: mynetworks.h
mail_params.o: mail_conf.h
mail_params.o: mail_version.h
mail_params.o: mail_proto.h
-mail_params.o: ../../include/vstream.h
mail_params.o: ../../include/iostuff.h
mail_params.o: ../../include/attr.h
mail_params.o: verp_sender.h
mkmap_db.o: ../../include/vstream.h
mkmap_db.o: ../../include/argv.h
mkmap_db.o: ../../include/dict_db.h
+mkmap_db.o: mail_params.h
mkmap_db.o: mkmap.h
mkmap_dbm.o: mkmap_dbm.c
mkmap_dbm.o: ../../include/sys_defs.h
quote_821_local.o: ../../include/vstring.h
quote_821_local.o: ../../include/vbuf.h
quote_821_local.o: quote_821_local.h
+quote_821_local.o: quote_flags.h
quote_822_local.o: quote_822_local.c
quote_822_local.o: ../../include/sys_defs.h
quote_822_local.o: ../../include/vstring.h
quote_822_local.o: ../../include/vbuf.h
quote_822_local.o: quote_822_local.h
+quote_822_local.o: quote_flags.h
rec2stream.o: rec2stream.c
rec2stream.o: ../../include/sys_defs.h
rec2stream.o: ../../include/vstring.h
rewrite_clnt.o: ../../include/events.h
rewrite_clnt.o: ../../include/iostuff.h
rewrite_clnt.o: quote_822_local.h
+rewrite_clnt.o: quote_flags.h
rewrite_clnt.o: mail_proto.h
rewrite_clnt.o: ../../include/attr.h
rewrite_clnt.o: mail_params.h
*/
if (*string == '@') {
buffer = vstring_alloc(100);
- if ((ratsign = strchr(address, '@')) != 0)
+ if ((ratsign = strrchr(address, '@')) != 0)
vstring_strncpy(buffer, address, ratsign - address);
else
vstring_strcpy(buffer, address);
if (flags & (MAIL_COPY_FROM | MAIL_COPY_RETURN_PATH)) {
if (sender == 0)
msg_panic("%s: null sender", myname);
- quote_822_local(buf, sender);
+ quote_822_local(buf, sender, QUOTE_FLAG_8BITCLEAN);
if (flags & MAIL_COPY_FROM) {
time(&now);
vstream_fprintf(dst, "From %s %.24s%s", *sender == 0 ?
if (flags & MAIL_COPY_DELIVERED) {
if (delivered == 0)
msg_panic("%s: null delivered", myname);
- quote_822_local(buf, delivered);
+ quote_822_local(buf, delivered, QUOTE_FLAG_8BITCLEAN);
vstream_fprintf(dst, "Delivered-To: %s%s",
lowercase(vstring_str(buf)), eol);
}
check_sgid_group();
check_overlap();
#ifdef HAS_DB
- dict_db_mpool_size = var_db_read_buf;
+ dict_db_cache_size = var_db_read_buf;
#endif
/*
extern int var_db_create_buf;
#define VAR_DB_READ_BUF "berkeley_db_read_buffer_size"
-#define DEF_DB_READ_BUF (256 *1024)
+#define DEF_DB_READ_BUF (128 *1024)
extern int var_db_read_buf;
/* LICENSE
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20020505"
+#define MAIL_RELEASE_DATE "20020508"
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "1.1.8-" MAIL_RELEASE_DATE
MKMAP *mkmap = (MKMAP *) mymalloc(sizeof(*mkmap));
/*
- * Override the default mpool size for map (re)builds.
+ * Override the default per-table cache size for map (re)builds.
*
- * db_mpool_size" is defined in util/dict_db.c and defaults to 256K, which
+ * db_cache_size" is defined in util/dict_db.c and defaults to 128kB, which
* works well for the lookup code.
*
- * We use a larger memory pool when building ".db" files. For "hash" files
- * performance degrades rapidly unless the memory pool is O(file size).
+ * We use a larger per-table cache when building ".db" files. For "hash"
+ * files performance degrades rapidly unless the memory pool is O(file
+ * size).
*
* For "btree" files peformance is good with sorted input even for small
* memory pools, but with random input degrades rapidly unless the memory
* size becomes an object property, instead of being specified by poking
* a global variable so that it becomes a class property.
*/
- dict_db_mpool_size = var_db_create_buf;
+ dict_db_cache_size = var_db_create_buf;
/*
* Fill in the generic members.
/* SYNOPSIS
/* #include "quote_821_local.h"
/*
-/* VSTRING *quote_821_local(dst, src)
+/* VSTRING *quote_821_local(dst, src, flags)
/* VSTRING *dst;
/* char *src;
+/* int flags;
/* DESCRIPTION
/* quote_821_local() quotes the local part of a mailbox address and
/* returns a result that can be used in SMTP commands as specified
/* The result.
/* .IP src
/* The input address.
+/* .IP flags
+/* Bit-wise OR of zero or more of the following.
+/* .RS
+/* .IP QUOTE_FLAG_8BITCLEAN
+/* In violation with RFCs, treat 8-bit text as ordinary text.
+/* .IP QUOTE_FLAG_EXPOSE_AT
+/* In violation with RFCs, treat `@' as an ordinary character.
+/* .RE
/* STANDARDS
/* RFC 821 (SMTP protocol)
/* BUGS
/* is_821_dot_string - is this local-part an rfc 821 dot-string? */
-static int is_821_dot_string(char *local_part, char *end)
+static int is_821_dot_string(char *local_part, char *end, int flags)
{
char *cp;
int ch;
for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) {
if (ch == '.' && cp[1] == '.')
return (NO);
- if (ch > 127)
+ if (ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN))
return (NO);
if (ch == ' ')
return (NO);
|| ch == '[' || ch == ']'
|| ch == '\\' || ch == ','
|| ch == ';' || ch == ':'
- /* || ch == '@' */ || ch == '"')
+ || (ch == '@' && !(flags & QUOTE_FLAG_EXPOSE_AT)) || ch == '"')
return (NO);
}
if (cp[-1] == '.')
/* quote_821_local - quote local part of address according to rfc 821 */
-VSTRING *quote_821_local(VSTRING *dst, char *addr)
+VSTRING *quote_821_local(VSTRING *dst, char *addr, int flags)
{
char *at;
*/
if ((at = strrchr(addr, '@')) == 0) /* just in case */
at = addr + strlen(addr); /* should not happen */
- if (is_821_dot_string(addr, at)) {
+ if (is_821_dot_string(addr, at, flags)) {
return (vstring_strcpy(dst, addr));
} else {
make_821_quoted_string(dst, addr, at);
*/
#include <vstring.h>
+ /*
+ * Global library.
+ */
+#include <quote_flags.h>
+
/*
* External interface.
*/
-extern VSTRING *quote_821_local(VSTRING *, char *);
+extern VSTRING *quote_821_local(VSTRING *, char *, int);
/* LICENSE
/* .ad
/* SYNOPSIS
/* #include <quote_822_local.h>
/*
-/* VSTRING *quote_822_local(dst, src)
+/* VSTRING *quote_822_local(dst, src, flags)
/* VSTRING *dst;
/* const char *src;
+/* int flags;
/*
/* VSTRING *unquote_822_local(dst, src)
/* VSTRING *dst;
/* The result.
/* .IP src
/* The input address.
+/* .IP flags
+/* Bit-wise OR of zero or more of the following.
+/* .RS
+/* .IP QUOTE_FLAG_8BITCLEAN
+/* In violation with RFCs, treat 8-bit text as ordinary text.
+/* .IP QUOTE_FLAG_EXPOSE_AT
+/* In violation with RFCs, treat `@' as an ordinary character.
+/* .RE
/* STANDARDS
/* RFC 822 (ARPA Internet Text Messages)
/* BUGS
/* is_822_dot_string - is this local-part an rfc 822 dot-string? */
-static int is_822_dot_string(const char *local_part, const char *end)
+static int is_822_dot_string(const char *local_part, const char *end, int flags)
{
const char *cp;
int ch;
for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) {
if (ch == '.' && (cp + 1) < end && cp[1] == '.')
return (NO);
-#if 0
- if (ch > 127)
+ if (ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN))
return (NO);
-#endif
if (ch == ' ')
return (NO);
if (ISCNTRL(ch))
return (NO);
if (ch == '(' || ch == ')'
|| ch == '<' || ch == '>'
- /* || ch == '@' */ || ch == ','
+ || (ch == '@' && !(flags & QUOTE_FLAG_EXPOSE_AT)) || ch == ','
|| ch == ';' || ch == ':'
|| ch == '\\' || ch == '"'
|| ch == '[' || ch == ']')
/* make_822_quoted_string - make quoted-string from local-part */
static VSTRING *make_822_quoted_string(VSTRING *dst, const char *local_part,
- const char *end)
+ const char *end)
{
const char *cp;
int ch;
/* quote_822_local - quote local part of mailbox according to rfc 822 */
-VSTRING *quote_822_local(VSTRING *dst, const char *mbox)
+VSTRING *quote_822_local(VSTRING *dst, const char *mbox, int flags)
{
const char *start; /* first byte of localpart */
const char *end; /* first byte after localpart */
start = mbox;
if ((end = strrchr(start, '@')) == 0)
end = start + strlen(start);
- if (is_822_dot_string(start, end)) {
+ if (is_822_dot_string(start, end, flags)) {
return (vstring_strcpy(dst, mbox));
} else {
vstring_strncpy(dst, mbox, start - mbox);
*/
#include <vstring.h>
+ /*
+ * Global library.
+ */
+#include <quote_flags.h>
+
/*
* External interface.
*/
-extern VSTRING *quote_822_local(VSTRING *, const char *);
+extern VSTRING *quote_822_local(VSTRING *, const char *, int);
extern VSTRING *unquote_822_local(VSTRING *, const char *);
/* LICENSE
--- /dev/null
+/*++
+/* NAME
+/* quote_flags 3h
+/* SUMMARY
+/* quote rfc 821/822 local part
+/* SYNOPSIS
+/* #include "quote_flags.h"
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * External interface.
+ */
+#define QUOTE_FLAG_8BITCLEAN (1<<0) /* be 8-bit clean */
+#define QUOTE_FLAG_EXPOSE_AT (1<<1) /* @ is ordinary text */
+
+/* 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
+/*--*/
* Convert the address from internal address form to external RFC822
* form, then rewrite it. After rewriting, convert to internal form.
*/
- quote_822_local(src, addr);
+ quote_822_local(src, addr, QUOTE_FLAG_8BITCLEAN);
rewrite_clnt(ruleset, STR(src), dst);
unquote_822_local(result, STR(dst));
vstring_free(src);
lmtp_proto.o: ../../include/off_cvt.h
lmtp_proto.o: ../../include/mark_corrupt.h
lmtp_proto.o: ../../include/quote_821_local.h
+lmtp_proto.o: ../../include/quote_flags.h
lmtp_proto.o: lmtp.h
lmtp_proto.o: ../../include/argv.h
lmtp_proto.o: lmtp_sasl.h
*/
#define REWRITE_ADDRESS(addr) do { \
if (*(addr)) { \
- quote_821_local(state->scratch, addr); \
+ quote_821_local(state->scratch, addr, QUOTE_FLAG_8BITCLEAN); \
myfree(addr); \
addr = mystrdup(vstring_str(state->scratch)); \
lowercase(addr); \
delivered.o: ../../include/rec_type.h
delivered.o: ../../include/is_header.h
delivered.o: ../../include/quote_822_local.h
+delivered.o: ../../include/quote_flags.h
delivered.o: ../../include/header_opts.h
delivered.o: local.h
delivered.o: ../../include/been_here.h
* header. We must therefore apply the same transformation when looking
* up the recipient. Lowercase the delivered-to address for consistency.
*/
- quote_822_local(buf, address);
+ quote_822_local(buf, address, QUOTE_FLAG_8BITCLEAN);
lowercase(STR(buf));
ht = htable_locate(table, STR(buf));
return (ht != 0);
pipe.o: ../../include/split_addr.h
pipe.o: ../../include/off_cvt.h
pipe.o: ../../include/quote_822_local.h
+pipe.o: ../../include/quote_flags.h
pipe.o: ../../include/mail_server.h
* Quote the recipient address as appropriate.
*/
if (flags & PIPE_OPT_QUOTE_LOCAL)
- quote_822_local(buf, address);
+ quote_822_local(buf, address, QUOTE_FLAG_8BITCLEAN);
else
vstring_strcpy(buf, address);
buf = vstring_alloc(10);
if (attr.flags & PIPE_OPT_QUOTE_LOCAL) {
- quote_822_local(buf, request->sender);
+ quote_822_local(buf, request->sender, QUOTE_FLAG_8BITCLEAN);
dict_update(PIPE_DICT_TABLE, PIPE_DICT_SENDER, STR(buf));
} else
dict_update(PIPE_DICT_TABLE, PIPE_DICT_SENDER, request->sender);
postalias.o: ../../include/split_at.h
postalias.o: ../../include/get_hostname.h
postalias.o: ../../include/vstring_vstream.h
+postalias.o: ../../include/set_eugid.h
postalias.o: ../../include/tok822.h
postalias.o: ../../include/resolve_clnt.h
postalias.o: ../../include/mail_conf.h
postmap.o: ../../include/stringops.h
postmap.o: ../../include/split_at.h
postmap.o: ../../include/vstring_vstream.h
+postmap.o: ../../include/set_eugid.h
postmap.o: ../../include/mail_conf.h
postmap.o: ../../include/mail_params.h
postmap.o: ../../include/mkmap.h
qmqpd.o: ../../include/match_list.h
qmqpd.o: ../../include/match_ops.h
qmqpd.o: ../../include/quote_822_local.h
+qmqpd.o: ../../include/quote_flags.h
qmqpd.o: ../../include/match_parent_style.h
qmqpd.o: ../../include/mail_server.h
qmqpd.o: qmqpd.h
"\tby %s (%s) with %s id %s",
var_myhostname, var_mail_name,
state->protocol, state->queue_id);
- quote_822_local(state->buf, state->recipient);
+ quote_822_local(state->buf, state->recipient, QUOTE_FLAG_8BITCLEAN);
rec_fprintf(state->cleanup, REC_TYPE_NORM,
"\tfor <%s>; %s", STR(state->buf), mail_date(state->time));
} else {
showq.o: ../../include/record.h
showq.o: ../../include/rec_type.h
showq.o: ../../include/quote_822_local.h
+showq.o: ../../include/quote_flags.h
showq.o: ../../include/mail_addr.h
showq.o: ../../include/bounce_log.h
showq.o: ../../include/mail_server.h
case REC_TYPE_FROM:
if (*start == 0)
start = var_empty_addr;
- quote_822_local(printable_quoted_addr, start);
+ quote_822_local(printable_quoted_addr, start, QUOTE_FLAG_8BITCLEAN);
printable(STR(printable_quoted_addr), '?');
vstream_fprintf(client, DATA_FORMAT, id, status,
msg_size > 0 ? msg_size : size, arrival_time > 0 ?
case REC_TYPE_RCPT:
if (*start == 0) /* can't happen? */
start = var_empty_addr;
- quote_822_local(printable_quoted_addr, start);
+ quote_822_local(printable_quoted_addr, start, QUOTE_FLAG_8BITCLEAN);
printable(STR(printable_quoted_addr), '?');
if (dup_filter == 0
|| htable_locate(dup_filter, STR(printable_quoted_addr)) == 0)
smtp_proto.o: ../../include/off_cvt.h
smtp_proto.o: ../../include/mark_corrupt.h
smtp_proto.o: ../../include/quote_821_local.h
+smtp_proto.o: ../../include/quote_flags.h
smtp_proto.o: smtp.h
smtp_proto.o: ../../include/argv.h
smtp_proto.o: smtp_sasl.h
*/
#define REWRITE_ADDRESS(addr) do { \
if (*(addr)) { \
- quote_821_local(state->scratch, addr); \
+ quote_821_local(state->scratch, addr, QUOTE_FLAG_8BITCLEAN); \
smtp_unalias_addr(state->scratch2, vstring_str(state->scratch)); \
myfree(addr); \
addr = mystrdup(vstring_str(state->scratch2)); \
#define QUOTE_ADDRESS(addr) do { \
if (*(addr)) { \
- quote_821_local(state->scratch, addr); \
+ quote_821_local(state->scratch, addr, QUOTE_FLAG_8BITCLEAN); \
myfree(addr); \
addr = mystrdup(vstring_str(state->scratch)); \
} \
return (SMTPD_CHECK_OK);
domain += 1;
+ /*
+ * Skip source-routed non-local or virtual mail (uncertain destination).
+ */
+ if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED))
+ return (SMTPD_CHECK_DUNNO);
+
/*
* Permit final delivery: the destination matches mydestination,
* virtual_maps, or virtual_mailbox_maps.
if (resolve_final(state, recipient, domain))
return (SMTPD_CHECK_OK);
- /*
- * Skip source-routed mail (uncertain destination).
- */
- if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED))
- return (SMTPD_CHECK_DUNNO);
-
/*
* Permit if the destination matches the relay_domains list.
*/
resolve.o: ../../include/resolve_local.h
resolve.o: ../../include/mail_conf.h
resolve.o: ../../include/quote_822_local.h
+resolve.o: ../../include/quote_flags.h
resolve.o: ../../include/tok822.h
resolve.o: ../../include/resolve_clnt.h
resolve.o: trivial-rewrite.h
/*
* The address is in internalized (unquoted) form, so we must externalize
* it first before we can parse it.
+ *
+ * While quoting the address local part, do not treat @ as a special
+ * character. This allows us to detect extra @ characters and block
+ * source routed relay attempts.
*/
- quote_822_local(addr_buf, addr);
+ quote_822_local(addr_buf, addr,
+ QUOTE_FLAG_8BITCLEAN | QUOTE_FLAG_EXPOSE_AT);
tree = tok822_scan_addr(vstring_str(addr_buf));
/*
/* SYNOPSIS
/* #include <dict_db.h>
/*
-/* int dict_db_mpool_size;
+/* int dict_db_cache_size;
/*
/* DICT *dict_hash_open(path, open_flags, dict_flags)
/* const char *path;
/* a pointer to a structure that can be used to access the dictionary
/* using the generic methods documented in dict_open(3).
/*
-/* The dict_db_mpool_size variable specifies a non-default I/O buffer
-/* size. The default buffer size is adequate for reading. For better
-/* performance while creating a large table, specify a large buffer size
-/* before opening the file.
+/* The dict_db_cache_size variable specifies a non-default per-table
+/* I/O buffer size. The default buffer size is adequate for reading.
+/* For better performance while creating a large table, specify a large
+/* buffer size before opening the file.
/*
/* Arguments:
/* .IP path
} DICT_DB;
/*
- * You can override the default dict_db_mpool_size setting before calling
+ * You can override the default dict_db_cache_size setting before calling
* dict_hash_open() or dict_btree_open(). This is done in mkmap_db_open() to
* set a larger memory pool for database (re)builds.
*
* object property, instead of being specified by poking a global variable
* so that it becomes a class property.
*/
+int dict_db_cache_size = (128 * 1024); /* 128K default memory pool */
+
#define DICT_DB_NELM 4096
-int dict_db_mpool_size = (256 * 1024); /* 256K default memory pool */
#if DB_VERSION_MAJOR > 1
#endif
-#if DB_VERSION_MAJOR > 1
-
-static DB_ENV *dict_db_env;
-static int dict_db_refcount;
-
-/* dict_db_env_alloc - allocate shared environment */
-
-static int dict_db_env_alloc(DB_ENV ** env)
-{
- int err;
-
- /*
- * Allocate a new environment if this is the first database. Bump the
- * reference count so we can deallocate the environment when the last
- * database is closed.
- */
- if (dict_db_env != 0) {
- ++dict_db_refcount;
- *env = dict_db_env;
- return (0);
- }
-#if DB_VERSION_MAJOR == 2
-#define DICT_DB_ENV_FLAGS (DB_CREATE|DB_INIT_MPOOL|DB_MPOOL_PRIVATE)
-
- dict_db_env = (DB_ENV *) mymalloc(sizeof(DB_ENV));
- memset((char *) dict_db_env, 0, sizeof(DB_ENV));
- dict_db_env->mp_size = dict_db_mpool_size;
-
- if ((err = db_appinit(0, 0, dict_db_env, DICT_DB_ENV_FLAGS)) != 0) {
- myfree((char *) dict_db_env);
- dict_db_env = 0;
- return (err);
- }
-#endif /* DB_VERSION_MAJOR == 2 */
-
-#if DB_VERSION_MAJOR > 2
-#define DICT_DB_ENV_FLAGS (DB_CREATE|DB_INIT_MPOOL|DB_PRIVATE)
-
- err = db_env_create(&dict_db_env, 0);
- if (err == 0)
- err = dict_db_env->set_cachesize(dict_db_env, 0, dict_db_mpool_size, 1);
- if (err == 0)
- err = dict_db_env->open(dict_db_env, 0, DICT_DB_ENV_FLAGS, 0644);
-
- if (err != 0) {
- if (dict_db_env)
- dict_db_env->close(dict_db_env, 0);
- dict_db_env = 0;
- return (err);
- }
-#endif /* DB_VERSION_MAJOR > 2 */
-
- ++dict_db_refcount;
- *env = dict_db_env;
- return (0);
-}
-
-static void dict_db_env_free(void)
-{
-
- /*
- * Deallocate a database within the environment Free the environment when
- * the last database is closed
- */
-
-#if DB_VERSION_MAJOR == 2
- if (dict_db_env && dict_db_refcount > 0 && --dict_db_refcount == 0) {
- db_appexit(dict_db_env);
- myfree((char *) dict_db_env);
- dict_db_env = 0;
- }
-#endif
-
-#if DB_VERSION_MAJOR > 2
- if (dict_db_env && dict_db_refcount > 0 && --dict_db_refcount == 0) {
- dict_db_env->close(dict_db_env, 0);
- dict_db_env = 0;
- }
-#endif
-}
-
-#endif /* DB_VERSION_MAJOR > 1 */
-
/* dict_db_lookup - find database entry */
static const char *dict_db_lookup(DICT *dict, const char *name)
msg_fatal("flush database %s: %m", dict_db->dict.name);
if (DICT_DB_CLOSE(dict_db->db) < 0)
msg_fatal("close database %s: %m", dict_db->dict.name);
-
-#if DB_VERSION_MAJOR > 1
- dict_db_env_free();
-#endif
-
dict_free(dict);
}
#if DB_VERSION_MAJOR > 1
int db_flags;
- DB_ENV *env;
#endif
db_flags |= DB_CREATE;
if (open_flags & O_TRUNC)
db_flags |= DB_TRUNCATE;
- if ((errno = dict_db_env_alloc(&env)) != 0)
- msg_fatal("create DB environment: %m");
- if ((errno = db_open(db_path, type, db_flags, 0644, env, tweak, &db)) != 0)
+ if ((errno = db_open(db_path, type, db_flags, 0644, 0, tweak, &db)) != 0)
msg_fatal("open database %s: %m", db_path);
if (db == 0)
msg_panic("db_open null result");
db_flags |= DB_CREATE;
if (open_flags & O_TRUNC)
db_flags |= DB_TRUNCATE;
- if ((errno = dict_db_env_alloc(&env)) != 0)
- msg_fatal("create DB environment: %m");
- if ((errno = db_create(&db, env, 0)) != 0)
+ if ((errno = db_create(&db, 0, 0)) != 0)
msg_fatal("create DB database: %m");
if (db == 0)
msg_panic("db_create null result");
+ if ((errno = db->set_cachesize(db, 0, dict_db_cache_size, 0)) != 0)
+ msg_fatal("set DB cache size %d: %m", dict_db_cache_size);
if (type == DB_HASH && db->set_h_nelem(db, DICT_DB_NELM) != 0)
msg_fatal("set DB hash element count %d: %m", DICT_DB_NELM);
if ((errno = db->open(db, db_path, 0, type, db_flags, 0644)) != 0)
memset((char *) &tweak, 0, sizeof(tweak));
tweak.nelem = DICT_DB_NELM;
- tweak.cachesize = dict_db_mpool_size;
+ tweak.cachesize = dict_db_cache_size;
#endif
#if DB_VERSION_MAJOR == 2
DB_INFO tweak;
memset((char *) &tweak, 0, sizeof(tweak));
tweak.h_nelem = DICT_DB_NELM;
+ tweak.db_cachesize = dict_db_cache_size;
#endif
#if DB_VERSION_MAJOR > 2
void *tweak;
BTREEINFO tweak;
memset((char *) &tweak, 0, sizeof(tweak));
- tweak.cachesize = dict_db_mpool_size;
+ tweak.cachesize = dict_db_cache_size;
#endif
#if DB_VERSION_MAJOR == 2
DB_INFO tweak;
memset((char *) &tweak, 0, sizeof(tweak));
+ tweak.db_cachesize = dict_db_cache_size;
#endif
#if DB_VERSION_MAJOR > 2
void *tweak;
/*
* XXX Should be part of the DICT interface.
*/
-extern int dict_db_mpool_size;
+extern int dict_db_cache_size;
/* LICENSE
/* .ad
$(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
- @$(EXPORT) @make -f Makefile.in Makefile
+ @$(EXPORT) make -f Makefile.in Makefile
# do not edit below this line - it is generated by 'make depend'
deliver_attr.o: deliver_attr.c