Handle too long lines. Make envelope reset into a session method.
This commit is contained in:
parent
50ed5fd57a
commit
38a9c27d35
3 changed files with 70 additions and 9 deletions
18
protocol.go
18
protocol.go
|
@ -38,6 +38,10 @@ func (session *session) handle(line string) {
|
||||||
|
|
||||||
cmd := parseLine(line)
|
cmd := parseLine(line)
|
||||||
|
|
||||||
|
// Commands are dispatched to the appropriate handler functions.
|
||||||
|
// If a network error occurs during handling, the handler should
|
||||||
|
// just return and let the error be handled on the next read.
|
||||||
|
|
||||||
switch cmd.action {
|
switch cmd.action {
|
||||||
|
|
||||||
case "HELO":
|
case "HELO":
|
||||||
|
@ -95,7 +99,7 @@ func (session *session) handleHELO(cmd command) {
|
||||||
|
|
||||||
if session.peer.HeloName != "" {
|
if session.peer.HeloName != "" {
|
||||||
// Reset envelope in case of duplicate HELO
|
// Reset envelope in case of duplicate HELO
|
||||||
session.envelope = nil
|
session.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
if session.server.HeloChecker != nil {
|
if session.server.HeloChecker != nil {
|
||||||
|
@ -122,7 +126,7 @@ func (session *session) handleEHLO(cmd command) {
|
||||||
|
|
||||||
if session.peer.HeloName != "" {
|
if session.peer.HeloName != "" {
|
||||||
// Reset envelope in case of duplicate EHLO
|
// Reset envelope in case of duplicate EHLO
|
||||||
session.envelope = nil
|
session.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
if session.server.HeloChecker != nil {
|
if session.server.HeloChecker != nil {
|
||||||
|
@ -197,7 +201,7 @@ func (session *session) handleRCPT(cmd command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(session.envelope.Recipients) >= session.server.MaxRecipients {
|
if len(session.envelope.Recipients) >= session.server.MaxRecipients {
|
||||||
session.reply(550, "Too many recipients")
|
session.reply(452, "Too many recipients")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +247,7 @@ func (session *session) handleSTARTTLS(cmd command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset envelope as a new EHLO/HELO is required after STARTTLS
|
// Reset envelope as a new EHLO/HELO is required after STARTTLS
|
||||||
session.envelope = nil
|
session.reset()
|
||||||
|
|
||||||
// Reset deadlines on the underlying connection before I replace it
|
// Reset deadlines on the underlying connection before I replace it
|
||||||
// with a TLS connection
|
// with a TLS connection
|
||||||
|
@ -291,7 +295,7 @@ func (session *session) handleDATA(cmd command) {
|
||||||
session.reply(250, "Thank you.")
|
session.reply(250, "Thank you.")
|
||||||
}
|
}
|
||||||
|
|
||||||
session.envelope = nil
|
session.reset()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,14 +317,14 @@ func (session *session) handleDATA(cmd command) {
|
||||||
session.server.MaxMessageSize,
|
session.server.MaxMessageSize,
|
||||||
))
|
))
|
||||||
|
|
||||||
session.envelope = nil
|
session.reset()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *session) handleRSET(cmd command) {
|
func (session *session) handleRSET(cmd command) {
|
||||||
session.envelope = nil
|
session.reset()
|
||||||
session.reply(250, "Go ahead")
|
session.reply(250, "Go ahead")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
27
smtpd.go
27
smtpd.go
|
@ -214,10 +214,33 @@ func (session *session) serve() {
|
||||||
|
|
||||||
session.welcome()
|
session.welcome()
|
||||||
|
|
||||||
|
for {
|
||||||
|
|
||||||
for session.scanner.Scan() {
|
for session.scanner.Scan() {
|
||||||
session.handle(session.scanner.Text())
|
session.handle(session.scanner.Text())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := session.scanner.Err()
|
||||||
|
|
||||||
|
if err == bufio.ErrTooLong {
|
||||||
|
|
||||||
|
session.reply(500, "Line too long")
|
||||||
|
|
||||||
|
// Advance reader to the next newline
|
||||||
|
|
||||||
|
session.reader.ReadString('\n')
|
||||||
|
session.scanner = bufio.NewScanner(session.reader)
|
||||||
|
|
||||||
|
// Reset and have the client start over.
|
||||||
|
|
||||||
|
session.reset()
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *session) reject() {
|
func (session *session) reject() {
|
||||||
|
@ -225,6 +248,10 @@ func (session *session) reject() {
|
||||||
session.close()
|
session.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *session) reset() {
|
||||||
|
session.envelope = nil
|
||||||
|
}
|
||||||
|
|
||||||
func (session *session) welcome() {
|
func (session *session) welcome() {
|
||||||
|
|
||||||
if session.server.ConnectionChecker != nil {
|
if session.server.ConnectionChecker != nil {
|
||||||
|
|
|
@ -1028,3 +1028,33 @@ func TestTLSTimeout(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLongLine(t *testing.T) {
|
||||||
|
|
||||||
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Listen failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
server := &smtpd.Server{}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
server.Serve(ln)
|
||||||
|
}()
|
||||||
|
|
||||||
|
c, err := smtp.Dial(ln.Addr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Dial failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.Mail(fmt.Sprintf("%s@example.org", strings.Repeat("x", 65*1024))); err == nil {
|
||||||
|
t.Fatalf("MAIL failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.Quit(); err != nil {
|
||||||
|
t.Fatalf("Quit failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue