smtp: distinguish bad paths from unknown users
Debian Trixie package bundle / packages (push) Successful in 15m54s
Debian Trixie package bundle / packages (push) Successful in 15m54s
This commit is contained in:
@@ -233,7 +233,49 @@ SMTPPathIsSafe(const char *path)
|
||||
int
|
||||
SMTPRecipientPathIsValid(const char *path)
|
||||
{
|
||||
return path != NULL && path[0] != '\0' && SMTPPathIsSafe(path);
|
||||
const unsigned char *cursor = (const unsigned char *)path;
|
||||
const unsigned char *separator = NULL;
|
||||
const unsigned char *local_end;
|
||||
int previous_dot = 0;
|
||||
|
||||
if (cursor == NULL || *cursor == '\0' || !SMTPPathIsSafe(path)) return 0;
|
||||
|
||||
/*
|
||||
* RewriteAddress() understands obsolete percent routes, but accepting a
|
||||
* second raw '@' here would turn malformed SMTP input into a routing
|
||||
* lookup and make it indistinguishable from an unknown mailbox. Its
|
||||
* resolver protocol cannot preserve quoted local-parts, so accept the
|
||||
* RFC 5321 dot-string form here rather than silently changing one.
|
||||
*/
|
||||
local_end = cursor;
|
||||
while (*local_end != '\0' && *local_end != '@') local_end++;
|
||||
if (local_end == cursor) return 0;
|
||||
while (cursor < local_end) {
|
||||
unsigned char current = *cursor++;
|
||||
|
||||
if (current == '.') {
|
||||
if (previous_dot ||
|
||||
cursor - 1 == (const unsigned char *)path) return 0;
|
||||
previous_dot = 1;
|
||||
continue;
|
||||
}
|
||||
previous_dot = 0;
|
||||
if (current >= 0x80U || isalnum(current) ||
|
||||
strchr("!#$%&'*+-/=?^_`{|}~", current) != NULL)
|
||||
continue;
|
||||
return 0;
|
||||
}
|
||||
if (previous_dot) return 0;
|
||||
if (*local_end == '@') {
|
||||
separator = local_end;
|
||||
cursor = local_end + 1;
|
||||
} else {
|
||||
cursor = local_end;
|
||||
}
|
||||
|
||||
if (separator == NULL) return *cursor == '\0';
|
||||
if (*cursor == '\0' || strchr((const char *)cursor, '@') != NULL) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -1582,7 +1582,8 @@ HandleConnection (void *param)
|
||||
if ((ReplyInt = RewriteAddress (Client->nmap.conn,
|
||||
RoutingName, To,
|
||||
sizeof (To))) == MAIL_BOGUS) {
|
||||
ConnWrite (Client->client.conn, MSG501RECIPNO, MSG501RECIPNO_LEN);
|
||||
ConnWrite(Client->client.conn, MSG550NOTFOUND,
|
||||
MSG550NOTFOUND_LEN);
|
||||
}
|
||||
else {
|
||||
if (ReplyInt == MAIL_REMOTE &&
|
||||
|
||||
@@ -143,10 +143,20 @@ TestPaths(void)
|
||||
assert(!SMTPPathIsSafe("user> SIZE=0"));
|
||||
assert(!SMTPPathIsSafe("bad\177@example.test"));
|
||||
assert(SMTPRecipientPathIsValid("user@example.test"));
|
||||
assert(SMTPRecipientPathIsValid("smtp18-missing-600189@example.test"));
|
||||
assert(SMTPRecipientPathIsValid("m\303\274ller@example.test"));
|
||||
assert(!SMTPRecipientPathIsValid(NULL));
|
||||
assert(!SMTPRecipientPathIsValid(""));
|
||||
assert(!SMTPRecipientPathIsValid("user name@example.test"));
|
||||
assert(!SMTPRecipientPathIsValid("@example.test"));
|
||||
assert(!SMTPRecipientPathIsValid("user@"));
|
||||
assert(!SMTPRecipientPathIsValid("bad@@example.test"));
|
||||
assert(!SMTPRecipientPathIsValid(".user@example.test"));
|
||||
assert(!SMTPRecipientPathIsValid("user.@example.test"));
|
||||
assert(!SMTPRecipientPathIsValid("user..tag@example.test"));
|
||||
assert(!SMTPRecipientPathIsValid("\"quoted local\"@example.test"));
|
||||
assert(!SMTPRecipientPathIsValid("\"quoted@local\"@example.test"));
|
||||
assert(!SMTPRecipientPathIsValid("\"unterminated@example.test"));
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
Reference in New Issue
Block a user