@@ -17,6 +17,9 @@ import (
17
17
"time"
18
18
)
19
19
20
+ // Number of errors we'll tolerate per connection before closing. Defaults to 3.
21
+ const errThreshold = 3
22
+
20
23
type ConnectionState struct {
21
24
Hostname string
22
25
LocalAddr net.Addr
@@ -25,11 +28,14 @@ type ConnectionState struct {
25
28
}
26
29
27
30
type Conn struct {
28
- conn net.Conn
29
- text * textproto.Conn
30
- server * Server
31
- helo string
32
- nbrErrors int
31
+ conn net.Conn
32
+ text * textproto.Conn
33
+ server * Server
34
+ helo string
35
+
36
+ // Number of errors witnessed on this connection
37
+ errCount int
38
+
33
39
session Session
34
40
locker sync.Mutex
35
41
binarymime bool
@@ -82,16 +88,6 @@ func (c *Conn) init() {
82
88
c .text = textproto .NewConn (rwc )
83
89
}
84
90
85
- func (c * Conn ) unrecognizedCommand (cmd string ) {
86
- c .WriteResponse (500 , EnhancedCode {5 , 5 , 2 }, fmt .Sprintf ("Syntax error, %v command unrecognized" , cmd ))
87
-
88
- c .nbrErrors ++
89
- if c .nbrErrors > 3 {
90
- c .WriteResponse (500 , EnhancedCode {5 , 5 , 2 }, "Too many unrecognized commands" )
91
- c .Close ()
92
- }
93
- }
94
-
95
91
// Commands are dispatched to the appropriate handler functions.
96
92
func (c * Conn ) handle (cmd string , arg string ) {
97
93
// If panic happens during command handling - send 421 response
@@ -107,7 +103,7 @@ func (c *Conn) handle(cmd string, arg string) {
107
103
}()
108
104
109
105
if cmd == "" {
110
- c .WriteResponse (500 , EnhancedCode {5 , 5 , 2 }, "Speak up" )
106
+ c .protocolError (500 , EnhancedCode {5 , 5 , 2 }, "Speak up" )
111
107
return
112
108
}
113
109
@@ -148,14 +144,15 @@ func (c *Conn) handle(cmd string, arg string) {
148
144
c .Close ()
149
145
case "AUTH" :
150
146
if c .server .AuthDisabled {
151
- c .unrecognizedCommand ( cmd )
147
+ c .protocolError ( 500 , EnhancedCode { 5 , 5 , 2 }, "Syntax error, AUTH command unrecognized" )
152
148
} else {
153
149
c .handleAuth (arg )
154
150
}
155
151
case "STARTTLS" :
156
152
c .handleStartTLS ()
157
153
default :
158
- c .unrecognizedCommand (cmd )
154
+ msg := fmt .Sprintf ("Syntax errors, %v command unrecognized" , cmd )
155
+ c .protocolError (500 , EnhancedCode {5 , 5 , 2 }, msg )
159
156
}
160
157
}
161
158
@@ -222,6 +219,18 @@ func (c *Conn) authAllowed() bool {
222
219
return ! c .server .AuthDisabled && (isTLS || c .server .AllowInsecureAuth )
223
220
}
224
221
222
+ // protocolError writes errors responses and closes the connection once too many
223
+ // have occurred.
224
+ func (c * Conn ) protocolError (code int , ec EnhancedCode , msg string ) {
225
+ c .WriteResponse (code , ec , msg )
226
+
227
+ c .errCount ++
228
+ if c .errCount > errThreshold {
229
+ c .WriteResponse (500 , EnhancedCode {5 , 5 , 1 }, "Too many errors. Quiting now" )
230
+ c .Close ()
231
+ }
232
+ }
233
+
225
234
// GREET state -> waiting for HELO
226
235
func (c * Conn ) handleGreet (enhanced bool , arg string ) {
227
236
if ! enhanced {
0 commit comments