-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
transaction_startTLS.go
56 lines (52 loc) · 1.48 KB
/
transaction_startTLS.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
package msmtpd
import (
"bufio"
"crypto/tls"
"time"
"go.opentelemetry.io/otel/attribute"
)
func (t *Transaction) handleSTARTTLS(cmd command) {
var err error
if t.Encrypted {
t.LogDebug("Connection is already encrypted!")
t.reply(502, "Already running in TLS")
return
}
if t.server.TLSConfig == nil {
t.reply(502, "TLS not supported")
return
}
t.LogDebug("STARTTLS [%s] is received...", cmd.line)
tlsConn := tls.Server(t.conn, t.server.TLSConfig)
t.reply(220, "Connection is encrypted, we can talk freely now!")
err = tlsConn.Handshake()
if err != nil {
t.LogError(err, "couldn't perform handshake")
t.reply(550, "TLS Handshake error")
return
}
t.LogInfo("Connection is encrypted via StartTLS!")
t.Span.SetAttributes(attribute.Bool("encrypted", true))
// Reset envelope as a new EHLO/HELO is required after STARTTLS
t.reset()
// Reset deadlines on the underlying connection before I replace it
// with a TLS connection
err = t.conn.SetDeadline(time.Time{})
if err != nil {
t.LogError(err, "error setting deadline for encrypted connection")
t.reply(550, "TLS Handshake error")
return
}
// Replace connection with a TLS connection
t.conn = tlsConn
t.reader = bufio.NewReader(tlsConn)
t.writer = bufio.NewWriter(tlsConn)
t.scanner = bufio.NewScanner(t.reader)
t.Encrypted = true
// Save connection state on peer
state := tlsConn.ConnectionState()
t.TLS = &state
// Flush the connection to set new timeout deadlines
t.flush()
t.Love(commandExecutedProperly)
}