1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2026-10-29 13:42:30 +00:00

fix(pop3): reject deleted messages and failed TLS handshakes (#620)

- RETR and TOP now respond "-ERR You deleted message N" for messages
  marked deleted, as RFC 1939 sections 5 (RETR) and 7 (TOP) require;
  previously the message content was still sent.
- STLS: a failed TLS handshake previously continued the session with
  the dead TLS connection installed as s.conn and a bogus tlsState,
  producing confusing follow-on errors. RFC 2595 section 4 requires
  the negotiation to complete before further commands, so a failure
  is now fatal: log it and terminate the session.

Updates the scripted tests that previously pinned the old behavior,
and adds a STLS handshake failure regression test.

Signed-off-by: James Hillyerd <james@hillyerd.com>
This commit is contained in:
James Hillyerd
2026-09-16 18:10:40 -07:00
committed by GitHub
parent 8bad098be9
commit a85a4ab996
3 changed files with 73 additions and 16 deletions
+15 -2
View File
@@ -235,8 +235,11 @@ func (s *Session) authorizationHandler(ctx context.Context, cmd string, args []s
s.send("+OK Begin TLS Negotiation")
tlsConn := tls.Server(s.conn, s.tlsConfig)
if err := tlsConn.HandshakeContext(tlsCtx); err != nil {
s.logger.Error().Msgf("-ERR TLS handshake failed %v", err)
s.ooSeq(cmd)
// RFC 2595 §4: the negotiation must complete before any further
// commands are sent, so a failure is fatal to the session.
s.logger.Error().Msgf("TLS handshake failed: %v", err)
s.enterState(QUIT)
return
}
s.conn = tlsConn
s.reader = bufio.NewReader(tlsConn)
@@ -328,6 +331,11 @@ func (s *Session) transactionHandler(cmd string, args []string) {
if !ok {
return
}
if !s.retain[msgNum-1] {
s.logger.Warn().Msgf("Client tried to RETR a message it had deleted")
s.send(fmt.Sprintf("-ERR You deleted message %v", msgNum))
return
}
s.send(fmt.Sprintf("+OK %v bytes follows", s.messages[msgNum-1].Size()))
s.sendMessageLines(s.messages[msgNum-1], -1)
case "TOP":
@@ -353,6 +361,11 @@ func (s *Session) transactionHandler(cmd string, args []string) {
s.send("-ERR TOP second argument must be non-negative")
return
}
if !s.retain[msgNum-1] {
s.logger.Warn().Msgf("Client tried to TOP a message it had deleted")
s.send(fmt.Sprintf("-ERR You deleted message %v", msgNum))
return
}
s.send("+OK Top of message follows")
s.sendMessageLines(s.messages[msgNum-1], int(lines))
case "QUIT":