Discussion:
IPv6 address literal issue in 'smtp'
Gurusamy Sarathy
2011-02-24 22:30:50 UTC
Permalink
Hi,

I've run into an issue with the IPv6 support in postfix when it is
set up to deliver to a literal IPv6 address in the transport table.
It looks like 'smtpd' will only accept IPv6 address literals in RFC
2821 format while 'smtp' will only accept IPv6 address literals in
the unadorned form (without the ipv6: prefix).

The (minimalist) patch below my sig appears to fix the issue, but
I suspect a better fix would be to refactor the various places in
the code that handle address literals to rationalize things a bit more.


Sarathy
***@sophos.com
-----------------------------------8<-----------------------------------
Index: postfix-2.8.1-RC1/src/global/valid_mailhost_addr.c
--- postfix-2.8.1-RC1/src/global/valid_mailhost_addr.c.~1~ Wed Feb 23 17:33:00 2011
+++ postfix-2.8.1-RC1/src/global/valid_mailhost_addr.c Wed Feb 23 17:33:00 2011
@@ -68,12 +68,6 @@

#include <valid_mailhost_addr.h>

-/* Application-specific. */
-
-#define IPV6_COL_LEN (sizeof(IPV6_COL) - 1)
-#define HAS_IPV6_COL(str) (strncasecmp((str), IPV6_COL, IPV6_COL_LEN) == 0)
-#define SKIP_IPV6_COL(str) (HAS_IPV6_COL(str) ? (str) + IPV6_COL_LEN : (str))
-
/* valid_mailhost_addr - validate RFC 2821 numerical address form */

const char *valid_mailhost_addr(const char *addr, int gripe)
Index: postfix-2.8.1-RC1/src/global/valid_mailhost_addr.h
--- postfix-2.8.1-RC1/src/global/valid_mailhost_addr.h.~1~ Wed Feb 23 17:33:00 2011
+++ postfix-2.8.1-RC1/src/global/valid_mailhost_addr.h Wed Feb 23 17:33:00 2011
@@ -15,11 +15,7 @@
* Utility library.
*/
#include <valid_hostname.h>
-
- /*
- * External interface
- */
-#define IPV6_COL "IPv6:" /* RFC 2821 */
+#include <host_port.h>

