mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 05:38:06 +00:00
postfix-2.12-20141228
This commit is contained in:
parent
e5e46ec03f
commit
19b6598b23
@ -21191,3 +21191,21 @@ Apologies for any names omitted.
|
||||
child process. Background: some shells implement "IFS=foo
|
||||
command" as a permanent IFS change; this was allowed by
|
||||
standards at some point in time. File: postfix-install.
|
||||
|
||||
20141227
|
||||
|
||||
Feature: smtp_address_verify_target (default: rcpt) that
|
||||
determines what protocol stage decides if a recipient is
|
||||
valid. Specify "data" for servers that reject recipients
|
||||
after the DATA command. Files: mantools/postlink,
|
||||
proto/postconf.proto, proto/ADDRESS_VERIFICATION_README.html,
|
||||
global/mail_params.h, smtp/lmtp_params.c, smtp/smtp.c,
|
||||
smtp/smtp.h, smtp/smtp_params.c, smtp/smtp_proto.c.
|
||||
|
||||
20141228
|
||||
|
||||
Cleanup: the IDNA conversion routines now accept both
|
||||
ASCII and UTF8 inputs. The functions als verify that
|
||||
either their result is a valid ASCII domain name or that
|
||||
it converts into a valid ASCII domain name. Files:
|
||||
util/midna.c, util/midna_test.in, util/midna_test.ref.
|
||||
|
@ -81,6 +81,11 @@ postconf(5) for details.
|
||||
|
||||
LLiimmiittaattiioonnss ooff aaddddrreessss vveerriiffiiccaattiioonn
|
||||
|
||||
* Postfix assumes that a remote SMTP server will reject unknown addresses in
|
||||
reply to the RCPT TO command. However, some sites report this in reply to
|
||||
the DATA command. For such sites you may configure a workaround with the
|
||||
smtp_address_verify_target parameter (Postfix 2.12 and later).
|
||||
|
||||
* When verifying a remote address, Postfix probes the preferred MTAs for that
|
||||
address, without actually delivering mail. If a preferred MTA accepts the
|
||||
address, then Postfix assumes that the address is deliverable. In reality,
|
||||
@ -108,9 +113,9 @@ LLiimmiittaattiioonnss ooff aaddddrreessss vveerriiffi
|
||||
here just in case people believe that it is a limitation.
|
||||
|
||||
* Unfortunately, some sites do not reject unknown addresses in reply to the
|
||||
RCPT TO command, but report a delivery failure in response to end of DATA
|
||||
after a message is transferred. Postfix address verification does not work
|
||||
with such sites.
|
||||
RCPT TO or DATA command, but instead report a delivery failure in response
|
||||
to end of DATA after a message is transferred. Postfix address verification
|
||||
does not work with such sites.
|
||||
|
||||
* By default, Postfix probe messages have a sender address "double-
|
||||
bounce@$myorigin" (with Postfix versions before 2.5, the default is
|
||||
|
@ -198,6 +198,12 @@ details. </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> Postfix assumes that a remote SMTP server will reject
|
||||
unknown addresses in reply to the RCPT TO command. However, some
|
||||
sites report this in reply to the DATA command. For such sites
|
||||
you may configure a workaround with the <a href="postconf.5.html#smtp_address_verify_target">smtp_address_verify_target</a>
|
||||
parameter (Postfix 2.12 and later). </p>
|
||||
|
||||
<li> <p> When verifying a remote address, Postfix probes the preferred
|
||||
MTAs for that address, without actually delivering mail. If
|
||||
a preferred MTA accepts the address, then Postfix assumes that the
|
||||
@ -227,8 +233,8 @@ MTA for that address rejects mail from your machine for any reason.
|
||||
This is not a limitation, but it is mentioned here just in case
|
||||
people believe that it is a limitation. </p>
|
||||
|
||||
<li> <p> Unfortunately, some sites do not reject
|
||||
unknown addresses in reply to the RCPT TO command, but report a
|
||||
<li> <p> Unfortunately, some sites do not reject unknown addresses
|
||||
in reply to the RCPT TO or DATA command, but instead report a
|
||||
delivery failure in response to end of DATA after a message is
|
||||
transferred. Postfix address verification does not work with such
|
||||
sites. </p>
|
||||
|
@ -833,6 +833,12 @@ SMTP(8) SMTP(8)
|
||||
Optional list of relay hosts for SMTP destinations that can't be
|
||||
found or that are unreachable.
|
||||
|
||||
Available with Postfix 2.12 and later:
|
||||
|
||||
<b><a href="postconf.5.html#smtp_address_verify_target">smtp_address_verify_target</a> (rcpt)</b>
|
||||
In the context of email address verification, the SMTP protocol
|
||||
stage that determines whether an email address is deliverable.
|
||||
|
||||
<b>SEE ALSO</b>
|
||||
<a href="generic.5.html">generic(5)</a>, output address rewriting
|
||||
<a href="header_checks.5.html">header_checks(5)</a>, message header content inspection
|
||||
|
@ -4021,6 +4021,17 @@ configuration parameter. See there for details. </p>
|
||||
<p> This feature is available in Postfix 2.8 and later. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="lmtp_address_verify_target">lmtp_address_verify_target</a>
|
||||
(default: rcpt)</b></DT><DD>
|
||||
|
||||
<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_dns_support_level">smtp_dns_support_level</a>
|
||||
configuration parameter. See there for details. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.12 and later. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="lmtp_assume_final">lmtp_assume_final</a>
|
||||
@ -9859,6 +9870,49 @@ that affects IPv6 or IPv4, as long as it does not affect both. </p>
|
||||
<p> This feature is available in Postfix 2.8 and later. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="smtp_address_verify_target">smtp_address_verify_target</a>
|
||||
(default: rcpt)</b></DT><DD>
|
||||
|
||||
<p> In the context of email address verification, the SMTP protocol
|
||||
stage that determines whether an email address is deliverable.
|
||||
Specify one of "rcpt" or "data". The latter is needed with remote
|
||||
SMTP servers that reject recipients after the DATA command. Use
|
||||
<a href="postconf.5.html#transport_maps">transport_maps</a> to apply this feature selectively: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/transport
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/transport:
|
||||
smtp-domain_that_verifies_after_data smtp-data-target:
|
||||
lmtp-domain_that_verifies_after_data lmtp-data-target:
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/<a href="master.5.html">master.cf</a>:
|
||||
smtp-data-target unix - - n - - smtp
|
||||
-o <a href="postconf.5.html#smtp_address_verify_target">smtp_address_verify_target</a>=data
|
||||
lmtp-data-target unix - - n - - lmtp
|
||||
-o <a href="postconf.5.html#lmtp_address_verify_target">lmtp_address_verify_target</a>=data
|
||||
<blockquote>
|
||||
<pre>
|
||||
|
||||
<p> Unselective use of the "data" target does no harm, but will
|
||||
result in unnecessary "lost connection after DATA" events at remote
|
||||
SMTP/LMTP servers. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.12 and later. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="smtp_always_send_ehlo">smtp_always_send_ehlo</a>
|
||||
|
@ -833,6 +833,12 @@ SMTP(8) SMTP(8)
|
||||
Optional list of relay hosts for SMTP destinations that can't be
|
||||
found or that are unreachable.
|
||||
|
||||
Available with Postfix 2.12 and later:
|
||||
|
||||
<b><a href="postconf.5.html#smtp_address_verify_target">smtp_address_verify_target</a> (rcpt)</b>
|
||||
In the context of email address verification, the SMTP protocol
|
||||
stage that determines whether an email address is deliverable.
|
||||
|
||||
<b>SEE ALSO</b>
|
||||
<a href="generic.5.html">generic(5)</a>, output address rewriting
|
||||
<a href="header_checks.5.html">header_checks(5)</a>, message header content inspection
|
||||
|
@ -2472,6 +2472,11 @@ The LMTP-specific version of the smtp_address_preference
|
||||
configuration parameter. See there for details.
|
||||
.PP
|
||||
This feature is available in Postfix 2.8 and later.
|
||||
.SH lmtp_address_verify_target (default: rcpt)
|
||||
The LMTP-specific version of the smtp_dns_support_level
|
||||
configuration parameter. See there for details.
|
||||
.PP
|
||||
This feature is available in Postfix 2.12 and later.
|
||||
.SH lmtp_assume_final (default: no)
|
||||
When a remote LMTP server announces no DSN support, assume that
|
||||
the
|
||||
@ -6085,6 +6090,56 @@ that affects IPv6 or IPv4, as long as it does not affect both.
|
||||
.br
|
||||
.PP
|
||||
This feature is available in Postfix 2.8 and later.
|
||||
.SH smtp_address_verify_target (default: rcpt)
|
||||
In the context of email address verification, the SMTP protocol
|
||||
stage that determines whether an email address is deliverable.
|
||||
Specify one of "rcpt" or "data". The latter is needed with remote
|
||||
SMTP servers that reject recipients after the DATA command. Use
|
||||
transport_maps to apply this feature selectively:
|
||||
.sp
|
||||
.in +4
|
||||
.nf
|
||||
.na
|
||||
.ft C
|
||||
/etc/postfix/main.cf:
|
||||
transport_maps = hash:/etc/postfix/transport
|
||||
.fi
|
||||
.ad
|
||||
.ft R
|
||||
.in -4
|
||||
.sp
|
||||
.in +4
|
||||
.nf
|
||||
.na
|
||||
.ft C
|
||||
/etc/postfix/transport:
|
||||
smtp-domain_that_verifies_after_data smtp-data-target:
|
||||
lmtp-domain_that_verifies_after_data lmtp-data-target:
|
||||
.fi
|
||||
.ad
|
||||
.ft R
|
||||
.in -4
|
||||
.sp
|
||||
.in +4
|
||||
.nf
|
||||
.na
|
||||
.ft C
|
||||
/etc/postfix/master.cf:
|
||||
smtp-data-target unix - - n - - smtp
|
||||
-o smtp_address_verify_target=data
|
||||
lmtp-data-target unix - - n - - lmtp
|
||||
-o lmtp_address_verify_target=data
|
||||
.sp
|
||||
.in +4
|
||||
.nf
|
||||
.na
|
||||
.ft C
|
||||
.PP
|
||||
Unselective use of the "data" target does no harm, but will
|
||||
result in unnecessary "lost connection after DATA" events at remote
|
||||
SMTP/LMTP servers.
|
||||
.PP
|
||||
This feature is available in Postfix 2.12 and later.
|
||||
.SH smtp_always_send_ehlo (default: yes)
|
||||
Always send EHLO at the start of an SMTP session.
|
||||
.PP
|
||||
|
@ -725,6 +725,11 @@ Available with Postfix 2.3 and later:
|
||||
.IP "\fBsmtp_fallback_relay ($fallback_relay)\fR"
|
||||
Optional list of relay hosts for SMTP destinations that can't be
|
||||
found or that are unreachable.
|
||||
.PP
|
||||
Available with Postfix 2.12 and later:
|
||||
.IP "\fBsmtp_address_verify_target (rcpt)\fR"
|
||||
In the context of email address verification, the SMTP protocol
|
||||
stage that determines whether an email address is deliverable.
|
||||
.SH "SEE ALSO"
|
||||
.na
|
||||
.nf
|
||||
|
@ -89,6 +89,8 @@ while (<>) {
|
||||
s;\baddress_verify_service_name\b;<a href="postconf.5.html#address_verify_service_name">$&</a>;g;
|
||||
s;\baddress_verify_transport_maps\b;<a href="postconf.5.html#address_verify_transport_maps">$&</a>;g;
|
||||
s;\baddress_verify_virtual_transport\b;<a href="postconf.5.html#address_verify_virtual_transport">$&</a>;g;
|
||||
s;\bsmtp_address_verify_target\b;<a href="postconf.5.html#smtp_address_verify_target">$&</a>;g;
|
||||
s;\blmtp_address_verify_target\b;<a href="postconf.5.html#lmtp_address_verify_target">$&</a>;g;
|
||||
s;\balias_database\b;<a href="postconf.5.html#alias_database">$&</a>;g;
|
||||
s;\balias_maps\b;<a href="postconf.5.html#alias_maps">$&</a>;g;
|
||||
s;\ballow_mail_to_com[-</bB>]*\n*[ <bB>]*mands\b;<a href="postconf.5.html#allow_mail_to_commands">$&</a>;g;
|
||||
|
@ -198,6 +198,12 @@ details. </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> Postfix assumes that a remote SMTP server will reject
|
||||
unknown addresses in reply to the RCPT TO command. However, some
|
||||
sites report this in reply to the DATA command. For such sites
|
||||
you may configure a workaround with the smtp_address_verify_target
|
||||
parameter (Postfix 2.12 and later). </p>
|
||||
|
||||
<li> <p> When verifying a remote address, Postfix probes the preferred
|
||||
MTAs for that address, without actually delivering mail. If
|
||||
a preferred MTA accepts the address, then Postfix assumes that the
|
||||
@ -227,8 +233,8 @@ MTA for that address rejects mail from your machine for any reason.
|
||||
This is not a limitation, but it is mentioned here just in case
|
||||
people believe that it is a limitation. </p>
|
||||
|
||||
<li> <p> Unfortunately, some sites do not reject
|
||||
unknown addresses in reply to the RCPT TO command, but report a
|
||||
<li> <p> Unfortunately, some sites do not reject unknown addresses
|
||||
in reply to the RCPT TO or DATA command, but instead report a
|
||||
delivery failure in response to end of DATA after a message is
|
||||
transferred. Postfix address verification does not work with such
|
||||
sites. </p>
|
||||
|
@ -15419,6 +15419,52 @@ units are: s (seconds), m (minutes), h (hours), d (days), w (weeks).
|
||||
|
||||
<p> This feature is available in Postfix 2.9 and later. </p>
|
||||
|
||||
%PARAM smtp_address_verify_target rcpt
|
||||
|
||||
<p> In the context of email address verification, the SMTP protocol
|
||||
stage that determines whether an email address is deliverable.
|
||||
Specify one of "rcpt" or "data". The latter is needed with remote
|
||||
SMTP servers that reject recipients after the DATA command. Use
|
||||
transport_maps to apply this feature selectively: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
transport_maps = hash:/etc/postfix/transport
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/transport:
|
||||
smtp-domain_that_verifies_after_data smtp-data-target:
|
||||
lmtp-domain_that_verifies_after_data lmtp-data-target:
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/master.cf:
|
||||
smtp-data-target unix - - n - - smtp
|
||||
-o smtp_address_verify_target=data
|
||||
lmtp-data-target unix - - n - - lmtp
|
||||
-o lmtp_address_verify_target=data
|
||||
<blockquote>
|
||||
<pre>
|
||||
|
||||
<p> Unselective use of the "data" target does no harm, but will
|
||||
result in unnecessary "lost connection after DATA" events at remote
|
||||
SMTP/LMTP servers. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.12 and later. </p>
|
||||
|
||||
%PARAM lmtp_address_verify_target rcpt
|
||||
|
||||
<p> The LMTP-specific version of the smtp_dns_support_level
|
||||
configuration parameter. See there for details. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.12 and later. </p>
|
||||
|
||||
%PARAM daemon_table_open_error_is_fatal no
|
||||
|
||||
<p> How a Postfix daemon process handles errors while opening lookup
|
||||
|
@ -462,7 +462,7 @@ static const char *bounce_template_lookup(const char *key, int unused_mode,
|
||||
"non-ASCII input value: \"%s\"",
|
||||
tp->origin, key, asc_val);
|
||||
return (asc_val);
|
||||
} else if ((utf8_val = midna_ascii_to_utf8(asc_val)) == 0) {
|
||||
} else if ((utf8_val = midna_to_utf8(asc_val)) == 0) {
|
||||
msg_warn("%s: conversion \"%s\" failed: "
|
||||
"input value: \"%s\"",
|
||||
tp->origin, key, asc_val);
|
||||
|
@ -2778,6 +2778,14 @@ extern char *var_vrfy_relay_maps;
|
||||
#define DEF_VRFY_XPORT_MAPS "$" VAR_TRANSPORT_MAPS
|
||||
extern char *var_vrfy_xport_maps;
|
||||
|
||||
#define SMTP_VRFY_TGT_RCPT "rcpt"
|
||||
#define SMTP_VRFY_TGT_DATA "data"
|
||||
#define VAR_LMTP_VRFY_TGT "lmtp_address_verify_target"
|
||||
#define DEF_LMTP_VRFY_TGT SMTP_VRFY_TGT_RCPT
|
||||
#define VAR_SMTP_VRFY_TGT "smtp_address_verify_target"
|
||||
#define DEF_SMTP_VRFY_TGT SMTP_VRFY_TGT_RCPT
|
||||
extern char *var_smtp_vrfy_tgt;
|
||||
|
||||
/*
|
||||
* Message delivery trace service.
|
||||
*/
|
||||
|
@ -17,7 +17,7 @@
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP name
|
||||
/* Parameter name. This is used to privode context for
|
||||
/* Parameter name. This is used to provide context for
|
||||
/* error messages.
|
||||
/* .IP value
|
||||
/* Parameter value.
|
||||
|
@ -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 "20141226"
|
||||
#define MAIL_RELEASE_DATE "20141228"
|
||||
#define MAIL_VERSION_NUMBER "2.12"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@ -1103,7 +1103,7 @@ static DNS_RR *domain_addr(STATE *state, char *domain)
|
||||
* IDNA support.
|
||||
*/
|
||||
#ifndef NO_EAI
|
||||
if (!allascii(domain) && (aname = midna_utf8_to_ascii(domain)) != 0) {
|
||||
if (!allascii(domain) && (aname = midna_to_ascii(domain)) != 0) {
|
||||
msg_info("%s asciified to %s", domain, aname);
|
||||
} else
|
||||
#endif
|
||||
@ -1168,7 +1168,7 @@ static DNS_RR *host_addr(STATE *state, const char *host)
|
||||
* IDNA support.
|
||||
*/
|
||||
#ifndef NO_EAI
|
||||
if (!allascii(host) && (ahost = midna_utf8_to_ascii(host)) != 0) {
|
||||
if (!allascii(host) && (ahost = midna_to_ascii(host)) != 0) {
|
||||
msg_info("%s asciified to %s", host, ahost);
|
||||
} else
|
||||
#endif
|
||||
|
@ -33,6 +33,7 @@
|
||||
VAR_LMTP_SASL_TYPE, DEF_LMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0,
|
||||
VAR_LMTP_BIND_ADDR, DEF_LMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0,
|
||||
VAR_LMTP_BIND_ADDR6, DEF_LMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0,
|
||||
VAR_LMTP_VRFY_TGT, DEF_LMTP_VRFY_TGT, &var_smtp_vrfy_tgt, 1, 0,
|
||||
VAR_LMTP_HELO_NAME, DEF_LMTP_HELO_NAME, &var_smtp_helo_name, 1, 0,
|
||||
VAR_LMTP_HOST_LOOKUP, DEF_LMTP_HOST_LOOKUP, &var_smtp_host_lookup, 1, 0,
|
||||
VAR_LMTP_DNS_SUPPORT, DEF_LMTP_DNS_SUPPORT, &var_smtp_dns_support, 0, 0,
|
||||
|
@ -685,6 +685,11 @@
|
||||
/* .IP "\fBsmtp_fallback_relay ($fallback_relay)\fR"
|
||||
/* Optional list of relay hosts for SMTP destinations that can't be
|
||||
/* found or that are unreachable.
|
||||
/* .PP
|
||||
/* Available with Postfix 2.12 and later:
|
||||
/* .IP "\fBsmtp_address_verify_target (rcpt)\fR"
|
||||
/* In the context of email address verification, the SMTP protocol
|
||||
/* stage that determines whether an email address is deliverable.
|
||||
/* SEE ALSO
|
||||
/* generic(5), output address rewriting
|
||||
/* header_checks(5), message header content inspection
|
||||
@ -816,6 +821,7 @@ char *var_smtp_sasl_mechs;
|
||||
char *var_smtp_sasl_type;
|
||||
char *var_smtp_bind_addr;
|
||||
char *var_smtp_bind_addr6;
|
||||
char *var_smtp_vrfy_tgt;
|
||||
bool var_smtp_rand_addr;
|
||||
int var_smtp_pix_thresh;
|
||||
int var_queue_run_delay;
|
||||
@ -1077,6 +1083,11 @@ static void post_init(char *unused_name, char **unused_argv)
|
||||
*/
|
||||
smtp_dns_res_opt = name_mask(VAR_LMTP_SMTP(DNS_RES_OPT), dns_res_opt_masks,
|
||||
var_smtp_dns_res_opt);
|
||||
|
||||
/*
|
||||
* Address verification.
|
||||
*/
|
||||
smtp_vrfy_init();
|
||||
}
|
||||
|
||||
/* pre_init - pre-jail initialization */
|
||||
|
@ -365,6 +365,7 @@ extern int smtp_connect(SMTP_STATE *);
|
||||
/*
|
||||
* smtp_proto.c
|
||||
*/
|
||||
extern void smtp_vrfy_init(void);
|
||||
extern int smtp_helo(SMTP_STATE *);
|
||||
extern int smtp_xfer(SMTP_STATE *);
|
||||
extern int smtp_rset(SMTP_STATE *);
|
||||
@ -515,6 +516,11 @@ extern void smtp_chat_notify(SMTP_SESSION *);
|
||||
|
||||
#define DSN_BY_LOCAL_MTA ((char *) 0) /* DSN issued by local MTA */
|
||||
|
||||
#define SMTP_RESP_SET_DSN(resp, _dsn) do { \
|
||||
vstring_strcpy((resp)->dsn_buf, (_dsn)); \
|
||||
(resp)->dsn = STR((resp)->dsn_buf); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* These operations implement a redundant mark-and-sweep algorithm that
|
||||
* explicitly accounts for the fate of every recipient. The interface is
|
||||
|
@ -378,7 +378,7 @@ DNS_RR *smtp_domain_addr(const char *name, DNS_RR **mxrr, int misc_flags,
|
||||
* IDNA support.
|
||||
*/
|
||||
#ifndef NO_EAI
|
||||
if (!allascii(name) && (aname = midna_utf8_to_ascii(name)) != 0) {
|
||||
if (!allascii(name) && (aname = midna_to_ascii(name)) != 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s asciified to %s", name, aname);
|
||||
} else
|
||||
@ -524,7 +524,7 @@ DNS_RR *smtp_host_addr(const char *host, int misc_flags, DSN_BUF *why)
|
||||
* IDNA support.
|
||||
*/
|
||||
#ifndef NO_EAI
|
||||
if (!allascii(host) && (ahost = midna_utf8_to_ascii(host)) != 0) {
|
||||
if (!allascii(host) && (ahost = midna_to_ascii(host)) != 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s asciified to %s", host, ahost);
|
||||
} else
|
||||
|
@ -34,6 +34,7 @@
|
||||
VAR_SMTP_SASL_TYPE, DEF_SMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0,
|
||||
VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0,
|
||||
VAR_SMTP_BIND_ADDR6, DEF_SMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0,
|
||||
VAR_SMTP_VRFY_TGT, DEF_SMTP_VRFY_TGT, &var_smtp_vrfy_tgt, 1, 0,
|
||||
VAR_SMTP_HELO_NAME, DEF_SMTP_HELO_NAME, &var_smtp_helo_name, 1, 0,
|
||||
VAR_SMTP_HOST_LOOKUP, DEF_SMTP_HOST_LOOKUP, &var_smtp_host_lookup, 1, 0,
|
||||
VAR_SMTP_DNS_SUPPORT, DEF_SMTP_DNS_SUPPORT, &var_smtp_dns_support, 0, 0,
|
||||
|
@ -144,6 +144,8 @@
|
||||
#include <tok822.h>
|
||||
#include <mail_addr_map.h>
|
||||
#include <ext_prop.h>
|
||||
#include <namadr_list.h>
|
||||
#include <match_parent_style.h>
|
||||
#include <lex_822.h>
|
||||
#include <dsn_mask.h>
|
||||
#include <xtext.h>
|
||||
@ -261,6 +263,24 @@ HBC_CALL_BACKS smtp_hbc_callbacks[1] = {
|
||||
smtp_text_out,
|
||||
};
|
||||
|
||||
static int smtp_vrfy_tgt;
|
||||
|
||||
/* smtp_vrfy_init - initialize */
|
||||
|
||||
void smtp_vrfy_init(void)
|
||||
{
|
||||
static const NAME_CODE vrfy_init_table[] = {
|
||||
SMTP_VRFY_TGT_RCPT, SMTP_STATE_RCPT,
|
||||
SMTP_VRFY_TGT_DATA, SMTP_STATE_DATA,
|
||||
0,
|
||||
};
|
||||
|
||||
if ((smtp_vrfy_tgt = name_code(vrfy_init_table, NAME_CODE_FLAG_NONE,
|
||||
var_smtp_vrfy_tgt)) == 0)
|
||||
msg_fatal("bad protocol stage: \"%s = %s\"",
|
||||
VAR_SMTP_VRFY_TGT, var_smtp_vrfy_tgt);
|
||||
}
|
||||
|
||||
/* smtp_helo - perform initial handshake with SMTP server */
|
||||
|
||||
int smtp_helo(SMTP_STATE *state)
|
||||
@ -1541,7 +1561,8 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
|
||||
dsn_notify_str(rcpt->dsn_notify));
|
||||
}
|
||||
if ((next_rcpt = send_rcpt + 1) == SMTP_RCPT_LEFT(state))
|
||||
next_state = DEL_REQ_TRACE_ONLY(request->flags) ?
|
||||
next_state = (DEL_REQ_TRACE_ONLY(request->flags)
|
||||
&& smtp_vrfy_tgt == SMTP_STATE_RCPT) ?
|
||||
SMTP_STATE_ABORT : SMTP_STATE_DATA;
|
||||
break;
|
||||
|
||||
@ -1808,7 +1829,8 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
|
||||
}
|
||||
++nrcpt;
|
||||
/* If trace-only, mark the recipient done. */
|
||||
if (DEL_REQ_TRACE_ONLY(request->flags)) {
|
||||
if (DEL_REQ_TRACE_ONLY(request->flags)
|
||||
&& smtp_vrfy_tgt == SMTP_STATE_RCPT) {
|
||||
translit(resp->str, "\n", " ");
|
||||
smtp_rcpt_done(state, resp, rcpt);
|
||||
}
|
||||
@ -1822,7 +1844,8 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
|
||||
}
|
||||
/* If trace-only, send RSET instead of DATA. */
|
||||
if (++recv_rcpt == SMTP_RCPT_LEFT(state))
|
||||
recv_state = DEL_REQ_TRACE_ONLY(request->flags) ?
|
||||
recv_state = (DEL_REQ_TRACE_ONLY(request->flags)
|
||||
&& smtp_vrfy_tgt == SMTP_STATE_RCPT) ?
|
||||
SMTP_STATE_ABORT : SMTP_STATE_DATA;
|
||||
/* XXX Also: record if non-delivering session. */
|
||||
break;
|
||||
@ -1833,6 +1856,7 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
|
||||
* receiver can apply a course correction.
|
||||
*/
|
||||
case SMTP_STATE_DATA:
|
||||
recv_state = SMTP_STATE_DOT;
|
||||
if (resp->code / 100 != 3) {
|
||||
if (nrcpt > 0)
|
||||
smtp_mesg_fail(state, STR(iter->host), resp,
|
||||
@ -1842,7 +1866,30 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
|
||||
xfer_request[SMTP_STATE_DATA]);
|
||||
nrcpt = -1;
|
||||
}
|
||||
recv_state = SMTP_STATE_DOT;
|
||||
|
||||
/*
|
||||
* In the case of a successful address probe with target
|
||||
* equal to DATA, the remote server is now in the DATA
|
||||
* state, and therefore we must not make any further
|
||||
* attempt to send or receive on this connection. This
|
||||
* means that we cannot not reuse the general-purpose
|
||||
* course-correction logic below which sends RSET (and
|
||||
* perhaps QUIT). Instead we "jump" straight to the exit
|
||||
* and force an unceremonious disconnect.
|
||||
*/
|
||||
else if (DEL_REQ_TRACE_ONLY(request->flags)
|
||||
&& smtp_vrfy_tgt == SMTP_STATE_DATA) {
|
||||
for (nrcpt = 0; nrcpt < recv_rcpt; nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (!SMTP_RCPT_ISMARKED(rcpt)) {
|
||||
translit(resp->str, "\n", " ");
|
||||
SMTP_RESP_SET_DSN(resp, "2.0.0");
|
||||
smtp_rcpt_done(state, resp, rcpt);
|
||||
}
|
||||
}
|
||||
DONT_CACHE_THIS_SESSION;
|
||||
send_state = recv_state = SMTP_STATE_LAST;
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
|
@ -1417,7 +1417,7 @@ static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name,
|
||||
* Fix 20140924: convert domain to ASCII.
|
||||
*/
|
||||
#ifndef NO_EAI
|
||||
if (!allascii(name) && (aname = midna_utf8_to_ascii(name)) != 0) {
|
||||
if (!allascii(name) && (aname = midna_to_ascii(name)) != 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s asciified to %s", name, aname);
|
||||
name = aname;
|
||||
@ -1916,7 +1916,7 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient,
|
||||
* Fix 20140924: convert domain to ASCII.
|
||||
*/
|
||||
#ifndef NO_EAI
|
||||
if (!allascii(domain) && (adomain = midna_utf8_to_ascii(domain)) != 0) {
|
||||
if (!allascii(domain) && (adomain = midna_to_ascii(domain)) != 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s asciified to %s", domain, adomain);
|
||||
domain = adomain;
|
||||
@ -2914,7 +2914,7 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
||||
* Fix 20140924: convert domain to ASCII.
|
||||
*/
|
||||
#ifndef NO_EAI
|
||||
if (!allascii(domain) && (adomain = midna_utf8_to_ascii(domain)) != 0) {
|
||||
if (!allascii(domain) && (adomain = midna_to_ascii(domain)) != 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s asciified to %s", domain, adomain);
|
||||
domain = adomain;
|
||||
@ -3634,7 +3634,7 @@ static const SMTPD_RBL_STATE *find_dnsxl_domain(SMTPD_STATE *state,
|
||||
* Fix 20140706: convert domain to ASCII.
|
||||
*/
|
||||
#ifndef NO_EAI
|
||||
if (!allascii(domain) && (adomain = midna_utf8_to_ascii(domain)) != 0) {
|
||||
if (!allascii(domain) && (adomain = midna_to_ascii(domain)) != 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s asciified to %s", domain, adomain);
|
||||
domain = adomain;
|
||||
|
@ -535,7 +535,7 @@ static int match_servername(const char *certid,
|
||||
*/
|
||||
if (!allascii(certid))
|
||||
return (0);
|
||||
if (!allascii(nexthop) && (aname = midna_utf8_to_ascii(nexthop)) != 0) {
|
||||
if (!allascii(nexthop) && (aname = midna_to_ascii(nexthop)) != 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s asciified to %s", nexthop, aname);
|
||||
nexthop = aname;
|
||||
@ -586,7 +586,7 @@ static int match_servername(const char *certid,
|
||||
}
|
||||
}
|
||||
if (!allascii(domain)
|
||||
&& (aname = midna_utf8_to_ascii(domain)) != 0) {
|
||||
&& (aname = midna_to_ascii(domain)) != 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s asciified to %s", domain, aname);
|
||||
domain = aname;
|
||||
|
@ -515,7 +515,7 @@ tests: all valid_hostname_test mac_expand_test dict_test unescape_test \
|
||||
dict_cidr_test attr_scan_plain_test htable_test hex_code_test \
|
||||
myaddrinfo_test format_tv_test ip_match_test name_mask_tests \
|
||||
base32_code_test dict_thash_test surrogate_test timecmp_test \
|
||||
dict_static_test dict_inline_test
|
||||
dict_static_test dict_inline_test midna_test
|
||||
|
||||
root_tests:
|
||||
|
||||
@ -750,6 +750,11 @@ dict_inline_test: dict_open dict_inline.ref
|
||||
diff dict_inline.ref dict_inline.tmp
|
||||
rm -f dict_inline.tmp
|
||||
|
||||
midna_test: midna midna_test.in midna_test.ref
|
||||
$(SHLIB_ENV) ./midna <midna_test.in >midna_test.tmp 2>&1
|
||||
diff midna_test.ref midna_test.tmp
|
||||
rm -f midna_test.tmp
|
||||
|
||||
depend: $(MAKES)
|
||||
(sed '1,/^# do not edit/!d' Makefile.in; \
|
||||
set -e; for i in [a-z][a-z0-9]*.c; do \
|
||||
|
@ -8,21 +8,34 @@
|
||||
/*
|
||||
/* int midna_cache_size;
|
||||
/*
|
||||
/* const char *midna_utf8_to_ascii(
|
||||
/* const char *midna_to_ascii(
|
||||
/* const char *name)
|
||||
/*
|
||||
/* const char *midna_ascii_to_utf8(
|
||||
/* const char *midna_to_utf8(
|
||||
/* const char *name)
|
||||
/*
|
||||
/* const char *midna_suffix_to_ascii(
|
||||
/* const char *name)
|
||||
/*
|
||||
/* const char *midna_suffix_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
|
||||
/* conversion of the same name.
|
||||
/*
|
||||
/* midna_utf8_to_ascii() converts an UTF-8 domain name to
|
||||
/* ASCII. The result is a null pointer in case of error.
|
||||
/* midna_to_ascii() converts an UTF-8 or ASCII domain name to
|
||||
/* ASCII. The result is a null pointer in case of error. This
|
||||
/* function verifies that the result is a valid ASCII domainname.
|
||||
/*
|
||||
/* midna_ascii_to_utf8() converts an ASCII domain name to
|
||||
/* UTF-8. The result is a null pointer in case of error.
|
||||
/* midna_to_utf8() converts an UTF-8 or ASCII domain name to
|
||||
/* UTF-8. The result is a null pointer in case of error. This
|
||||
/* function verifies that the result converts to a valid ASCII
|
||||
/* domainname.
|
||||
/*
|
||||
/* midna_suffix_to_ascii() and midna_suffix_to_utf8() take a
|
||||
/* name that starts with '.' and otherwise perform the same
|
||||
/* operations as midna_to_ascii() and midna_to_utf8().
|
||||
/*
|
||||
/* midna_cache_size specifies the size of the conversion result
|
||||
/* cache. This value is used only once, upon the first lookup
|
||||
@ -31,7 +44,7 @@
|
||||
/* msg(3) diagnostics interface
|
||||
/* DIAGNOSTICS
|
||||
/* Fatal errors: memory allocation problem.
|
||||
/* Warnings: conversion error.
|
||||
/* Warnings: conversion error or result validation error.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -50,6 +63,7 @@
|
||||
*/
|
||||
#include <sys_defs.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef NO_EAI
|
||||
#include <unicode/uidna.h>
|
||||
@ -67,15 +81,18 @@
|
||||
/*
|
||||
* Application-specific.
|
||||
*/
|
||||
#define DEF_MIDNA_CACHE_SIZE 100
|
||||
#define DEF_MIDNA_CACHE_SIZE 256
|
||||
|
||||
int midna_cache_size = DEF_MIDNA_CACHE_SIZE;
|
||||
static VSTRING *midna_buf; /* x.suffix */
|
||||
|
||||
/* midna_utf8_to_ascii_create - convert UTF8 domain to ASCII */
|
||||
#define STR(x) vstring_str(x)
|
||||
|
||||
static void *midna_utf8_to_ascii_create(const char *name, void *unused_context)
|
||||
/* midna_to_ascii_create - convert domain to ASCII */
|
||||
|
||||
static void *midna_to_ascii_create(const char *name, void *unused_context)
|
||||
{
|
||||
static const char myname[] = "midna_utf8_to_ascii_create";
|
||||
static const char myname[] = "midna_to_ascii_create";
|
||||
char buf[1024]; /* XXX */
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
|
||||
@ -85,11 +102,15 @@ static void *midna_utf8_to_ascii_create(const char *name, void *unused_context)
|
||||
/*
|
||||
* Paranoia: do not expose uidna_*() to unfiltered network data.
|
||||
*/
|
||||
if (valid_utf8_string(name, strlen(name)) == 0) {
|
||||
msg_warn("%s: Problem translating domain \"%s\" to IDNA form: %s",
|
||||
if (allascii(name) == 0 && valid_utf8_string(name, strlen(name)) == 0) {
|
||||
msg_warn("%s: Problem translating domain \"%s\" to ASCII form: %s",
|
||||
myname, name, "malformed UTF-8");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the requested conversion.
|
||||
*/
|
||||
idna = uidna_openUTS46(UIDNA_DEFAULT, &error);
|
||||
anl = uidna_nameToASCII_UTF8(idna,
|
||||
name, strlen(name),
|
||||
@ -97,20 +118,32 @@ static void *midna_utf8_to_ascii_create(const char *name, void *unused_context)
|
||||
&info,
|
||||
&error);
|
||||
uidna_close(idna);
|
||||
|
||||
/*
|
||||
* Paranoia: verify that the result is a valid ASCII domain name. A quick
|
||||
* check shows that the UTS46 implementation will reject labels that
|
||||
* start or end in '-' or that are over-long, but let's play safe here.
|
||||
*/
|
||||
if (U_SUCCESS(error) && info.errors == 0 && anl > 0) {
|
||||
buf[anl] = 0; /* XXX */
|
||||
if (!valid_hostname(buf, DONT_GRIPE)) {
|
||||
msg_warn("%s: Problem translating domain \"%s\" to ASCII form: %s",
|
||||
myname, name, "malformed ASCII label(s)");
|
||||
return (0);
|
||||
}
|
||||
return (mystrndup(buf, anl));
|
||||
} else {
|
||||
msg_warn("%s: Problem translating domain \"%s\" to IDNA form: %s",
|
||||
msg_warn("%s: Problem translating domain \"%s\" to ASCII form: %s",
|
||||
myname, name, u_errorName(error));
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* midna_ascii_to_utf8_create - convert ASCII domain to UTF8 */
|
||||
/* midna_to_utf8_create - convert domain to UTF8 */
|
||||
|
||||
static void *midna_ascii_to_utf8_create(const char *name, void *unused_context)
|
||||
static void *midna_to_utf8_create(const char *name, void *unused_context)
|
||||
{
|
||||
static const char myname[] = "midna_ascii_to_utf8_create";
|
||||
static const char myname[] = "midna_to_utf8_create";
|
||||
char buf[1024]; /* XXX */
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
|
||||
@ -120,11 +153,15 @@ static void *midna_ascii_to_utf8_create(const char *name, void *unused_context)
|
||||
/*
|
||||
* 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");
|
||||
if (allascii(name) == 0 && valid_utf8_string(name, strlen(name)) == 0) {
|
||||
msg_warn("%s: Problem translating domain \"%s\" to UTF-8 form: %s",
|
||||
myname, name, "malformed UTF-8");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the requested conversion.
|
||||
*/
|
||||
idna = uidna_openUTS46(UIDNA_DEFAULT, &error);
|
||||
anl = uidna_nameToUnicodeUTF8(idna,
|
||||
name, strlen(name),
|
||||
@ -132,10 +169,18 @@ static void *midna_ascii_to_utf8_create(const char *name, void *unused_context)
|
||||
&info,
|
||||
&error);
|
||||
uidna_close(idna);
|
||||
|
||||
/*
|
||||
* Paranoia: UTS46 toUTF8 will accept and produce a name that does not
|
||||
* convert to a valid ASCII domain name. So we enforce sanity here.
|
||||
*/
|
||||
if (U_SUCCESS(error) && info.errors == 0 && anl > 0) {
|
||||
buf[anl] = 0; /* XXX */
|
||||
if (midna_to_ascii(buf) == 0)
|
||||
return (0);
|
||||
return (mystrndup(buf, anl));
|
||||
} else {
|
||||
msg_warn("%s: Problem translating domain \"%s\" to IDNA form: %s",
|
||||
msg_warn("%s: Problem translating domain \"%s\" to UTF8 form: %s",
|
||||
myname, name, u_errorName(error));
|
||||
return (0);
|
||||
}
|
||||
@ -149,39 +194,76 @@ static void midna_cache_free(void *value, void *unused_context)
|
||||
myfree(value);
|
||||
}
|
||||
|
||||
/* midna_utf8_to_ascii - convert UTF8 hostname to ASCII */
|
||||
/* midna_to_ascii - convert name to ASCII */
|
||||
|
||||
const char *midna_utf8_to_ascii(const char *name)
|
||||
const char *midna_to_ascii(const char *name)
|
||||
{
|
||||
static CTABLE *midna_utf8_to_ascii_cache = 0;
|
||||
static CTABLE *midna_to_ascii_cache = 0;
|
||||
|
||||
if (midna_utf8_to_ascii_cache == 0)
|
||||
midna_utf8_to_ascii_cache = ctable_create(midna_cache_size,
|
||||
midna_utf8_to_ascii_create,
|
||||
midna_cache_free,
|
||||
(void *) 0);
|
||||
return (ctable_locate(midna_utf8_to_ascii_cache, name));
|
||||
if (midna_to_ascii_cache == 0)
|
||||
midna_to_ascii_cache = ctable_create(midna_cache_size,
|
||||
midna_to_ascii_create,
|
||||
midna_cache_free,
|
||||
(void *) 0);
|
||||
return (ctable_locate(midna_to_ascii_cache, name));
|
||||
}
|
||||
|
||||
/* midna_ascii_to_utf8 - convert UTF8 hostname to ASCII */
|
||||
/* midna_to_utf8 - convert name to UTF8 */
|
||||
|
||||
const char *midna_ascii_to_utf8(const char *name)
|
||||
const char *midna_to_utf8(const char *name)
|
||||
{
|
||||
static CTABLE *midna_ascii_to_utf8_cache = 0;
|
||||
static CTABLE *midna_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));
|
||||
if (midna_to_utf8_cache == 0)
|
||||
midna_to_utf8_cache = ctable_create(midna_cache_size,
|
||||
midna_to_utf8_create,
|
||||
midna_cache_free,
|
||||
(void *) 0);
|
||||
return (ctable_locate(midna_to_utf8_cache, name));
|
||||
}
|
||||
|
||||
/* midna_suffix_to_ascii - convert .name to ASCII */
|
||||
|
||||
const char *midna_suffix_to_ascii(const char *suffix)
|
||||
{
|
||||
const char *cache_res;
|
||||
|
||||
/*
|
||||
* If prepending x to .name causes the result to become too long, then
|
||||
* the suffix is bad.
|
||||
*/
|
||||
if (midna_buf == 0)
|
||||
midna_buf = vstring_alloc(100);
|
||||
vstring_sprintf(midna_buf, "x%s", suffix);
|
||||
if ((cache_res = midna_to_ascii(STR(midna_buf))) == 0)
|
||||
return (0);
|
||||
else
|
||||
return (cache_res + 1);
|
||||
}
|
||||
|
||||
/* midna_suffix_to_utf8 - convert .name to UTF8 */
|
||||
|
||||
const char *midna_suffix_to_utf8(const char *name)
|
||||
{
|
||||
const char *cache_res;
|
||||
|
||||
/*
|
||||
* If prepending x to .name causes the result to become too long, then
|
||||
* the suffix is bad.
|
||||
*/
|
||||
if (midna_buf == 0)
|
||||
midna_buf = vstring_alloc(100);
|
||||
vstring_sprintf(midna_buf, "x%s", name);
|
||||
if ((cache_res = midna_to_utf8(STR(midna_buf))) == 0)
|
||||
return (0);
|
||||
else
|
||||
return (cache_res + 1);
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
/*
|
||||
* Test program - reads hostnames from stdin, reports invalid hostnames to
|
||||
* stderr.
|
||||
* Test program - reads names from stdin, reports invalid names to stderr.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
@ -207,26 +289,37 @@ int main(int argc, char **argv)
|
||||
temp_utf8_kludge = 1;
|
||||
|
||||
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
|
||||
msg_info("testing: \"%s\"", bp = vstring_str(buffer));
|
||||
bp = STR(buffer);
|
||||
msg_info("> %s", bp);
|
||||
while (ISSPACE(*bp))
|
||||
bp++;
|
||||
if (*bp == '#' || *bp == 0)
|
||||
continue;
|
||||
if (!allascii(bp)) {
|
||||
ascii = midna_utf8_to_ascii(bp);
|
||||
utf8 = midna_to_utf8(bp);
|
||||
if (utf8 != 0)
|
||||
msg_info("\"%s\" ->utf8 \"%s\"", bp, utf8);
|
||||
ascii = midna_to_ascii(bp);
|
||||
if (ascii != 0) {
|
||||
msg_info("\"%s\" -> \"%s\"", bp, ascii);
|
||||
utf8 = midna_ascii_to_utf8(ascii);
|
||||
msg_info("\"%s\" ->ascii \"%s\"", bp, ascii);
|
||||
utf8 = midna_to_utf8(ascii);
|
||||
if (utf8 != 0) {
|
||||
msg_info("\"%s\" -> \"%s\" -> \"%s\"",
|
||||
msg_info("\"%s\" ->ascii \"%s\" ->utf8 \"%s\"",
|
||||
bp, ascii, utf8);
|
||||
if (strcmp(utf8, bp) != 0)
|
||||
msg_warn("\"%s\" != \"%s\"", bp, utf8);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
utf8 = midna_ascii_to_utf8(bp);
|
||||
ascii = midna_to_ascii(bp);
|
||||
if (ascii != 0)
|
||||
msg_info("\"%s\" ->ascii \"%s\"", bp, ascii);
|
||||
utf8 = midna_to_utf8(bp);
|
||||
if (utf8 != 0) {
|
||||
msg_info("\"%s\" -> \"%s\"", bp, utf8);
|
||||
ascii = midna_utf8_to_ascii(utf8);
|
||||
msg_info("\"%s\" ->utf8 \"%s\"", bp, utf8);
|
||||
ascii = midna_to_ascii(utf8);
|
||||
if (ascii != 0) {
|
||||
msg_info("\"%s\" -> \"%s\" -> \"%s\"",
|
||||
msg_info("\"%s\" ->utf8 \"%s\" ->ascii \"%s\"",
|
||||
bp, utf8, ascii);
|
||||
if (strcmp(ascii, bp) != 0)
|
||||
msg_warn("\"%s\" != \"%s\"", bp, ascii);
|
||||
@ -237,6 +330,6 @@ int main(int argc, char **argv)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* TEST */
|
||||
|
||||
#endif
|
||||
#endif /* NO_EAI */
|
||||
|
@ -14,8 +14,10 @@
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern const char *midna_utf8_to_ascii(const char *);
|
||||
extern const char *midna_ascii_to_utf8(const char *);
|
||||
extern const char *midna_to_ascii(const char *);
|
||||
extern const char *midna_to_utf8(const char *);
|
||||
extern const char *midna_suffix_to_ascii(const char *);
|
||||
extern const char *midna_suffix_to_utf8(const char *);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
14
postfix/src/util/midna_test.in
Normal file
14
postfix/src/util/midna_test.in
Normal file
@ -0,0 +1,14 @@
|
||||
# Upper-case greek -> lower-case greek.
|
||||
Δημοσθένους.example.com
|
||||
# Upper-case ASCII -> lower-case ASCII.
|
||||
Hello.example.com
|
||||
# Invalid domain name ('-' at begin or end).
|
||||
-bad-.example.com
|
||||
# Invalid domain name (label > 62 bytes).
|
||||
abcdef01234567890abcdef01234567890abcdef01234567890abcdef0123456789.example.com
|
||||
# Valid domain name.
|
||||
abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com
|
||||
# Aliases for '.' -> '.'.
|
||||
x。example.com
|
||||
x.example.com
|
||||
x。example.com
|
71
postfix/src/util/midna_test.ref
Normal file
71
postfix/src/util/midna_test.ref
Normal file
@ -0,0 +1,71 @@
|
||||
./midna: > # Upper-case greek -> lower-case greek.
|
||||
./midna: > Δημοσθένους.example.com
|
||||
./midna: ctable_locate: install entry key δημοσθένουσ.example.com
|
||||
./midna: ctable_locate: install entry key Δημοσθένους.example.com
|
||||
./midna: "Δημοσθένους.example.com" ->utf8 "δημοσθένουσ.example.com"
|
||||
./midna: ctable_locate: install entry key Δημοσθένους.example.com
|
||||
./midna: "Δημοσθένους.example.com" ->ascii "xn--ixanjetild6aev.example.com"
|
||||
./midna: ctable_locate: move existing entry key δημοσθένουσ.example.com
|
||||
./midna: ctable_locate: install entry key xn--ixanjetild6aev.example.com
|
||||
./midna: "Δημοσθένους.example.com" ->ascii "xn--ixanjetild6aev.example.com" ->utf8 "δημοσθένουσ.example.com"
|
||||
./midna: warning: "Δημοσθένους.example.com" != "δημοσθένουσ.example.com"
|
||||
./midna: > # Upper-case ASCII -> lower-case ASCII.
|
||||
./midna: > Hello.example.com
|
||||
./midna: ctable_locate: install entry key Hello.example.com
|
||||
./midna: "Hello.example.com" ->ascii "hello.example.com"
|
||||
./midna: ctable_locate: install entry key hello.example.com
|
||||
./midna: ctable_locate: install entry key Hello.example.com
|
||||
./midna: "Hello.example.com" ->utf8 "hello.example.com"
|
||||
./midna: ctable_locate: leave existing entry key hello.example.com
|
||||
./midna: "Hello.example.com" ->utf8 "hello.example.com" ->ascii "hello.example.com"
|
||||
./midna: warning: "Hello.example.com" != "hello.example.com"
|
||||
./midna: > # Invalid domain name ('-' at begin or end).
|
||||
./midna: > -bad-.example.com
|
||||
./midna: warning: midna_to_ascii_create: Problem translating domain "-bad-.example.com" to ASCII form: U_ZERO_ERROR
|
||||
./midna: ctable_locate: install entry key -bad-.example.com
|
||||
./midna: warning: midna_to_utf8_create: Problem translating domain "-bad-.example.com" to UTF8 form: U_ZERO_ERROR
|
||||
./midna: ctable_locate: install entry key -bad-.example.com
|
||||
./midna: > # Invalid domain name (label > 62 bytes).
|
||||
./midna: > abcdef01234567890abcdef01234567890abcdef01234567890abcdef0123456789.example.com
|
||||
./midna: warning: midna_to_ascii_create: Problem translating domain "abcdef01234567890abcdef01234567890abcdef01234567890abcdef0123456789.example.com" to ASCII form: U_ZERO_ERROR
|
||||
./midna: ctable_locate: install entry key abcdef01234567890abcdef01234567890abcdef01234567890abcdef0123456789.example.com
|
||||
./midna: ctable_locate: leave existing entry key abcdef01234567890abcdef01234567890abcdef01234567890abcdef0123456789.example.com
|
||||
./midna: ctable_locate: install entry key abcdef01234567890abcdef01234567890abcdef01234567890abcdef0123456789.example.com
|
||||
./midna: > # Valid domain name.
|
||||
./midna: > abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com
|
||||
./midna: ctable_locate: install entry key abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com
|
||||
./midna: "abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com" ->ascii "abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com"
|
||||
./midna: ctable_locate: leave existing entry key abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com
|
||||
./midna: ctable_locate: install entry key abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com
|
||||
./midna: "abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com" ->utf8 "abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com"
|
||||
./midna: ctable_locate: leave existing entry key abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com
|
||||
./midna: "abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com" ->utf8 "abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com" ->ascii "abcdef01234567890abcdef01234567890abcdef01234567890abcdef012345.example.com"
|
||||
./midna: > # Aliases for '.' -> '.'.
|
||||
./midna: > x。example.com
|
||||
./midna: ctable_locate: install entry key x.example.com
|
||||
./midna: ctable_locate: install entry key x。example.com
|
||||
./midna: "x。example.com" ->utf8 "x.example.com"
|
||||
./midna: ctable_locate: install entry key x。example.com
|
||||
./midna: "x。example.com" ->ascii "x.example.com"
|
||||
./midna: ctable_locate: move existing entry key x.example.com
|
||||
./midna: ctable_locate: install entry key x.example.com
|
||||
./midna: "x。example.com" ->ascii "x.example.com" ->utf8 "x.example.com"
|
||||
./midna: warning: "x。example.com" != "x.example.com"
|
||||
./midna: > x.example.com
|
||||
./midna: ctable_locate: leave existing entry key x.example.com
|
||||
./midna: ctable_locate: install entry key x.example.com
|
||||
./midna: "x.example.com" ->utf8 "x.example.com"
|
||||
./midna: ctable_locate: install entry key x.example.com
|
||||
./midna: "x.example.com" ->ascii "x.example.com"
|
||||
./midna: ctable_locate: move existing entry key x.example.com
|
||||
./midna: "x.example.com" ->ascii "x.example.com" ->utf8 "x.example.com"
|
||||
./midna: warning: "x.example.com" != "x.example.com"
|
||||
./midna: > x。example.com
|
||||
./midna: ctable_locate: move existing entry key x.example.com
|
||||
./midna: ctable_locate: install entry key x。example.com
|
||||
./midna: "x。example.com" ->utf8 "x.example.com"
|
||||
./midna: ctable_locate: install entry key x。example.com
|
||||
./midna: "x。example.com" ->ascii "x.example.com"
|
||||
./midna: ctable_locate: move existing entry key x.example.com
|
||||
./midna: "x。example.com" ->ascii "x.example.com" ->utf8 "x.example.com"
|
||||
./midna: warning: "x。example.com" != "x.example.com"
|
@ -68,7 +68,7 @@ int valid_utf8_hostname(int enable_utf8, const char *name, int gripe)
|
||||
*/
|
||||
#ifndef NO_EAI
|
||||
if (enable_utf8 && !allascii(name)) {
|
||||
if ((aname = midna_utf8_to_ascii(name)) == 0) {
|
||||
if ((aname = midna_to_ascii(name)) == 0) {
|
||||
if (gripe)
|
||||
msg_warn("%s: malformed UTF-8 domain name", myname);
|
||||
return (0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user