diff --git a/postfix/HISTORY b/postfix/HISTORY index 5b94ef6ce..3e1e22249 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -19217,10 +19217,24 @@ Apologies for any names omitted. html/Makefile.in, man/Makefile.in, proto/DATABASE_README.html, postconf/postconf.c, proto/socketmap_table, proto/lmdb_table. -20121122 +20131122 Documentation: missing database hyperlinks, refined text about partial lookup keys. Files: mantools/postlink, proto/DATABASE_README.html, proto/lmdb_table, proto/socketmap_table. +20131123 + + Feature: support for NOTIFY parameter in the Milter + SMFIR_ADDRCPT_PAR request. Contributed by by Andrew Ayer. + Wietse added support for ORCPT. Files: cleanup/cleanup.h, + cleanup/cleanup_milter.c, cleanup/cleanup_state.c, + global/xtext.c, global/xtext.h, milter/test-milter.c. + +20131124 + + Cleanup: remove extra blank line from ccformat output, + making it compatible with the script that Wietse actually + uses (this line was part of a test to detect file truncation, + but it is now obsolete). File: mantools/ccformat. diff --git a/postfix/mantools/ccformat b/postfix/mantools/ccformat index 3573a6dc8..c9ec6aeb6 100755 --- a/postfix/mantools/ccformat +++ b/postfix/mantools/ccformat @@ -64,7 +64,8 @@ case $# in { # some versions of indent return garbage exit status -- gack! (indent $FLAGS <$i 2>.ind.$$ >$TMPF || test ! -s .ind.$$) >$TMPF && # try a device full check - echo >>$TMPF && ( + # echo >>$TMPF && + ( # ignore interrupts while we overwrite the original file trap '' 1 2 3 15; cp $TMPF $i ) && echo replaced; } || { echo replacement FAILED; exit 1; } diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in index 28afe9df6..289cea262 100644 --- a/postfix/src/cleanup/Makefile.in +++ b/postfix/src/cleanup/Makefile.in @@ -1024,6 +1024,7 @@ cleanup_milter.o: ../../include/tok822.h cleanup_milter.o: ../../include/vbuf.h cleanup_milter.o: ../../include/vstream.h cleanup_milter.o: ../../include/vstring.h +cleanup_milter.o: ../../include/xtext.h cleanup_milter.o: cleanup.h cleanup_milter.o: cleanup_milter.c cleanup_out.o: ../../include/argv.h diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index 9b9d6279d..eca0785c6 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -114,6 +114,7 @@ typedef struct CLEANUP_STATE { VSTRING *milter_err_text; /* milter call-back reply */ HBC_CHECKS *milter_hbc_checks; /* Milter header checks */ VSTRING *milter_hbc_reply; /* Milter header checks reply */ + VSTRING *milter_orcpt_buf; /* add_rcpt_par() orcpt */ /* * Support for Milter body replacement requests. diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c index e6a74e84d..db38c911f 100644 --- a/postfix/src/cleanup/cleanup_milter.c +++ b/postfix/src/cleanup/cleanup_milter.c @@ -106,6 +106,7 @@ #include #include #include +#include /* Application-specific. */ @@ -1388,9 +1389,10 @@ static const char *cleanup_chg_from(void *context, const char *ext_from, return (CLEANUP_OUT_OK(state) ? 0 : cleanup_milter_error(state, 0)); } -/* cleanup_add_rcpt - append recipient address */ +/* cleanup_add_rcpt_par - append recipient address, with ESMTP arguments */ -static const char *cleanup_add_rcpt(void *context, const char *ext_rcpt) +static const char *cleanup_add_rcpt_par(void *context, const char *ext_rcpt, + const char *esmtp_args) { const char *myname = "cleanup_add_rcpt"; CLEANUP_STATE *state = (CLEANUP_STATE *) context; @@ -1400,7 +1402,45 @@ static const char *cleanup_add_rcpt(void *context, const char *ext_rcpt) TOK822 *tree; TOK822 *tp; VSTRING *int_rcpt_buf; + ARGV *esmtp_argv; + int dsn_notify = 0; + const char *dsn_orcpt_info = 0; + size_t type_len; + int i; + const char *arg; + const char *arg_val; + if (esmtp_args[0]) { + esmtp_argv = argv_split(esmtp_args, " "); + for (i = 0; i < esmtp_argv->argc; ++i) { + arg = esmtp_argv->argv[i]; + if (strncasecmp(arg, "NOTIFY=", 7) == 0) { /* RFC 3461 */ + if (dsn_notify || (dsn_notify = dsn_notify_mask(arg + 7)) == 0) + msg_warn("%s: Bad NOTIFY parameter from MILTER: \"%.100s\"", + state->queue_id, arg); + } else if (strncasecmp(arg, "ORCPT=", 6) == 0) { /* RFC 3461 */ + if (state->milter_orcpt_buf == 0) + state->milter_orcpt_buf = vstring_alloc(100); + if (dsn_orcpt_info + || (type_len = strcspn(arg_val = arg + 6, ";")) == 0 + || (arg_val)[type_len] != ';' + || xtext_unquote_append( + vstring_sprintf(state->milter_orcpt_buf, + "%.*s;", (int) type_len, + arg_val), + arg_val + type_len + 1) == 0) { + msg_warn("%s: Bad ORCPT parameter from MILTER: \"%.100s\"", + state->queue_id, arg); + } else { + dsn_orcpt_info = STR(state->milter_orcpt_buf); + } + } else { + msg_warn("%s: ignoring ESMTP argument from MILTER: \"%.100s\"", + state->queue_id, arg); + } + } + argv_free(esmtp_argv); + } if (msg_verbose) msg_info("%s: \"%s\"", myname, ext_rcpt); @@ -1426,8 +1466,6 @@ static const char *cleanup_add_rcpt(void *context, const char *ext_rcpt) * overwrite the old "recipient append" pointer with the forward pointer * to the new recipient. */ -#define NO_DSN_ORCPT ((char *) 0) - if ((new_rcpt_offset = vstream_fseek(state->dst, (off_t) 0, SEEK_END)) < 0) { msg_warn("%s: seek file %s: %m", myname, cleanup_path); return (cleanup_milter_error(state, errno)); @@ -1454,7 +1492,8 @@ static const char *cleanup_add_rcpt(void *context, const char *ext_rcpt) } } tok822_free_tree(tree); - cleanup_addr_bcc_dsn(state, STR(int_rcpt_buf), NO_DSN_ORCPT, DEF_DSN_NOTIFY); + cleanup_addr_bcc_dsn(state, STR(int_rcpt_buf), dsn_orcpt_info, + dsn_notify ? dsn_notify : DEF_DSN_NOTIFY); vstring_free(int_rcpt_buf); if (addr_count == 0) { msg_warn("%s: ignoring attempt from Milter to add null recipient", @@ -1494,18 +1533,11 @@ static const char *cleanup_add_rcpt(void *context, const char *ext_rcpt) return (CLEANUP_OUT_OK(state) ? 0 : cleanup_milter_error(state, 0)); } -/* cleanup_add_rcpt_par - append recipient address, ignore ESMTP arguments */ +/* cleanup_add_rcpt - append recipient address */ -static const char *cleanup_add_rcpt_par(void *context, const char *ext_rcpt, - const char *esmtp_args) +static const char *cleanup_add_rcpt(void *context, const char *ext_rcpt) { - const char *myname = "cleanup_add_rcpt"; - CLEANUP_STATE *state = (CLEANUP_STATE *) context; - - if (esmtp_args[0]) - msg_warn("%s: %s: ignoring ESMTP arguments \"%.100s\"", - state->queue_id, myname, esmtp_args); - return (cleanup_add_rcpt(context, ext_rcpt)); + return (cleanup_add_rcpt_par(context, ext_rcpt, "")); } /* cleanup_del_rcpt - remove recipient and all its expansions */ diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c index 8d9085262..50e90f158 100644 --- a/postfix/src/cleanup/cleanup_state.c +++ b/postfix/src/cleanup/cleanup_state.c @@ -101,6 +101,7 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src) state->append_meta_pt_target = -1; state->milter_hbc_checks = 0; state->milter_hbc_reply = 0; + state->milter_orcpt_buf = 0; state->rcpt_count = 0; state->reason = 0; state->smtp_reply = 0; @@ -159,6 +160,8 @@ void cleanup_state_free(CLEANUP_STATE *state) myfree(state->reason); if (state->smtp_reply) myfree(state->smtp_reply); + if (state->milter_orcpt_buf) + vstring_free(state->milter_orcpt_buf); nvtable_free(state->attr); if (state->mime_state) mime_state_free(state->mime_state); diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 10cbb6eb2..00973bb01 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20131122" +#define MAIL_RELEASE_DATE "20131126" #define MAIL_VERSION_NUMBER "2.11" #ifdef SNAPSHOT diff --git a/postfix/src/global/xtext.c b/postfix/src/global/xtext.c index 3bcb8c3d4..4e7373344 100644 --- a/postfix/src/global/xtext.c +++ b/postfix/src/global/xtext.c @@ -19,6 +19,10 @@ /* VSTRING *xtext_unquote(unquoted, quoted) /* VSTRING *unquoted; /* const char *quoted; +/* +/* VSTRING *xtext_unquote_append(unquoted, quoted) +/* VSTRING *unquoted; +/* const char *quoted; /* DESCRIPTION /* xtext_quote() takes a null-terminated string and replaces characters /* +, <33(10) and >126(10), as well as characters specified with "special" @@ -31,6 +35,9 @@ /* understands lowercase, uppercase, and mixed case +XX sequences. The /* result value is the unquoted argument in case of success, a null pointer /* otherwise. +/* +/* xtext_unquote_append() is like xtext_unquote(), but appends +/* the conversion result to the result buffer. /* BUGS /* This module cannot process null characters in data. /* LICENSE @@ -90,14 +97,13 @@ VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special) return (quoted); } -/* xtext_unquote - quoted data to unquoted */ +/* xtext_unquote_append - quoted data to unquoted */ -VSTRING *xtext_unquote(VSTRING *unquoted, const char *quoted) +VSTRING *xtext_unquote_append(VSTRING *unquoted, const char *quoted) { const char *cp; int ch; - VSTRING_RESET(unquoted); for (cp = quoted; (ch = *cp) != 0; cp++) { if (ch == '+') { if (ISDIGIT(cp[1])) @@ -123,6 +129,14 @@ VSTRING *xtext_unquote(VSTRING *unquoted, const char *quoted) VSTRING_TERMINATE(unquoted); return (unquoted); } +/* xtext_unquote - quoted data to unquoted */ + +VSTRING *xtext_unquote(VSTRING *unquoted, const char *quoted) +{ + VSTRING_RESET(unquoted); + xtext_unquote_append(unquoted, quoted); + return (unquoted); +} #ifdef TEST diff --git a/postfix/src/global/xtext.h b/postfix/src/global/xtext.h index 1515242d3..c7680622d 100644 --- a/postfix/src/global/xtext.h +++ b/postfix/src/global/xtext.h @@ -22,6 +22,7 @@ extern VSTRING *xtext_quote(VSTRING *, const char *, const char *); extern VSTRING *xtext_quote_append(VSTRING *, const char *, const char *); extern VSTRING *xtext_unquote(VSTRING *, const char *); +extern VSTRING *xtext_unquote_append(VSTRING *, const char *); /* LICENSE /* .ad diff --git a/postfix/src/milter/test-milter.c b/postfix/src/milter/test-milter.c index 26be0f7c2..a89ae34ff 100644 --- a/postfix/src/milter/test-milter.c +++ b/postfix/src/milter/test-milter.c @@ -20,8 +20,8 @@ /* Specifies a non-default reply for the MTA command specified /* with \fB-c\fR. The default is \fBtempfail\fR. /* .IP "\fB-A address\fR" -/* Add the specified recipient address. Multiple -A options -/* are supported. +/* Add the specified recipient address (specify ESMTP parameters +/* separated by space). Multiple -A options are supported. /* .IP "\fB-b pathname /* Replace the message body by the content of the specified file. /* .IP "\fB-c connect|helo|mail|rcpt|data|header|eoh|body|eom|unknown|close|abort\fR" @@ -358,10 +358,20 @@ static sfsistat test_eom(SMFICTX *ctx) #endif { int count; + char *args; - for (count = 0; count < add_rcpt_count; count++) - if (smfi_addrcpt(ctx, add_rcpt[count]) == MI_FAILURE) - fprintf(stderr, "smfi_addrcpt `%s' failed\n", add_rcpt[count]); + for (count = 0; count < add_rcpt_count; count++) { + if ((args = strchr(add_rcpt[count], ' ')) != 0) { + *args++ = 0; + if (smfi_addrcpt_par(ctx, add_rcpt[count], args) == MI_FAILURE) + fprintf(stderr, "smfi_addrcpt_par `%s' `%s' failed\n", + add_rcpt[count], args); + } else { + if (smfi_addrcpt(ctx, add_rcpt[count]) == MI_FAILURE) + fprintf(stderr, "smfi_addrcpt `%s' failed\n", + add_rcpt[count]); + } + } for (count = 0; count < del_rcpt_count; count++) if (smfi_delrcpt(ctx, del_rcpt[count]) == MI_FAILURE)