Harden STARTTLS handlers and add per-dialect tests

Bound line reads with readLineLimited to prevent a peer from exhausting
memory by withholding line terminators, wrap previously bare error
returns for consistent context, surface XML decoder Skip errors, and
replace the goto in the XMPP feature scan with a labeled break. New
starttls_test.go exercises SMTP/IMAP/POP3/XMPP/LDAP success and
not-advertised paths through net.Pipe-mocked servers.
This commit is contained in:
nemunaire 2026-04-25 23:15:06 +07:00
commit e32633ca40
6 changed files with 330 additions and 19 deletions

View file

@ -15,7 +15,7 @@ func init() {
func starttlsPOP3(conn net.Conn, sni string) error {
rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
greeting, err := rw.ReadString('\n')
greeting, err := readLineLimited(rw.Reader)
if err != nil {
return fmt.Errorf("read greeting: %w", err)
}
@ -24,19 +24,19 @@ func starttlsPOP3(conn net.Conn, sni string) error {
}
if _, err := rw.WriteString("CAPA\r\n"); err != nil {
return err
return fmt.Errorf("write CAPA: %w", err)
}
if err := rw.Flush(); err != nil {
return err
return fmt.Errorf("flush CAPA: %w", err)
}
first, err := rw.ReadString('\n')
first, err := readLineLimited(rw.Reader)
if err != nil {
return fmt.Errorf("read CAPA: %w", err)
}
supportsSTLS := false
if strings.HasPrefix(first, "+OK") {
for {
line, err := rw.ReadString('\n')
line, err := readLineLimited(rw.Reader)
if err != nil {
return fmt.Errorf("read CAPA body: %w", err)
}
@ -54,12 +54,12 @@ func starttlsPOP3(conn net.Conn, sni string) error {
}
if _, err := rw.WriteString("STLS\r\n"); err != nil {
return err
return fmt.Errorf("write STLS: %w", err)
}
if err := rw.Flush(); err != nil {
return err
return fmt.Errorf("flush STLS: %w", err)
}
resp, err := rw.ReadString('\n')
resp, err := readLineLimited(rw.Reader)
if err != nil {
return fmt.Errorf("read STLS response: %w", err)
}