extern const char *valid_mailhost_addr(const char *, int);
extern int valid_mailhost_literal(const char *, int);
Index: postfix-2.8.1-RC1/src/util/host_port.c
--- postfix-2.8.1-RC1/src/util/host_port.c.~1~ Wed Feb 23 17:33:00 2011
+++ postfix-2.8.1-RC1/src/util/host_port.c Wed Feb 23 17:33:00 2011
@@ -22,6 +22,8 @@
/*
/* When def_service is not null, and def_host is null:
/*
+/* [IPv6:host]:port, [IPv6:host]:, [IPV6:host]
+/*
/* [host]:port, [host]:, [host]
/*
/* host:port, host:, host
@@ -106,7 +108,9 @@
* [host]:port, [host]:, [host].
*/
if (*cp == '[') {
- *host = ++cp;
+ ++cp;
+ /* skip past RFC2821 IPv6: prefix, if any */
+ *host = cp = SKIP_IPV6_COL(cp);
if ((cp = split_at(cp, ']')) == 0)
return ("missing \"]\"");
if (*cp && *cp++ != ':')
Index: postfix-2.8.1-RC1/src/util/host_port.h
--- postfix-2.8.1-RC1/src/util/host_port.h.~1~ Wed Feb 23 17:33:00 2011
+++ postfix-2.8.1-RC1/src/util/host_port.h Wed Feb 23 17:33:00 2011
@@ -12,6 +12,10 @@
/* .nf

/* External interface. */
+#define IPV6_COL "IPv6:" /* RFC 2821 */
+#define IPV6_COL_LEN (sizeof(IPV6_COL) - 1)
+#define HAS_IPV6_COL(str) (strncasecmp((str), IPV6_COL, IPV6_COL_LEN) == 0)
+#define SKIP_IPV6_COL(str) (HAS_IPV6_COL(str) ? (str) + IPV6_COL_LEN : (str))

extern const char *host_port(char *, char **, char *, char **, char *);

End of Patch.
Victor Duchovni
2011-02-24 22:43:24 UTC
Permalink
On Thu, Feb 24, 2011 at 02:30:50PM -0800, Gurusamy Sarathy wrote:

> I've run into an issue with the IPv6 support in postfix when it is
> set up to deliver to a literal IPv6 address in the transport table.
> It looks like 'smtpd' will only accept IPv6 address literals in RFC
> 2821 format while 'smtp' will only accept IPv6 address literals in
> the unadorned form (without the ipv6: prefix).

The documented smtp(8) nexthop syntax is:

http://www.postfix.org/smtp.8.html

SMTP DESTINATION SYNTAX
SMTP destinations have the following form:

...

[address]:port
Connect to the host at the specified address, and
connect to the specified port (default: smtp). An
IPv6 address must be formatted as [ipv6:address].

If this is not the case, perhaps you are reporting a bug, rather
than a missing feature?

--
Viktor.
Gurusamy Sarathy
2011-02-24 22:55:05 UTC
Permalink
Hi Victor,

Sorry, didn't mean to suggest it is a missing feature--it does look like a bug to me. The documented form doesn't work.

BTW, the errors in the logs look like this:

Feb 23 10:32:46 vm-rhes5-01 postfix/smtp[1062]: fatal: valid hostname or network address required in server description: [IPv6:fe80::250:56ff:fe82:54b5]
Feb 23 10:32:47 vm-rhes5-01 postfix/qmgr[544]: warning: private/smtp socket: malformed response
Feb 23 10:32:47 vm-rhes5-01 postfix/qmgr[544]: warning: transport smtp failure -- see a previous warning/fatal/panic logfile record for the problem description
Feb 23 10:32:47 vm-rhes5-01 postfix/master[542]: warning: process /opt/pmx/postfix/libexec/smtp pid 1062 exit status 1
Feb 23 10:32:47 vm-rhes5-01 postfix/master[542]: warning: /opt/pmx/postfix/libexec/smtp: bad command startup -- throttling

Google reveals other people have run into the issue, but perhaps no one bothered to patch it as the problem can be worked around by adding a DNS entry.

Sarathy


-----Original Message-----
From: owner-postfix-***@postfix.org [mailto:owner-postfix-***@postfix.org] On Behalf Of Victor Duchovni
Sent: Thursday, February 24, 2011 2:43 PM
To: postfix-***@postfix.org
Subject: Re: IPv6 address literal issue in 'smtp'

On Thu, Feb 24, 2011 at 02:30:50PM -0800, Gurusamy Sarathy wrote:

> I've run into an issue with the IPv6 support in postfix when it is
> set up to deliver to a literal IPv6 address in the transport table.
> It looks like 'smtpd' will only accept IPv6 address literals in RFC
> 2821 format while 'smtp' will only accept IPv6 address literals in
> the unadorned form (without the ipv6: prefix).

The documented smtp(8) nexthop syntax is:

http://www.postfix.org/smtp.8.html

SMTP DESTINATION SYNTAX
SMTP destinations have the following form:

...

[address]:port
Connect to the host at the specified address, and
connect to the specified port (default: smtp). An
IPv6 address must be formatted as [ipv6:address].

If this is not the case, perhaps you are reporting a bug, rather
than a missing feature?

--
Viktor.
Victor Duchovni
2011-02-25 06:00:50 UTC
Permalink
On Thu, Feb 24, 2011 at 05:55:05PM -0500, Gurusamy Sarathy wrote:

> Sorry, didn't mean to suggest it is a missing feature--it does look
> like a bug to me. The documented form doesn't work.
>
> Feb 23 10:32:46 vm-rhes5-01 postfix/smtp[1062]: fatal: valid hostname or network address required in server description: [IPv6:fe80::250:56ff:fe82:54b5]

Yep, indeed host_port() seems to pass "ipv6:..." to valid_hostaddr(),
which calls valid_ipv6_hostaddr(), which is not prepared for the
"ipv6:" prefix.

Perhaps the call to valid_hostaddr() should be replaced by a call to
valid_mailhost_addr(), and the result used to update the "bare" host
address returned from host_port().

Perhaps the simpler patch below will do the job. Please drop the list
a note when you have checked whether this also solves the problem.

Index: src/util/host_port.c
*** src/util/host_port.c 6 Feb 2010 07:35:12 -0000 1.1.1.1
--- src/util/host_port.c 25 Feb 2011 05:57:57 -0000
***************
*** 136,142 ****
* network addresses instead of requiring proper [ipaddress] forms.
*/
if (*host != def_host && !valid_hostname(*host, DONT_GRIPE)
! && !valid_hostaddr(*host, DONT_GRIPE))
return ("valid hostname or network address required");
if (*port != def_service && ISDIGIT(**port) && !alldig(*port))
return ("garbage after numerical service");
--- 136,142 ----
* network addresses instead of requiring proper [ipaddress] forms.
*/
if (*host != def_host && !valid_hostname(*host, DONT_GRIPE)
! && (*host = valid_mailhost_addr(*host, DONT_GRIPE)) == 0)
return ("valid hostname or network address required");
if (*port != def_service && ISDIGIT(**port) && !alldig(*port))
return ("garbage after numerical service");

--
Viktor.
Victor Duchovni
2011-02-25 06:18:28 UTC
Permalink
On Fri, Feb 25, 2011 at 01:00:50AM -0500, Victor Duchovni wrote:

> Perhaps the simpler patch below will do the job. Please drop the list
> a note when you have checked whether this also solves the problem.
>
> Index: src/util/host_port.c
> *** src/util/host_port.c 6 Feb 2010 07:35:12 -0000 1.1.1.1
> --- src/util/host_port.c 25 Feb 2011 05:57:57 -0000

Oops, this will likely break other uses of [ipv6addr]:port in which the
[ipv6:...] format is not required, e.g. in the master.cf file, where
the format is just addr:port with no "[]" at all.

--
Viktor.
Wietse Venema
2011-02-25 13:42:14 UTC
Permalink
Victor Duchovni:
> On Thu, Feb 24, 2011 at 05:55:05PM -0500, Gurusamy Sarathy wrote:
>
> > Sorry, didn't mean to suggest it is a missing feature--it does look
> > like a bug to me. The documented form doesn't work.
> >
> > Feb 23 10:32:46 vm-rhes5-01 postfix/smtp[1062]: fatal: valid hostname or network address required in server description: [IPv6:fe80::250:56ff:fe82:54b5]
>
> Yep, indeed host_port() seems to pass "ipv6:..." to valid_hostaddr(),
> which calls valid_ipv6_hostaddr(), which is not prepared for the
> "ipv6:" prefix.
>
> Perhaps the call to valid_hostaddr() should be replaced by a call to
> valid_mailhost_addr(), and the result used to update the "bare" host
> address returned from host_port().
>
> Perhaps the simpler patch below will do the job. Please drop the list
> a note when you have checked whether this also solves the problem.
>
> Index: src/util/host_port.c
> *** src/util/host_port.c 6 Feb 2010 07:35:12 -0000 1.1.1.1
> --- src/util/host_port.c 25 Feb 2011 05:57:57 -0000
> ***************
> *** 136,142 ****
> * network addresses instead of requiring proper [ipaddress] forms.
> */
> if (*host != def_host && !valid_hostname(*host, DONT_GRIPE)
> ! && !valid_hostaddr(*host, DONT_GRIPE))
> return ("valid hostname or network address required");
> if (*port != def_service && ISDIGIT(**port) && !alldig(*port))
> return ("garbage after numerical service");
> --- 136,142 ----
> * network addresses instead of requiring proper [ipaddress] forms.
> */
> if (*host != def_host && !valid_hostname(*host, DONT_GRIPE)
> ! && (*host = valid_mailhost_addr(*host, DONT_GRIPE)) == 0)

The IPV6: prefix is required in "SMTP email" context but not
elsewhere.

The practical solution is to strip the IPV6: prefix if it exists,
while allowing address forms without IPV6: to avoid breaking existing
configurations.

Wietse
Wietse Venema
2011-02-25 16:01:02 UTC
Permalink
Gurusamy Sarathy:
> Hi,
>
> I've run into an issue with the IPv6 support in postfix when it is
> set up to deliver to a literal IPv6 address in the transport table.
> It looks like 'smtpd' will only accept IPv6 address literals in RFC
> 2821 format while 'smtp' will only accept IPv6 address literals in
> the unadorned form (without the ipv6: prefix).

Aha. This has been broken since IPv6 support was added to Postfix.

Thanks for reporting this here. Unfortunately I don't have the time
to scrape every blog on the web for Postfix problem reports.

The patch below provides a workaround. I have followed your approach
to do minimal damage, and have added a simple sanity check so that
Postfix won't accept forms with [ipv6:hostname] or [ipv6:127.0.0.1].

If some site has omitted the ipv6: prefix in some transport map or
config file, then this patch won't break backwards compatibility.
In the final fix, Postfix should issue a warning that the form
[ipv6addr] is not supported, and that it will become a fatal error.

The final fix would require structural change, but that is allowed
only in the development release. Stable releases are sacred.

Wietse
Gurusamy Sarathy
2011-02-25 16:23:59 UTC
Permalink
Thanks Wietse, the extra check is a good idea indeed. I haven't tried your patch yet, but shouldn't valid_ipv6_hostaddr(host, ...) in your patch read valid_ipv6_hostaddr(*host, ...) instead? Otherwise it would seem we're passing char** where char* is expected. Hope I'm not misreading the patch.

Sarathy

________________________________________
From: Wietse Venema [***@porcupine.org]
Sent: Friday, February 25, 2011 8:01 AM
To: Gurusamy Sarathy
Cc: postfix-***@postfix.org
Subject: Re: IPv6 address literal issue in 'smtp'

Gurusamy Sarathy:
> Hi,
>
> I've run into an issue with the IPv6 support in postfix when it is
> set up to deliver to a literal IPv6 address in the transport table.
> It looks like 'smtpd' will only accept IPv6 address literals in RFC
> 2821 format while 'smtp' will only accept IPv6 address literals in
> the unadorned form (without the ipv6: prefix).

Aha. This has been broken since IPv6 support was added to Postfix.

Thanks for reporting this here. Unfortunately I don't have the time
to scrape every blog on the web for Postfix problem reports.

The patch below provides a workaround. I have followed your approach
to do minimal damage, and have added a simple sanity check so that
Postfix won't accept forms with [ipv6:hostname] or [ipv6:127.0.0.1].

If some site has omitted the ipv6: prefix in some transport map or
config file, then this patch won't break backwards compatibility.
In the final fix, Postfix should issue a warning that the form
[ipv6addr] is not supported, and that it will become a fatal error.

The final fix would require structural change, but that is allowed
only in the development release. Stable releases are sacred.

Wietse
Wietse Venema
2011-02-25 16:37:22 UTC
Permalink
Gurusamy Sarathy:
> Thanks Wietse, the extra check is a good idea indeed. I haven't
> tried your patch yet, but shouldn't valid_ipv6_hostaddr(host, ...)
> in your patch read valid_ipv6_hostaddr(*host, ...) instead?
> Otherwise it would seem we're passing char** where char* is
> expected. Hope I'm not misreading the patch.

Indeed. I added the syntax check after verifying that Postfix
now delivers user@[ipv6:addr] properly.

I hate it when programs silently accept bogus input such as
IPV6: prepended to a hostname or IPv4 address.

Wietse

>
> ________________________________________
> From: Wietse Venema [***@porcupine.org]
> Sent: Friday, February 25, 2011 8:01 AM
> To: Gurusamy Sarathy
> Cc: postfix-***@postfix.org
> Subject: Re: IPv6 address literal issue in 'smtp'
>
> Gurusamy Sarathy:
> > Hi,
> >
> > I've run into an issue with the IPv6 support in postfix when it is
> > set up to deliver to a literal IPv6 address in the transport table.
> > It looks like 'smtpd' will only accept IPv6 address literals in RFC
> > 2821 format while 'smtp' will only accept IPv6 address literals in
> > the unadorned form (without the ipv6: prefix).
>
> Aha. This has been broken since IPv6 support was added to Postfix.
>
> Thanks for reporting this here. Unfortunately I don't have the time
> to scrape every blog on the web for Postfix problem reports.
>
> The patch below provides a workaround. I have followed your approach
> to do minimal damage, and have added a simple sanity check so that
> Postfix won't accept forms with [ipv6:hostname] or [ipv6:127.0.0.1].
>
> If some site has omitted the ipv6: prefix in some transport map or
> config file, then this patch won't break backwards compatibility.
> In the final fix, Postfix should issue a warning that the form
> [ipv6addr] is not supported, and that it will become a fatal error.
>
> The final fix would require structural change, but that is allowed
> only in the development release. Stable releases are sacred.
>
> Wietse
>
Loading...