-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
openrelay.go
131 lines (113 loc) · 2.9 KB
/
openrelay.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package main
import (
"bufio"
"crypto/tls"
"fmt"
"log"
"net"
"net/smtp"
"strings"
"time"
)
type openResult struct {
orboolresult bool
orresult string
rcptresult string
rcptboolresult bool
senderresult string
senderboolresult bool
serverstring string
starttlsbool bool
starttlsvalid bool
starttlsversion string
tlsbool bool
tlsvalid bool
tlsversion string
vrfybool bool
}
// openRelay checks if a mail server sends email without
// authentication and with a fake sender address.
// It returns a struct:
func openRelay(mailFrom string, mailTo string, targetHost string, targetPort string) (openResult, error) {
//var orresult string
var or openResult
c, err := smtp.Dial(targetHost + ":" + targetPort)
if err != nil {
return or, err
}
// Print server string. You can trust the server string, but you shouldn't...
conn, err := net.DialTimeout("tcp", targetHost+":"+targetPort, 15*time.Second)
defer conn.Close()
if err != nil {
or.serverstring = "Could not read banner: " + err.Error()
} else {
buf := bufio.NewReader(conn)
bannerbytes, err := buf.ReadBytes('\n')
if err != nil {
log.Fatalf("ee Fatal error: %s", err.Error())
}
or.serverstring = string(bannerbytes)
}
// set default TLS config
tlsconfig := &tls.Config{ServerName: targetHost}
// the overall STARTTLS check
err = c.StartTLS(tlsconfig)
if err == nil {
or.starttlsbool = true
or.starttlsvalid = true
} else {
// update config to ignore invalid TLS certificates and proceed
tlsconfig = &tls.Config{InsecureSkipVerify: true}
err = c.StartTLS(tlsconfig)
// As there are no error types returned by the TLS client we need this ugly or. Should be fixed with a switch
if err == nil || strings.HasSuffix(err.Error(), "certificate name does not match input") {
or.starttlsbool = true
or.starttlsvalid = false
}
}
// Get more info about the StartTLS connection
if or.starttlsbool {
tlsstate, _ := c.TLSConnectionState()
or.starttlsversion = tlsversions[tlsstate.Version]
}
// Check if server supports VRFY command. The
vrfyerr := c.Verify(mailFrom)
if vrfyerr == nil {
or.vrfybool = true
}
// Set from value
err = c.Mail(mailFrom)
if err != nil {
or.senderresult = err.Error()
} else {
or.senderboolresult = true
}
// Set recipient value
err = c.Rcpt(mailTo)
if err != nil {
or.rcptresult = err.Error()
} else {
or.rcptboolresult = true
}
if !or.rcptboolresult {
return or, nil
}
// Create WriteCloser
wc, err := c.Data()
if err != nil {
return or, err
}
defer wc.Close()
// Write test message, close and quit
// If we can write the message to wc we
// set the orboolresult to true
_, err = fmt.Fprintf(wc, "From: <"+mailFrom+">\n\n"+"This server is an open relay")
orerr := wc.Close()
if orerr != nil {
or.orresult = orerr.Error()
} else {
or.orboolresult = true
}
err = c.Quit()
return or, err
}