smtp: align BDAT error recovery with Postfix
Debian Trixie package bundle / packages (push) Successful in 22m21s

This commit is contained in:
Mario Fetka
2026-07-27 19:37:20 +02:00
parent 59e8af7ebf
commit 8fcff3fa4b
2 changed files with 273 additions and 2 deletions
+45 -2
View File
@@ -289,6 +289,7 @@ typedef struct
BOOL IsEHLO; /* used for RFC 3848 */
BOOL HasSPFResult;
BOOL NMAPMessageWrite;
BOOL BdatDiscard;
FILE *BdatMessage;
uint64_t BdatLength;
BongoSPFResponse SPFResult;
@@ -902,6 +903,7 @@ SMTPClearTransaction(ConnectionStruct *client, unsigned long next_state)
client->RcptCommandCount = 0;
client->MsgFlags = MSG_FLAG_ENCODING_NONE;
client->HasSPFResult = FALSE;
client->BdatDiscard = FALSE;
memset(&client->SPFResult, 0, sizeof(client->SPFResult));
if (client->BdatMessage != NULL) {
fclose(client->BdatMessage);
@@ -919,7 +921,8 @@ SMTPResetTransaction(ConnectionStruct *client, unsigned long next_state)
{
char reply[BUFSIZE + 1];
if (client->State >= STATE_FROM && client->State <= STATE_BDAT) {
if (client->State >= STATE_FROM && client->State <= STATE_BDAT &&
!client->BdatDiscard) {
if (NMAPSendCommand(client->nmap.conn, "QABRT\r\n", 7) < 0 ||
NMAPReadResponse(client->nmap.conn, reply, sizeof(reply), TRUE) !=
1000) return FALSE;
@@ -973,7 +976,8 @@ EndClientConnection (ConnectionStruct * Client)
* closing it lets the queue discard the incomplete entry. */
FreeInternalConnection(Client->nmap);
} else if (Client->Flags >= STATE_FROM &&
Client->Flags <= STATE_BDAT) {
Client->Flags <= STATE_BDAT &&
!Client->BdatDiscard) {
if (NMAPSendCommand(Client->nmap.conn, "QABRT\r\n", 7) >= 0 &&
NMAPReadResponse(Client->nmap.conn, Reply, sizeof(Reply),
TRUE) == 1000) {
@@ -2189,6 +2193,26 @@ HandleConnection (void *param)
ConnFlush(Client->client.conn);
return EndClientConnection(Client);
}
if (Client->BdatDiscard) {
if (ConnDiscard64(Client->client.conn, ChunkSize) < 0)
return EndClientConnection(Client);
if (LastChunk) {
SMTPClearTransaction(
Client,
IsAuthed ? STATE_AUTH : STATE_HELO);
}
count = snprintf(
Answer, sizeof(Answer),
"551 5.0.0 Discarded %" PRIu64
" bytes after earlier BDAT error\r\n",
ChunkSize);
if (count < 0 ||
(size_t)count >= sizeof(Answer))
return EndClientConnection(Client);
ConnWrite(Client->client.conn, Answer,
(size_t)count);
break;
}
if (!Client->IsEHLO ||
(Client->State != STATE_TO &&
Client->State != STATE_BDAT)) {
@@ -2203,6 +2227,21 @@ HandleConnection (void *param)
MSG503BADORDER_LEN);
break;
}
if (ChunkSize == 0U && !LastChunk) {
if (!SMTPResetTransaction(
Client,
IsAuthed ? STATE_AUTH : STATE_HELO))
return EndClientConnection(Client);
Client->State = STATE_BDAT;
Client->BdatDiscard = TRUE;
NullSender = FALSE;
TooManyNullSenderRecips = FALSE;
ConnWrite(
Client->client.conn,
"551 5.7.1 Null BDAT request\r\n",
sizeof("551 5.7.1 Null BDAT request\r\n") - 1U);
break;
}
if (Client->State == STATE_TO) {
Client->BdatMessage = tmpfile();
if (Client->BdatMessage == NULL) {
@@ -2233,6 +2272,10 @@ HandleConnection (void *param)
if (!SMTPResetTransaction(
Client, IsAuthed ? STATE_AUTH : STATE_HELO))
return EndClientConnection(Client);
if (!LastChunk) {
Client->State = STATE_BDAT;
Client->BdatDiscard = TRUE;
}
NullSender = FALSE;
TooManyNullSenderRecips = FALSE;
ConnWrite(Client->client.conn, MSG552MSGTOOBIG,