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:
parent
4177fcdc7b
commit
e32633ca40
6 changed files with 330 additions and 19 deletions
|
|
@ -1,6 +1,41 @@
|
|||
package checker
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
// maxSTARTTLSLineBytes caps the length of a single line read from a STARTTLS
|
||||
// peer. Real banners and CAPABILITY responses are well under 1 KiB; this
|
||||
// bound prevents a malicious or buggy server from exhausting memory by
|
||||
// withholding the line terminator.
|
||||
const maxSTARTTLSLineBytes = 8 * 1024
|
||||
|
||||
// readLineLimited reads bytes from r up to and including the next '\n', or
|
||||
// until maxSTARTTLSLineBytes have been read without one (in which case it
|
||||
// returns an error). The returned string keeps the trailing '\n' so callers
|
||||
// can use the same parsing logic as bufio.Reader.ReadString('\n').
|
||||
func readLineLimited(r *bufio.Reader) (string, error) {
|
||||
out := make([]byte, 0, 128)
|
||||
for {
|
||||
b, err := r.ReadByte()
|
||||
if err != nil {
|
||||
if err == io.EOF && len(out) > 0 {
|
||||
return string(out), io.ErrUnexpectedEOF
|
||||
}
|
||||
return string(out), err
|
||||
}
|
||||
out = append(out, b)
|
||||
if b == '\n' {
|
||||
return string(out), nil
|
||||
}
|
||||
if len(out) >= maxSTARTTLSLineBytes {
|
||||
return string(out), fmt.Errorf("line exceeds %d bytes without terminator", maxSTARTTLSLineBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// starttlsUpgrader performs the plaintext portion of a STARTTLS upgrade on
|
||||
// conn, leaving conn ready for tls.Client(conn, …).Handshake(). On success
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue