Skip to content

Commit f228c00

Browse files
committed
Fix issue when the connection was remotely closed
1 parent 4df1aea commit f228c00

File tree

3 files changed

+76
-22
lines changed

3 files changed

+76
-22
lines changed

src/modules/smtp/private.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package smtp
2+
3+
import (
4+
"GoMapEnum/src/utils"
5+
6+
smtp "github.com/nodauf/net-smtp"
7+
)
8+
9+
func (options *Options) prepareOneConnection(client *smtp.Client) error {
10+
11+
mailFrom := utils.RandomString(6) + "@" + options.Domain
12+
err := client.Mail(mailFrom)
13+
if err != nil {
14+
//options.Log.Error("Mail From command failed with email: " + mailFrom + " and error " + err.Error())
15+
return err
16+
}
17+
options.Log.Debug("One connection has been successfully prepared")
18+
19+
return nil
20+
}
21+
22+
func (options *Options) createNewConnection() *smtp.Client {
23+
client, err := smtp.Dial(options.Target + ":25")
24+
if err != nil {
25+
options.Log.Error("Failed to establish a connection " + err.Error())
26+
return nil
27+
}
28+
29+
hello := utils.RandomString(6)
30+
err = client.Hello(hello)
31+
if err != nil {
32+
options.Log.Error("helo command failed with helo " + hello + " and error " + err.Error())
33+
return nil
34+
}
35+
return client
36+
}

src/modules/smtp/struct.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ type Options struct {
1313
Mode string
1414
utils.BaseOptions
1515

16-
all bool
17-
connectionsPool chan *smtp.Client
16+
all bool
17+
connectionsPool chan *smtp.Client
18+
expnNotRecognized bool
1819
}
1920

2021
func (options *Options) GetBaseOptions() *utils.BaseOptions {

src/modules/smtp/userEnum.go

+37-20
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package smtp
22

33
import (
4-
"GoMapEnum/src/utils"
5-
"fmt"
64
"net"
75
"reflect"
86
"strconv"
@@ -32,27 +30,27 @@ func PrepareSMTPConnections(optionsInterface *interface{}) {
3230
}
3331
options.Log.Debug("Preparing a pool of " + strconv.Itoa(nbConnectionsRequired) + " connections")
3432
for i := 1; i <= nbConnectionsRequired; i++ {
35-
client, err := smtp.Dial(options.Target + ":25")
36-
if err != nil {
37-
options.Log.Error("Failed to establish a connection " + err.Error())
38-
continue
39-
}
40-
err = client.Hello(utils.RandomString(6))
41-
if err != nil {
42-
fmt.Println("hello" + err.Error())
43-
}
44-
err = client.Mail(utils.RandomString(6) + "@" + options.Domain)
45-
if err != nil {
46-
fmt.Println("mail" + err.Error())
33+
client := options.createNewConnection()
34+
if client != nil {
35+
options.connectionsPool <- client
4736
}
48-
options.connectionsPool <- client
4937
}
5038
}
5139

5240
func UserEnum(optionsInterface *interface{}, username string) bool {
5341
options := (*optionsInterface).(*Options)
5442
valid := false
5543
smtpConnection := <-options.connectionsPool
44+
smtpConnection.Reset()
45+
err := options.prepareOneConnection(smtpConnection)
46+
if err != nil && strings.Contains(err.Error(), "connection reset by peer") {
47+
options.Log.Debug("Connection reset. Generating new one")
48+
smtpConnection = options.createNewConnection()
49+
err = options.prepareOneConnection(smtpConnection)
50+
}
51+
if err != nil {
52+
options.Log.Fatal("Failed to prepare a connection. " + err.Error())
53+
}
5654
switch strings.ToLower(options.Mode) {
5755
case "rcpt":
5856
err := smtpConnection.Rcpt(username)
@@ -61,6 +59,11 @@ func UserEnum(optionsInterface *interface{}, username string) bool {
6159
valid = true
6260
} else {
6361
options.Log.Debug(username + " => " + err.Error())
62+
if strings.Contains(err.Error(), "connection reset by peer") {
63+
smtpConnection.Close()
64+
options.createNewConnection()
65+
return UserEnum(optionsInterface, username)
66+
}
6467
options.Log.Fail(username)
6568
}
6669
case "vrfy":
@@ -70,6 +73,11 @@ func UserEnum(optionsInterface *interface{}, username string) bool {
7073
valid = true
7174
} else {
7275
options.Log.Debug(username + " => " + err.Error())
76+
if strings.Contains(err.Error(), "connection reset by peer") {
77+
smtpConnection.Close()
78+
options.createNewConnection()
79+
return UserEnum(optionsInterface, username)
80+
}
7381
options.Log.Fail(username)
7482
}
7583
case "expn":
@@ -80,12 +88,20 @@ func UserEnum(optionsInterface *interface{}, username string) bool {
8088
} else {
8189
code := strings.Split(err.Error(), " ")[0]
8290
options.Log.Debug(username + " => " + err.Error())
91+
if strings.Contains(err.Error(), "connection reset by peer") {
92+
smtpConnection.Close()
93+
options.createNewConnection()
94+
return UserEnum(optionsInterface, username)
95+
}
8396
options.Log.Fail(username)
8497
// If the command is not implemented no need to pursue
8598
if code == "502" && !options.all {
8699
CloseSMTPConnections(optionsInterface)
87100
options.Log.Fatal("The command EXPN is not implemented. No need to pursue using this method.")
88101
}
102+
if code == "502" && options.all {
103+
options.expnNotRecognized = true
104+
}
89105
}
90106
case "", "all":
91107

@@ -111,15 +127,16 @@ func UserEnum(optionsInterface *interface{}, username string) bool {
111127
return true
112128
}
113129
// EXPN
114-
options.Log.Debug("Enumerate with EXPN")
115-
optionsCopy.Mode = "expn"
116-
newOptionsInterface = reflect.ValueOf(&optionsCopy).Interface()
117-
valid = UserEnum(&newOptionsInterface, username)
130+
if !options.expnNotRecognized {
131+
options.Log.Debug("Enumerate with EXPN")
132+
optionsCopy.Mode = "expn"
133+
newOptionsInterface = reflect.ValueOf(&optionsCopy).Interface()
134+
valid = UserEnum(&newOptionsInterface, username)
135+
}
118136
return valid
119137
default:
120138
options.Log.Fatal("Unrecognised mode: " + options.Mode + ". Only RCPT, VRFY and EXPN are supported.")
121139
}
122-
123140
options.connectionsPool <- smtpConnection
124141
return valid
125142
}

0 commit comments

Comments
 (0)