smtp: deliver IPv4 address literals directly
Debian Trixie package bundle / packages (push) Successful in 16m1s

This commit is contained in:
Mario Fetka
2026-07-28 13:30:11 +02:00
parent af04096d31
commit 8daa2dfbfd
+50 -1
View File
@@ -499,6 +499,8 @@ Connection *LookupRemoteMX(RecipStruct *Recipient, char *hostname,
XplDns_MxLookup *mx = NULL;
XplDns_IpList *list = NULL;
Connection *Result=NULL;
struct in_addr literalAddress;
BOOL addressLiteral = FALSE;
if (hostname == NULL || hostnameSize == 0 || canonicalHostname == NULL ||
canonicalHostnameSize == 0 || nextHopDomain == NULL ||
@@ -533,7 +535,13 @@ Connection *LookupRemoteMX(RecipStruct *Recipient, char *hostname,
*(Recipient->localPart-1) = '@';
return Result;
}
// FIXME: assumes our DNS routines will accept IP address.
if (inet_pton(AF_INET, Host, &literalAddress) != 1) {
Recipient->Result = DELIVER_BOGUS_NAME;
*end = ']';
*(Recipient->localPart-1) = '@';
return Result;
}
addressLiteral = TRUE;
*end = ']';
} else {
size_t hostLength = strlen(Recipient->SortField);
@@ -549,6 +557,47 @@ Connection *LookupRemoteMX(RecipStruct *Recipient, char *hostname,
/* make sure to reset the SortField as it was previously */
*(Recipient->localPart-1) = '@';
/*
* RFC 5321 address literals bypass MX and address lookups. Besides
* avoiding a meaningless DNS query, this preserves the literal as the
* next-hop identity and prevents DNSSEC state from being inferred for it.
*/
if (addressLiteral) {
int status;
snprintf(hostname, hostnameSize, "%s", Host);
snprintf(canonicalHostname, canonicalHostnameSize, "%s", Host);
snprintf(nextHopDomain, nextHopDomainSize, "%s", Host);
Result = ConnAlloc(TRUE);
if (Result == NULL) {
Recipient->Result = DELIVER_INTERNAL_ERROR;
goto finish;
}
Result->socketAddress.sin_addr = literalAddress;
Result->socketAddress.sin_family = AF_INET;
Result->socketAddress.sin_port = htons(25);
status = ConnConnect(Result, NULL, 0, NULL);
if (status <= 0) {
switch (errno) {
case ETIMEDOUT:
Recipient->Result = DELIVER_TIMEOUT;
break;
case ECONNREFUSED:
Recipient->Result = DELIVER_REFUSED;
break;
case ENETUNREACH:
Recipient->Result = DELIVER_UNREACHABLE;
break;
default:
Recipient->Result = DELIVER_TRY_LATER;
break;
}
ConnFree(Result);
Result = NULL;
}
goto finish;
}
/* DNS and the normalized SMTP envelope both use the same IDNA2008
* A-label. This also validates ASCII domains before lookup. */
if (!BongoDomainToASCII(Host, asciiHost, sizeof(asciiHost))) {