From 73a6977944ea11e173821b18bcc2aeea38c3e67d Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Sun, 20 Jul 2014 00:00:00 -0500 Subject: [PATCH] postfix-2.12-20140720 --- postfix/.indent.pro | 1 + postfix/HISTORY | 15 ++++ postfix/WISHLIST | 5 ++ postfix/html/bounce.5.html | 58 ++++++++------ postfix/html/postconf.5.html | 9 +-- postfix/man/man5/bounce.5 | 12 +++ postfix/man/man5/postconf.5 | 8 +- postfix/proto/bounce | 12 +++ postfix/proto/postconf.proto | 9 +-- postfix/src/bounce/Makefile.in | 1 + postfix/src/bounce/bounce_notify_util.c | 55 +++++++------ postfix/src/bounce/bounce_service.h | 1 - postfix/src/bounce/bounce_template.c | 51 +++++++++++- postfix/src/global/mail_version.h | 2 +- postfix/src/global/uxtext.c | 4 +- postfix/src/global/xtext.c | 4 +- postfix/src/util/Makefile.in | 4 +- postfix/src/util/mac_expand.c | 7 +- postfix/src/util/mac_expand.h | 1 + postfix/src/util/midna.c | 100 ++++++++++++++++++++++-- postfix/src/util/midna.h | 1 + 21 files changed, 283 insertions(+), 77 deletions(-) diff --git a/postfix/.indent.pro b/postfix/.indent.pro index c690ce828..37dcdeaef 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -26,6 +26,7 @@ -TBOUNCE_LOG_FORGE -TBOUNCE_LOG_RCPT_BUF -TBOUNCE_STAT +-TBOUNCE_STR_PARAMETER -TBOUNCE_TEMPLATE -TBOUNCE_TEMPLATES -TBOUNCE_TIME_DIVISOR diff --git a/postfix/HISTORY b/postfix/HISTORY index 51ea7b184..00297dba2 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -20261,3 +20261,18 @@ Apologies for any names omitted. Cleanup: hard-coded GCC dependencies. Eray Aslan. File: makedefs. + +20140717 + + Safety: manipulate unsigned characters while decoding. + Files: global/xtext.c, global/uxtext.c. + + Infrastructure: ACE label to UTF-8 conversion. Files: + util/midna.[hc]. + + Infrastructure: macro expansion with printable() filter. + Files: util/mac_expand.[hc]. + + Feature: when expanding myhostname or mydomain in bounce + template messages, and smtputf8_enable=yes, convert ACE + (xn--mumble) labels into UTF-8. bounce/bounce_template.c. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 7f4be0f6b..dffb68ea2 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -8,6 +8,11 @@ Wish list: Things to do after the stable release: + up-convert myhostname in MIME boundary strings? + + Table-driven case folding and case-insensitive string + comparison specifically for UTF-8. + When downgrading message/global to 7bit, is quoted-printable the appropriate encoding? Should it be base64? diff --git a/postfix/html/bounce.5.html b/postfix/html/bounce.5.html index 1c0860e97..18051cd40 100644 --- a/postfix/html/bounce.5.html +++ b/postfix/html/bounce.5.html @@ -16,16 +16,16 @@ BOUNCE(5) BOUNCE(5) DESCRIPTION The Postfix bounce(8) server produces delivery status notification - (DSN) messages for undeliverable mail, delayed mail, successful deliv- + (DSN) messages for undeliverable mail, delayed mail, successful deliv‐ ery or address verification requests. By default, these notifications are generated from built-in templates with message headers and message text. Sites can override the built-in - information by specifying a bounce template file with the bounce_tem- - plate_file configuration parameter. + information by specifying a bounce template file with the bounce_tem‐‐ + plate_file configuration parameter. - This document describes the general procedure to create a bounce tem- - plate file, followed by the specific details of bounce template for- + This document describes the general procedure to create a bounce tem‐ + plate file, followed by the specific details of bounce template for‐ mats. GENERAL PROCEDURE @@ -44,7 +44,7 @@ BOUNCE(5) BOUNCE(5) expansion of time value parameters that appear in the delayed mail notification text. - Once the result is satisfactory, copy the template to the Postfix con- + Once the result is satisfactory, copy the template to the Postfix con‐ figuration directory and specify in main.cf something like: /etc/postfix/main.cf: @@ -53,13 +53,13 @@ BOUNCE(5) BOUNCE(5) TEMPLATE FILE FORMAT The template file can specify templates for failed mail, delayed mail, successful delivery or for address verification. These templates are - named failure_template, delay_template, success_template and ver- + named failure_template, delay_template, success_template and ver‐‐ ify_template, respectively. You can but do not have to specify all four templates in a bounce template file. Each template starts with "template_name = <<EOF" and ends with a line that contains the word "EOF" only. You can change the word EOF, but you - can't enclose it in quotes as with the shell or with Perl (tem- + can't enclose it in quotes as with the shell or with Perl (tem‐ plate_name = <<'EOF'). Here is an example: # The failure template is used for undeliverable mail. @@ -83,16 +83,16 @@ BOUNCE(5) BOUNCE(5) The mail system EOF - The usage and specification of bounce templates is subject to the fol- + The usage and specification of bounce templates is subject to the fol‐ lowing restrictions: - o No special meaning is given to the backslash character or to + · No special meaning is given to the backslash character or to leading whitespace; these are always taken literally. - o Inside the << context, the "$" character is special. To produce + · Inside the << context, the "$" character is special. To produce a "$" character as output, specify "$$". - o Outside the << context, lines beginning with "#" are ignored, as + · Outside the << context, lines beginning with "#" are ignored, as are empty lines, and lines consisting of whitespace only. Examples of all templates can be found in the file bounce.cf.default in @@ -100,7 +100,7 @@ BOUNCE(5) BOUNCE(5) TEMPLATE HEADER FORMAT The first portion of a bounce template consists of optional template - headers. Some become message headers in the delivery status notifica- + headers. Some become message headers in the delivery status notifica‐ tion; some control the formatting of that notification. Headers not specified in a template will be left at their default value. @@ -114,26 +114,26 @@ BOUNCE(5) BOUNCE(5) notification. Subject: - The subject in the message header of the delivery status notifi- + The subject in the message header of the delivery status notifi‐ cation that is returned to the sender. Postmaster-Subject: - The subject that will be used in Postmaster copies of undeliver- + The subject that will be used in Postmaster copies of undeliver‐ able or delayed mail notifications. These copies are sent under control of the notify_classes configuration parameter. The usage and specification of template message headers is subject to the following restrictions: - o Template message header names can be specified in upper case, + · Template message header names can be specified in upper case, lower case or mixed case. Postfix always produces bounce message header labels of the form "From:" and "Subject:". - o Template message headers must not span multiple lines. + · Template message headers must not span multiple lines. - o Template message headers do not support $parameter expansions. + · Template message headers do not support $parameter expansions. - o Template message headers must contain ASCII characters only, and + · Template message headers must contain ASCII characters only, and must not contain ASCII null characters. TEMPLATE MESSAGE TEXT FORMAT @@ -153,16 +153,30 @@ BOUNCE(5) BOUNCE(5) expressed in the time unit specified by suffix. See above under delay_warning_time for possible suffix values. + mydomain + Expands into the value of the mydomain parameter. With "smt‐ + putf8_enable = yes", this replaces ACE labels (xn--mumble) with + their UTF-8 equivalent. + + This feature is available in Postfix 2.12. + + myhostname + Expands into the value of the myhostname parameter. With "smt‐ + putf8_enable = yes", this replaces ACE labels (xn--mumble) with + their UTF-8 equivalent. + + This feature is available in Postfix 2.12. + The usage and specification of template message text is subject to the following restrictions: - o The template message text is not sent in Postmaster copies of + · The template message text is not sent in Postmaster copies of delivery status notifications. - o If the template message text contains non-ASCII characters, + · If the template message text contains non-ASCII characters, Postfix requires that the Charset: template header is updated. Specify an appropriate superset of US-ASCII. A superset is - needed because Postfix appends ASCII text after the message tem- + needed because Postfix appends ASCII text after the message tem‐ plate when it sends a delivery status notification. SEE ALSO diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 90a52c4fa..8af0a3cce 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -16413,13 +16413,12 @@ daemon. daemon.
forward
Local forwarding or aliasing. When -a message is received with "SMTPUTF8 requested", then the forwarded -(aliased) message automatically has "SMTPUTF8 requested".
+a message is received with "SMTPUTF8 required", then the forwarded +(aliased) message always has "SMTPUTF8 required".
bounce
Submission by the bounce(8) daemon. -When a message is received with "SMTPUTF8 requested", then the -delivery status notification automatically has "SMTPUTF8 requested". -
+When a message is received with "SMTPUTF8 required", then the +delivery status notification always has "SMTPUTF8 required".
notify
Postmaster notification from the smtp(8) or smtpd(8) daemon.
diff --git a/postfix/man/man5/bounce.5 b/postfix/man/man5/bounce.5 index f039f1810..b8aa51bca 100644 --- a/postfix/man/man5/bounce.5 +++ b/postfix/man/man5/bounce.5 @@ -178,6 +178,18 @@ Expands into the value of the \fBmaximal_queue_lifetime\fR parameter, expressed in the time unit specified by \fIsuffix\fR. See above under \fBdelay_warning_time\fR for possible \fIsuffix\fR values. +.IP \fBmydomain\fR +Expands into the value of the \fBmydomain\fR parameter. +With "smtputf8_enable = yes", this replaces ACE labels +(xn--mumble) with their UTF-8 equivalent. +.sp +This feature is available in Postfix 2.12. +.IP \fBmyhostname\fR +Expands into the value of the \fBmyhostname\fR parameter. +With "smtputf8_enable = yes", this replaces ACE labels +(xn--mumble) with their UTF-8 equivalent. +.sp +This feature is available in Postfix 2.12. .PP The usage and specification of template message text is subject to the following restrictions: diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 7c73e1d07..50471fc47 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -11229,13 +11229,13 @@ daemon. .br .IP "\fB forward \fR" Local forwarding or aliasing. When -a message is received with "SMTPUTF8 requested", then the forwarded -(aliased) message automatically has "SMTPUTF8 requested". +a message is received with "SMTPUTF8 required", then the forwarded +(aliased) message always has "SMTPUTF8 required". .br .IP "\fB bounce \fR" Submission by the \fBbounce\fR(8) daemon. -When a message is received with "SMTPUTF8 requested", then the -delivery status notification automatically has "SMTPUTF8 requested". +When a message is received with "SMTPUTF8 required", then the +delivery status notification always has "SMTPUTF8 required". .br .IP "\fB notify \fR" Postmaster notification from the diff --git a/postfix/proto/bounce b/postfix/proto/bounce index a76da97c7..b838f5c3a 100644 --- a/postfix/proto/bounce +++ b/postfix/proto/bounce @@ -164,6 +164,18 @@ # parameter, expressed in the time unit specified by # \fIsuffix\fR. See above under \fBdelay_warning_time\fR for # possible \fIsuffix\fR values. +# .IP \fBmydomain\fR +# Expands into the value of the \fBmydomain\fR parameter. +# With "smtputf8_enable = yes", this replaces ACE labels +# (xn--mumble) with their UTF-8 equivalent. +# .sp +# This feature is available in Postfix 2.12. +# .IP \fBmyhostname\fR +# Expands into the value of the \fBmyhostname\fR parameter. +# With "smtputf8_enable = yes", this replaces ACE labels +# (xn--mumble) with their UTF-8 equivalent. +# .sp +# This feature is available in Postfix 2.12. # .PP # The usage and specification of template message text is # subject to the following restrictions: diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 98a82e2f0..908d19dbc 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -16097,13 +16097,12 @@ daemon. daemon.
forward
Local forwarding or aliasing. When -a message is received with "SMTPUTF8 requested", then the forwarded -(aliased) message automatically has "SMTPUTF8 requested".
+a message is received with "SMTPUTF8 required", then the forwarded +(aliased) message always has "SMTPUTF8 required".
bounce
Submission by the bounce(8) daemon. -When a message is received with "SMTPUTF8 requested", then the -delivery status notification automatically has "SMTPUTF8 requested". -
+When a message is received with "SMTPUTF8 required", then the +delivery status notification always has "SMTPUTF8 required".
notify
Postmaster notification from the smtp(8) or smtpd(8) daemon.
diff --git a/postfix/src/bounce/Makefile.in b/postfix/src/bounce/Makefile.in index 3206537a5..1fd913f5c 100644 --- a/postfix/src/bounce/Makefile.in +++ b/postfix/src/bounce/Makefile.in @@ -298,6 +298,7 @@ bounce_template.o: ../../include/mac_parse.h bounce_template.o: ../../include/mail_conf.h bounce_template.o: ../../include/mail_params.h bounce_template.o: ../../include/mail_proto.h +bounce_template.o: ../../include/midna.h bounce_template.o: ../../include/msg.h bounce_template.o: ../../include/mymalloc.h bounce_template.o: ../../include/split_at.h diff --git a/postfix/src/bounce/bounce_notify_util.c b/postfix/src/bounce/bounce_notify_util.c index e1c27a122..d48b77948 100644 --- a/postfix/src/bounce/bounce_notify_util.c +++ b/postfix/src/bounce/bounce_notify_util.c @@ -227,18 +227,19 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service, /* * Bundle up a bunch of parameters and initialize information that will * be discovered on the fly. + * + * XXX Instead of overriding the returned-message MIME encoding, separate + * the returned-message MIME encoding from the (boiler plate, delivery + * status) MIME encoding. */ bounce_info = (BOUNCE_INFO *) mymalloc(sizeof(*bounce_info)); bounce_info->service = service; bounce_info->queue_name = queue_name; bounce_info->queue_id = queue_id; bounce_info->smtputf8 = smtputf8; - /* Fix 20140708: propagate smtputf8 attribute to bounce message. */ - bounce_info->smtputf8_attr = - vstring_export(vstring_sprintf(vstring_alloc(20), "%s=%d", - MAIL_ATTR_SMTPUTF8, smtputf8)); /* Fix 20140708: override MIME encoding: addresses may be 8bit. */ - if (bounce_info->smtputf8) { + /* Fix 20140718: override MIME encoding: 8bit $myhostname expansion. */ + if (var_smtputf8_enable /* was: bounce_info->smtputf8 */ ) { bounce_info->mime_encoding = "8bit"; } else if (strcmp(encoding, MAIL_ATTR_ENC_8BIT) == 0) { bounce_info->mime_encoding = "8bit"; @@ -442,7 +443,6 @@ void bounce_mail_free(BOUNCE_INFO *bounce_info) bounce_info->queue_id); vstring_free(bounce_info->buf); vstring_free(bounce_info->sender); - myfree(bounce_info->smtputf8_attr); myfree(bounce_info->mail_name); myfree((char *) bounce_info->mime_boundary); myfree((char *) bounce_info); @@ -460,6 +460,7 @@ int bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info, * headers and will make all addresses fully qualified. */ #define STREQ(a, b) (strcasecmp((a), (b)) == 0) +#define STRNE(a, b) (strcasecmp((a), (b)) != 0) /* * Generic headers. @@ -493,15 +494,25 @@ int bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info, /* * MIME header. */ +#define NOT_US_ASCII(tp) \ + STRNE(bounce_template_charset(template), "us-ascii") + +#define NOT_7BIT_MIME(bp) \ + (bp->mime_encoding && STRNE(bp->mime_encoding, MAIL_ATTR_ENC_7BIT)) + post_mail_fputs(bounce, ""); post_mail_fprintf(bounce, "--%s", bounce_info->mime_boundary); post_mail_fprintf(bounce, "Content-Description: %s", "Notification"); + /* Fix 20140718: UTF-8 address or $myhostname expansion. */ post_mail_fprintf(bounce, "Content-Type: %s; charset=%s", - "text/plain", bounce_template_charset(template)); + "text/plain", NOT_US_ASCII(template) ? + bounce_template_charset(template) : + NOT_7BIT_MIME(bounce_info) ? + "utf-8" : "us-ascii"); /* Fix 20140709: addresses may be 8bit. */ - if (bounce_info->smtputf8) + if (NOT_7BIT_MIME(bounce_info)) post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", - bounce_info->mime_encoding); + bounce_info->mime_encoding); post_mail_fputs(bounce, ""); return (vstream_ferror(bounce)); @@ -626,7 +637,7 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) (bounce_info->smtputf8 & SMTPUTF8_FLAG_REQUESTED) ? "global-" : ""); /* Fix 20140709: addresses may be 8bit. */ - if (bounce_info->smtputf8) + if (NOT_7BIT_MIME(bounce_info)) post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", bounce_info->mime_encoding); @@ -647,13 +658,15 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) } post_mail_fprintf(bounce, "X-%s-Queue-ID: %s", bounce_info->mail_name, bounce_info->queue_id); + +#define IS_UTF8_ADDRESS(str, len) \ + ((str)[0] != 0 && !allascii(str) && valid_utf8_string((str), (len))) + /* Fix 20140708: use "utf-8" or "rfc822" as appropriate. */ if (VSTRING_LEN(bounce_info->sender) > 0) post_mail_fprintf(bounce, "X-%s-Sender: %s; %s", bounce_info->mail_name, bounce_info->smtputf8 - && STR(bounce_info->sender)[0] - && !allascii(STR(bounce_info->sender)) - && valid_utf8_string(STR(bounce_info->sender), + && IS_UTF8_ADDRESS(STR(bounce_info->sender), VSTRING_LEN(bounce_info->sender)) ? "utf-8" : "rfc822", STR(bounce_info->sender)); if (bounce_info->arrival_time > 0) @@ -672,10 +685,9 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) post_mail_fputs(bounce, ""); /* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */ post_mail_fprintf(bounce, "Final-Recipient: %s; %s", - bounce_info->smtputf8 && rcpt->address[0] - && !allascii(rcpt->address) - && valid_utf8_string(rcpt->address, - strlen(rcpt->address)) ? + bounce_info->smtputf8 + && IS_UTF8_ADDRESS(rcpt->address, + strlen(rcpt->address)) ? "utf-8" : "rfc822", rcpt->address); /* @@ -702,10 +714,9 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) } else if (NON_NULL_EMPTY(rcpt->orig_addr)) { /* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */ post_mail_fprintf(bounce, "Original-Recipient: %s; %s", - bounce_info->smtputf8 && rcpt->orig_addr[0] - && !allascii(rcpt->orig_addr) - && valid_utf8_string(rcpt->orig_addr, - strlen(rcpt->orig_addr)) ? + bounce_info->smtputf8 + && IS_UTF8_ADDRESS(rcpt->orig_addr, + strlen(rcpt->orig_addr)) ? "utf-8" : "rfc822", rcpt->orig_addr); } post_mail_fprintf(bounce, "Action: %s", @@ -807,7 +818,7 @@ int bounce_original(VSTREAM *bounce, BOUNCE_INFO *bounce_info, post_mail_fprintf(bounce, "Content-Type: %s", headers_only == DSN_RET_HDRS ? "text/rfc822-headers" : "message/rfc822"); - if (bounce_info->mime_encoding) + if (NOT_7BIT_MIME(bounce_info)) post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", bounce_info->mime_encoding); post_mail_fputs(bounce, ""); diff --git a/postfix/src/bounce/bounce_service.h b/postfix/src/bounce/bounce_service.h index 9ba5ca503..f8cc4d6dc 100644 --- a/postfix/src/bounce/bounce_service.h +++ b/postfix/src/bounce/bounce_service.h @@ -85,7 +85,6 @@ typedef struct { BOUNCE_LOG *log_handle; /* open logfile */ char *mail_name; /* $mail_name, cooked */ int smtputf8; /* SMTPUTF8 requested */ - char *smtputf8_attr; /* pre-formatted record value */ } BOUNCE_INFO; /* */ diff --git a/postfix/src/bounce/bounce_template.c b/postfix/src/bounce/bounce_template.c index 7888a1867..f5b7e19a1 100644 --- a/postfix/src/bounce/bounce_template.c +++ b/postfix/src/bounce/bounce_template.c @@ -117,6 +117,9 @@ #include #include #include +#ifndef NO_EAI +#include +#endif /* Global library. */ @@ -198,6 +201,21 @@ static const BOUNCE_TIME_PARAMETER time_parameter[] = { 0, 0, }; + /* + * Parameters whose value may have to be converted to UTF-8 for presentation + * purposes. + */ +typedef struct { + const char *param_name; /* parameter name */ + char **value; /* parameter value */ +} BOUNCE_STR_PARAMETER; + +static const BOUNCE_STR_PARAMETER str_parameter[] = { + VAR_MYHOSTNAME, &var_myhostname, + VAR_MYDOMAIN, &var_mydomain, + 0, 0, +}; + /* * SLMs. */ @@ -387,8 +405,11 @@ static const char *bounce_template_lookup(const char *key, int unused_mode, BOUNCE_TEMPLATE *tp = (BOUNCE_TEMPLATE *) context; const BOUNCE_TIME_PARAMETER *bp; const BOUNCE_TIME_DIVISOR *bd; + const BOUNCE_STR_PARAMETER *sp; static VSTRING *buf; int result; + const char *asc_val; + const char *utf8_val; /* * Look for parameter names that can have a time unit suffix, and scale @@ -426,6 +447,33 @@ static const char *bounce_template_lookup(const char *key, int unused_mode, key + bp->param_name_len + 1, key); } } + + /* + * Look for parameter names that may have to be up-converted for + * presentation purposes. + */ +#ifndef NO_EAI + if (var_smtputf8_enable) { + for (sp = str_parameter; sp->param_name; sp++) { + if (strcmp(key, sp->param_name) == 0) { + asc_val = sp->value[0]; + if (!allascii(asc_val)) { + msg_warn("%s: conversion \"%s\" failed: " + "non-ASCII input value: \"%s\"", + tp->origin, key, asc_val); + return (asc_val); + } else if ((utf8_val = midna_ascii_to_utf8(asc_val)) == 0) { + msg_warn("%s: conversion \"%s\" failed: " + "input value: \"%s\"", + tp->origin, key, asc_val); + return (asc_val); + } else { + return (utf8_val); + } + } + } + } +#endif return (mail_conf_lookup_eval(key)); } @@ -453,13 +501,12 @@ void bounce_template_expand(BOUNCE_XP_PUT_FN out_fn, VSTREAM *fp, VSTRING *buf = vstring_alloc(100); const char **cpp; int stat; - const char *filter = "\t !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; if (tp->flags & BOUNCE_TMPL_FLAG_NEW_BUFFER) bounce_template_parse_buffer(tp); for (cpp = tp->message_text; *cpp; cpp++) { - stat = mac_expand(buf, *cpp, MAC_EXP_FLAG_NONE, filter, + stat = mac_expand(buf, *cpp, MAC_EXP_FLAG_PRINTABLE, (char *) 0, bounce_template_lookup, (char *) tp); if (stat & MAC_PARSE_ERROR) msg_fatal("%s: bad $name syntax in %s template: %s", diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index beb6e6c49..e216b07af 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 "20140716" +#define MAIL_RELEASE_DATE "20140720" #define MAIL_VERSION_NUMBER "2.12" #ifdef SNAPSHOT diff --git a/postfix/src/global/uxtext.c b/postfix/src/global/uxtext.c index ccd0d84a8..aade6a8ce 100644 --- a/postfix/src/global/uxtext.c +++ b/postfix/src/global/uxtext.c @@ -146,10 +146,10 @@ VSTRING *uxtext_quote(VSTRING *quoted, const char *unquoted, const char *special VSTRING *uxtext_unquote_append(VSTRING *unquoted, const char *quoted) { - const char *cp; + const unsigned char *cp; int ch; - for (cp = quoted; (ch = *cp) != 0; cp++) { + for (cp = (const unsigned char *) quoted; (ch = *cp) != 0; cp++) { if (ch == '\\' && cp[1] == 'x' && cp[2] == '{') { cp += 2; int unicode = 0; diff --git a/postfix/src/global/xtext.c b/postfix/src/global/xtext.c index 4e7373344..e5605d7be 100644 --- a/postfix/src/global/xtext.c +++ b/postfix/src/global/xtext.c @@ -101,10 +101,10 @@ VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special) VSTRING *xtext_unquote_append(VSTRING *unquoted, const char *quoted) { - const char *cp; + const unsigned char *cp; int ch; - for (cp = quoted; (ch = *cp) != 0; cp++) { + for (cp = (const unsigned char *) quoted; (ch = *cp) != 0; cp++) { if (ch == '+') { if (ISDIGIT(cp[1])) ch = (cp[1] - '0') << 4; diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index b6c7d5795..4dbe47db4 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -1523,8 +1523,6 @@ load_file.o: vbuf.h load_file.o: vstream.h load_file.o: warn_stat.h load_lib.o: load_lib.c -load_lib.o: load_lib.h -load_lib.o: msg.h load_lib.o: sys_defs.h lowercase.o: lowercase.c lowercase.o: stringops.h @@ -1542,6 +1540,7 @@ mac_expand.o: mac_expand.h mac_expand.o: mac_parse.h mac_expand.o: msg.h mac_expand.o: mymalloc.h +mac_expand.o: stringops.h mac_expand.o: sys_defs.h mac_expand.o: vbuf.h mac_expand.o: vstring.h @@ -1599,6 +1598,7 @@ midna.o: msg.h midna.o: mymalloc.h midna.o: stringops.h midna.o: sys_defs.h +midna.o: valid_hostname.h midna.o: vbuf.h midna.o: vstring.h msg.o: msg.c diff --git a/postfix/src/util/mac_expand.c b/postfix/src/util/mac_expand.c index f9fd2e82a..8c6f6bb31 100644 --- a/postfix/src/util/mac_expand.c +++ b/postfix/src/util/mac_expand.c @@ -54,6 +54,8 @@ /* string, including macro names in the values of conditional /* expressions. Do not expand macros, and do not write to the /* result argument. +/* .IP MAC_EXP_FLAG_PRINTABLE +/* Use the printable() function instead of \fIfilter\fR. /* .PP /* The constant MAC_EXP_FLAG_NONE specifies a manifest null value. /* .RE @@ -103,6 +105,7 @@ #include #include #include +#include #include #include @@ -197,7 +200,9 @@ static int mac_expand_callback(int type, VSTRING *buf, char *ptr) } else { len = VSTRING_LEN(mc->result); vstring_strcat(mc->result, text); - if (mc->filter) { + if (mc->flags & MAC_EXP_FLAG_PRINTABLE) { + printable(vstring_str(mc->result) + len, '_'); + } else if (mc->filter) { cp = vstring_str(mc->result) + len; while (*(cp += strspn(cp, mc->filter))) *cp++ = '_'; diff --git a/postfix/src/util/mac_expand.h b/postfix/src/util/mac_expand.h index f08cd9c86..f8fcffebd 100644 --- a/postfix/src/util/mac_expand.h +++ b/postfix/src/util/mac_expand.h @@ -24,6 +24,7 @@ #define MAC_EXP_FLAG_RECURSE (1<<0) #define MAC_EXP_FLAG_APPEND (1<<1) #define MAC_EXP_FLAG_SCAN (1<<2) +#define MAC_EXP_FLAG_PRINTABLE (1<<3) /* * Real lookup or just a test? diff --git a/postfix/src/util/midna.c b/postfix/src/util/midna.c index 87f71e676..446af8991 100644 --- a/postfix/src/util/midna.c +++ b/postfix/src/util/midna.c @@ -10,6 +10,9 @@ /* /* const char *midna_utf8_to_ascii( /* const char *name) +/* +/* const char *midna_ascii_to_utf8( +/* const char *name) /* DESCRIPTION /* The functions in this module transform domain names from /* or to IDNA form. The result is cached to avoid repeated @@ -18,6 +21,9 @@ /* midna_utf8_to_ascii() converts an UTF-8 domain name to /* ASCII. The result is a null pointer in case of error. /* +/* midna_ascii_to_utf8() converts an ASCII domain name to +/* UTF-8. The result is a null pointer in case of error. +/* /* midna_cache_size specifies the size of the conversion result /* cache. This value is used only once, upon the first lookup /* request. @@ -55,6 +61,7 @@ #include #include #include +#include #include /* @@ -99,9 +106,44 @@ static void *midna_utf8_to_ascii_create(const char *name, void *unused_context) } } -/* midna_utf8_to_ascii_free - cache element destructor */ +/* midna_ascii_to_utf8_create - convert ASCII domain to UTF8 */ -static void midna_utf8_to_ascii_free(void *value, void *unused_context) +static void *midna_ascii_to_utf8_create(const char *name, void *unused_context) +{ + const char myname[] = "midna_ascii_to_utf8_create"; + char buf[1024]; /* XXX */ + UErrorCode error = U_ZERO_ERROR; + UIDNAInfo info = UIDNA_INFO_INITIALIZER; + UIDNA *idna; + int anl; + + /* + * Paranoia: do not expose uidna_*() to unfiltered network data. + */ + if (valid_hostname(name, DONT_GRIPE) == 0) { + msg_warn("%s: Problem translating domain \"%s\" to UTF8 form: %s", + myname, name, "malformed ASCII"); + return (0); + } + idna = uidna_openUTS46(UIDNA_DEFAULT, &error); + anl = uidna_nameToUnicodeUTF8(idna, + name, strlen(name), + buf, sizeof(buf), + &info, + &error); + uidna_close(idna); + if (U_SUCCESS(error) && info.errors == 0 && anl > 0) { + return (mystrndup(buf, anl)); + } else { + msg_warn("%s: Problem translating domain \"%s\" to IDNA form: %s", + myname, name, u_errorName(error)); + return (0); + } +} + +/* midna_cache_free - cache element destructor */ + +static void midna_cache_free(void *value, void *unused_context) { if (value) myfree(value); @@ -116,11 +158,25 @@ const char *midna_utf8_to_ascii(const char *name) if (midna_utf8_to_ascii_cache == 0) midna_utf8_to_ascii_cache = ctable_create(midna_cache_size, midna_utf8_to_ascii_create, - midna_utf8_to_ascii_free, + midna_cache_free, (void *) 0); return (ctable_locate(midna_utf8_to_ascii_cache, name)); } +/* midna_ascii_to_utf8 - convert UTF8 hostname to ASCII */ + +const char *midna_ascii_to_utf8(const char *name) +{ + static CTABLE *midna_ascii_to_utf8_cache = 0; + + if (midna_ascii_to_utf8_cache == 0) + midna_ascii_to_utf8_cache = ctable_create(midna_cache_size, + midna_ascii_to_utf8_create, + midna_cache_free, + (void *) 0); + return (ctable_locate(midna_ascii_to_utf8_cache, name)); +} + #ifdef TEST /* @@ -128,6 +184,7 @@ const char *midna_utf8_to_ascii(const char *name) * stderr. */ #include +#include #include /* XXX temp_utf8_kludge */ #include @@ -138,17 +195,44 @@ const char *midna_utf8_to_ascii(const char *name) int main(int argc, char **argv) { VSTRING *buffer = vstring_alloc(1); - const char *res; + const char *bp; + const char *ascii; + const char *utf8; + + if (setlocale(LC_ALL, "C") == 0) + msg_fatal("setlocale(LC_ALL, C) failed: %m"); msg_vstream_init(argv[0], VSTREAM_ERR); msg_verbose = 1; temp_utf8_kludge = 1; while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { - msg_info("testing: \"%s\"", vstring_str(buffer)); - res = midna_utf8_to_ascii(vstring_str(buffer)); - if (res != 0) - msg_info("result: \"%s\"", res); + msg_info("testing: \"%s\"", bp = vstring_str(buffer)); + if (!allascii(bp)) { + ascii = midna_utf8_to_ascii(bp); + if (ascii != 0) { + msg_info("\"%s\" -> \"%s\"", bp, ascii); + utf8 = midna_ascii_to_utf8(ascii); + if (utf8 != 0) { + msg_info("\"%s\" -> \"%s\" -> \"%s\"", + bp, ascii, utf8); + if (strcmp(utf8, bp) != 0) + msg_warn("\"%s\" != \"%s\"", bp, utf8); + } + } + } else { + utf8 = midna_ascii_to_utf8(bp); + if (utf8 != 0) { + msg_info("\"%s\" -> \"%s\"", bp, utf8); + ascii = midna_utf8_to_ascii(utf8); + if (ascii != 0) { + msg_info("\"%s\" -> \"%s\" -> \"%s\"", + bp, utf8, ascii); + if (strcmp(ascii, bp) != 0) + msg_warn("\"%s\" != \"%s\"", bp, ascii); + } + } + } } exit(0); } diff --git a/postfix/src/util/midna.h b/postfix/src/util/midna.h index 5a24a113e..1d2477773 100644 --- a/postfix/src/util/midna.h +++ b/postfix/src/util/midna.h @@ -15,6 +15,7 @@ * External interface. */ extern const char *midna_utf8_to_ascii(const char *); +extern const char *midna_ascii_to_utf8(const char *); /* LICENSE /* .ad