Skip to content

Commit

Permalink
Fix multiple calls to Handshake
Browse files Browse the repository at this point in the history
Handshake are synchronized by a mutex, but there is a panicing
scenario when the first handshake fails.
  • Loading branch information
Danielius1922 authored and Sean-Der committed Aug 6, 2024
1 parent f3e8a9e commit e20b162
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 9 deletions.
8 changes: 5 additions & 3 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -1055,9 +1055,11 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh
}()
go func() {
defer func() {
// Escaping read loop.
// It's safe to close decrypted channnel now.
close(c.decrypted)
if c.isHandshakeCompletedSuccessfully() {
// Escaping read loop.
// It's safe to close decrypted channnel now.
close(c.decrypted)
}

// Force stop handshaker when the underlying connection is closed.
cancel()
Expand Down
48 changes: 48 additions & 0 deletions conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3614,3 +3614,51 @@ func TestConnectionState(t *testing.T) {
t.Fatal("ConnectionState should not be nil")
}
}

func TestMultiHandshake(t *testing.T) {
defer test.CheckRoutines(t)()
defer test.TimeOut(time.Second * 10).Stop()

ca, cb := dpipe.Pipe()
serverCert, err := selfsign.GenerateSelfSigned()
if err != nil {
t.Fatal(err)
}
server, err := Server(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{
Certificates: []tls.Certificate{serverCert},
})
if err != nil {
t.Fatal(err)
}

go func() {
_ = server.Handshake()
}()

clientCert, err := selfsign.GenerateSelfSigned()
if err != nil {
t.Fatal(err)
}
client, err := Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{
Certificates: []tls.Certificate{clientCert},
})
if err != nil {
t.Fatal(err)
}

if err = client.Handshake(); err == nil {
t.Fatal(err)
}

if err = client.Handshake(); err == nil {
t.Fatal(err)
}

if err = server.Close(); err != nil {
t.Fatal(err)
}

if err = client.Close(); err != nil {
t.Fatal(err)
}
}
14 changes: 8 additions & 6 deletions examples/listen/verify-brute-force-protection/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ func main() {
//

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

certificate, err := util.LoadKeyAndCertificate("examples/certificates/server.pem",
"examples/certificates/server.pub.pem")
Expand Down Expand Up @@ -68,9 +70,9 @@ func main() {
}
}
// Check if the IP address is in the map, and the IP address has exceeded the limit (Brute Force Attack protection)
attemptIP := addr.(*net.UDPAddr).IP.String()
attemptIP := addr.(*net.UDPAddr).IP.String() //nolint
if attempts[attemptIP] > 10 {
return fmt.Errorf("too many attempts from this IP address")
return fmt.Errorf("too many attempts from this IP address") //nolint
}
// Here I increment the number of attempts for this IP address (Brute Force Attack protection)
attempts[attemptIP]++
Expand Down Expand Up @@ -105,7 +107,7 @@ func main() {
// *************** Brute Force Attack protection ***************
// Here I decrease the number of attempts for this IP address
attemptsMutex.Lock()
attemptIP := conn.(*dtls.Conn).RemoteAddr().(*net.UDPAddr).IP.String()
attemptIP := conn.(*dtls.Conn).RemoteAddr().(*net.UDPAddr).IP.String() //nolint
attempts[attemptIP]--
// If the number of attempts for this IP address is 0, I delete the IP address from the map
if attempts[attemptIP] == 0 {
Expand Down

0 comments on commit e20b162

Please sign in to comment.