Technically this might not be a bug, but it certainly allows any user to cause unexpected behaviour so I think it should be fixed...
It's possible to use header folding to append arbitrary data to the final 'Received:' header that smtpd generates, as smtpd does not reject an initial data line which begins with a space or a tab. Here is an example: # telnet ::1 25 Trying ::1... Connected to ::1. Escape character is '^]'. 220 mx3.example ESMTP OpenSMTPD helo foobar 250 mx3.example Hello foobar [::1], pleased to meet you mail from: <> 250 2.0.0 Ok rcpt to: <root> 250 2.1.5 Destination address valid: Recipient ok data 354 Enter mail, end with "." on a line by itself this will be appended :-/ Date: now Subject: header folding To: root From: Crystal Looks like a bug to me . 250 2.0.0 6af41037 Message accepted for delivery quit 221 2.0.0 Bye Connection closed by foreign host. # The headers are written to the mailbox as: Delivered-To: root@mx3.example Received: from foobar (localhost [::1]) by mx3.example (OpenSMTPD) with SMTP id 6af41037 for <root@mx3.example>; Mon, 27 Nov 2023 09:59:16 -0300 (-03) this will be appended :-/ Date: now Subject: header folding To: root@mx3.example From: Crystal@mx3.example I don't think that this is exactly exploitable in any way, but you could certainly append a different date to the last Received: header, which might cause software processing it to do something unexpected. The following patch causes smtpd to error out if a folding-continuation line is submitted as the first line of the mail. --- smtp_session.c.dist Mon Nov 27 09:58:26 2023 +++ smtp_session.c Mon Nov 27 11:50:18 2023 @@ -58,6 +58,7 @@ SF_BOUNCE = 0x0010, SF_VERIFIED = 0x0020, SF_BADINPUT = 0x0080, + SF_FOK = 0x0100, }; enum { @@ -1140,6 +1141,20 @@ if (s->tx->datain > env->sc_maxsize) s->tx->error = TX_ERROR_SIZE; } + + /* Check for header folding at start of input */ + if (!((s)->flags & SF_FOK) && (line[0]==' ' || + line[0]=='\t')) { + smtp_reply(s, "500 %s Header folding invalid " + "here", esc_code(ESC_STATUS_PERMFAIL, + ESC_OTHER_STATUS)); + smtp_enter_state(s, STATE_QUIT); + io_set_write(io); + return ; + } + + (s)->flags |= SF_FOK; + eom = (s->tx->filter == NULL) ? smtp_tx_dataline(s->tx, line) : smtp_tx_filtered_dataline(s->tx, line); @@ -1332,6 +1347,7 @@ if (!smtp_check_data(s, args)) break; smtp_filter_phase(FILTER_DATA, s, NULL); + s->flags &= ~SF_FOK; break; /*