Skip to content

Commit e20b162

Browse files
Danielius1922Sean-Der
authored andcommitted
Fix multiple calls to Handshake
Handshake are synchronized by a mutex, but there is a panicing scenario when the first handshake fails.
1 parent f3e8a9e commit e20b162

3 files changed

Lines changed: 61 additions & 9 deletions

File tree

conn.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,9 +1055,11 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh
10551055
}()
10561056
go func() {
10571057
defer func() {
1058-
// Escaping read loop.
1059-
// It's safe to close decrypted channnel now.
1060-
close(c.decrypted)
1058+
if c.isHandshakeCompletedSuccessfully() {
1059+
// Escaping read loop.
1060+
// It's safe to close decrypted channnel now.
1061+
close(c.decrypted)
1062+
}
10611063

10621064
// Force stop handshaker when the underlying connection is closed.
10631065
cancel()

conn_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3614,3 +3614,51 @@ func TestConnectionState(t *testing.T) {
36143614
t.Fatal("ConnectionState should not be nil")
36153615
}
36163616
}
3617+
3618+
func TestMultiHandshake(t *testing.T) {
3619+
defer test.CheckRoutines(t)()
3620+
defer test.TimeOut(time.Second * 10).Stop()
3621+
3622+
ca, cb := dpipe.Pipe()
3623+
serverCert, err := selfsign.GenerateSelfSigned()
3624+
if err != nil {
3625+
t.Fatal(err)
3626+
}
3627+
server, err := Server(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{
3628+
Certificates: []tls.Certificate{serverCert},
3629+
})
3630+
if err != nil {
3631+
t.Fatal(err)
3632+
}
3633+
3634+
go func() {
3635+
_ = server.Handshake()
3636+
}()
3637+
3638+
clientCert, err := selfsign.GenerateSelfSigned()
3639+
if err != nil {
3640+
t.Fatal(err)
3641+
}
3642+
client, err := Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{
3643+
Certificates: []tls.Certificate{clientCert},
3644+
})
3645+
if err != nil {
3646+
t.Fatal(err)
3647+
}
3648+
3649+
if err = client.Handshake(); err == nil {
3650+
t.Fatal(err)
3651+
}
3652+
3653+
if err = client.Handshake(); err == nil {
3654+
t.Fatal(err)
3655+
}
3656+
3657+
if err = server.Close(); err != nil {
3658+
t.Fatal(err)
3659+
}
3660+
3661+
if err = client.Close(); err != nil {
3662+
t.Fatal(err)
3663+
}
3664+
}

examples/listen/verify-brute-force-protection/main.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ func main() {
2727
//
2828

2929
// ************ Variables used to implement a basic Brute Force Attack protection *************
30-
var attempts = make(map[string]int) // Map of attempts for each IP address.
31-
var attemptsMutex sync.Mutex // Mutex for the map of attempts.
32-
var attemptsCleaner = time.Now() // Time to be able to clean the map of attempts every X minutes.
30+
var (
31+
attempts = make(map[string]int) // Map of attempts for each IP address.
32+
attemptsMutex sync.Mutex // Mutex for the map of attempts.
33+
attemptsCleaner = time.Now() // Time to be able to clean the map of attempts every X minutes.
34+
)
3335

3436
certificate, err := util.LoadKeyAndCertificate("examples/certificates/server.pem",
3537
"examples/certificates/server.pub.pem")
@@ -68,9 +70,9 @@ func main() {
6870
}
6971
}
7072
// Check if the IP address is in the map, and the IP address has exceeded the limit (Brute Force Attack protection)
71-
attemptIP := addr.(*net.UDPAddr).IP.String()
73+
attemptIP := addr.(*net.UDPAddr).IP.String() //nolint
7274
if attempts[attemptIP] > 10 {
73-
return fmt.Errorf("too many attempts from this IP address")
75+
return fmt.Errorf("too many attempts from this IP address") //nolint
7476
}
7577
// Here I increment the number of attempts for this IP address (Brute Force Attack protection)
7678
attempts[attemptIP]++
@@ -105,7 +107,7 @@ func main() {
105107
// *************** Brute Force Attack protection ***************
106108
// Here I decrease the number of attempts for this IP address
107109
attemptsMutex.Lock()
108-
attemptIP := conn.(*dtls.Conn).RemoteAddr().(*net.UDPAddr).IP.String()
110+
attemptIP := conn.(*dtls.Conn).RemoteAddr().(*net.UDPAddr).IP.String() //nolint
109111
attempts[attemptIP]--
110112
// If the number of attempts for this IP address is 0, I delete the IP address from the map
111113
if attempts[attemptIP] == 0 {

0 commit comments

Comments
 (0)