From 574775e53bd5f72a9d48438c583904328e06e573 Mon Sep 17 00:00:00 2001 From: joerger Date: Thu, 17 Apr 2025 19:20:21 -0700 Subject: [PATCH 1/6] Prevent windows from trying to reuse the addr and getting a bind error. --- lib/hardwarekey/agent.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/hardwarekey/agent.go b/lib/hardwarekey/agent.go index 090ba9b9143ee..9d2ebf06b5b97 100644 --- a/lib/hardwarekey/agent.go +++ b/lib/hardwarekey/agent.go @@ -101,8 +101,19 @@ func NewAgentServer(ctx context.Context, s hardwarekey.Service, keyAgentDir stri } func newAgentListener(ctx context.Context, keyAgentDir string) (net.Listener, error) { + lc := net.ListenConfig{ + Control: func(network, addr string, conn syscall.RawConn) error { + var err error + err2 := conn.Control(func(descriptor uintptr) { + // Disable address reuse to prevent socket replacement. + err = syscall.SetsockoptInt(int(descriptor), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 0) + }) + return trace.NewAggregate(err2, err) + }, + } + socketPath := filepath.Join(keyAgentDir, sockName) - l, err := net.Listen("unix", socketPath) + l, err := lc.Listen(ctx, "unix", socketPath) if err == nil { return l, nil } else if !errors.Is(err, syscall.EADDRINUSE) { From b4529e35ff0d67c482a3440e7d1fb1ca4c8f401e Mon Sep 17 00:00:00 2001 From: joerger Date: Thu, 17 Apr 2025 19:39:06 -0700 Subject: [PATCH 2/6] Replace unresponsive windows unix sockets. --- lib/hardwarekey/agent.go | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/lib/hardwarekey/agent.go b/lib/hardwarekey/agent.go index 9d2ebf06b5b97..84ca44419a708 100644 --- a/lib/hardwarekey/agent.go +++ b/lib/hardwarekey/agent.go @@ -101,23 +101,16 @@ func NewAgentServer(ctx context.Context, s hardwarekey.Service, keyAgentDir stri } func newAgentListener(ctx context.Context, keyAgentDir string) (net.Listener, error) { - lc := net.ListenConfig{ - Control: func(network, addr string, conn syscall.RawConn) error { - var err error - err2 := conn.Control(func(descriptor uintptr) { - // Disable address reuse to prevent socket replacement. - err = syscall.SetsockoptInt(int(descriptor), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 0) - }) - return trace.NewAggregate(err2, err) - }, - } - socketPath := filepath.Join(keyAgentDir, sockName) - l, err := lc.Listen(ctx, "unix", socketPath) + l, err := net.Listen("unix", socketPath) if err == nil { return l, nil } else if !errors.Is(err, syscall.EADDRINUSE) { - return nil, trace.Wrap(err) + // Double check if the socket file already exists, since Windows + // does not return the expected error. + if _, err := os.Stat(socketPath); err != nil { + return nil, trace.Wrap(err) + } } // A hardware key agent already exists in the given path. Before replacing it, From 756ba3721201400c37e1f798ddc52d7105f11545 Mon Sep 17 00:00:00 2001 From: joerger Date: Fri, 18 Apr 2025 10:24:35 -0700 Subject: [PATCH 3/6] Explicitly check for error message instead of os.Stat. --- lib/hardwarekey/agent.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/hardwarekey/agent.go b/lib/hardwarekey/agent.go index 84ca44419a708..24dff46f29b00 100644 --- a/lib/hardwarekey/agent.go +++ b/lib/hardwarekey/agent.go @@ -25,6 +25,7 @@ import ( "net" "os" "path/filepath" + "strings" "syscall" "github.com/gravitational/trace" @@ -100,17 +101,17 @@ func NewAgentServer(ctx context.Context, s hardwarekey.Service, keyAgentDir stri }, nil } +// On windows, listening on an already existing unix socket results in a different, +// Windows specific [syscall.Bind] error not defined in the [syscall] library. +const windowsBindErrMessage = "bind: Only one usage of each socket address (protocol/network address/port) is normally permitted" + func newAgentListener(ctx context.Context, keyAgentDir string) (net.Listener, error) { socketPath := filepath.Join(keyAgentDir, sockName) l, err := net.Listen("unix", socketPath) if err == nil { return l, nil - } else if !errors.Is(err, syscall.EADDRINUSE) { - // Double check if the socket file already exists, since Windows - // does not return the expected error. - if _, err := os.Stat(socketPath); err != nil { - return nil, trace.Wrap(err) - } + } else if !errors.Is(err, syscall.EADDRINUSE) && !strings.Contains(err.Error(), windowsBindErrMessage) { + return nil, trace.Wrap(err) } // A hardware key agent already exists in the given path. Before replacing it, From 06c814f0f7e296e8885039acc9748847b5f36147 Mon Sep 17 00:00:00 2001 From: joerger Date: Mon, 21 Apr 2025 14:08:49 -0700 Subject: [PATCH 4/6] Move windowsBindErrMessage. --- lib/hardwarekey/agent.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/hardwarekey/agent.go b/lib/hardwarekey/agent.go index 24dff46f29b00..99d1b2157213f 100644 --- a/lib/hardwarekey/agent.go +++ b/lib/hardwarekey/agent.go @@ -101,11 +101,11 @@ func NewAgentServer(ctx context.Context, s hardwarekey.Service, keyAgentDir stri }, nil } -// On windows, listening on an already existing unix socket results in a different, -// Windows specific [syscall.Bind] error not defined in the [syscall] library. -const windowsBindErrMessage = "bind: Only one usage of each socket address (protocol/network address/port) is normally permitted" - func newAgentListener(ctx context.Context, keyAgentDir string) (net.Listener, error) { + // On windows, listening on an already existing unix socket results in a different, + // Windows specific [syscall.Bind] error not defined in the [syscall] library. + const windowsBindErrMessage = "bind: Only one usage of each socket address (protocol/network address/port) is normally permitted" + socketPath := filepath.Join(keyAgentDir, sockName) l, err := net.Listen("unix", socketPath) if err == nil { From e7cddc3ddfe6daa2efb5cf374ab88b7d8b20f078 Mon Sep 17 00:00:00 2001 From: joerger Date: Tue, 22 Apr 2025 10:03:07 -0700 Subject: [PATCH 5/6] Add cross-platform ErrAddrInUse constant. --- api/utils/net/errors_common.go | 24 ++++++++++++++++++++++++ api/utils/net/errors_windows.go | 24 ++++++++++++++++++++++++ go.mod | 2 +- go.sum | 2 ++ lib/hardwarekey/agent.go | 9 ++------- 5 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 api/utils/net/errors_common.go create mode 100644 api/utils/net/errors_windows.go diff --git a/api/utils/net/errors_common.go b/api/utils/net/errors_common.go new file mode 100644 index 0000000000000..c4bd3af94464f --- /dev/null +++ b/api/utils/net/errors_common.go @@ -0,0 +1,24 @@ +//go:build !windows + +// Copyright 2025 Gravitational, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net + +import "syscall" + +const ( + // ErrAddrInUse is [syscall.EADDRINUSE] + ErrAddrInUse = syscall.EADDRINUSE +) diff --git a/api/utils/net/errors_windows.go b/api/utils/net/errors_windows.go new file mode 100644 index 0000000000000..0fdb2561baa90 --- /dev/null +++ b/api/utils/net/errors_windows.go @@ -0,0 +1,24 @@ +//go:build windows + +// Copyright 2025 Gravitational, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net + +import "golang.org/x/sys/windows" + +const ( + // ErrAddrInUse is [windows.WSAEADDRINUSE] + ErrAddrInUse = windows.WSAEADDRINUSE +) diff --git a/go.mod b/go.mod index 36b1a997e702e..2263afd5a3abc 100644 --- a/go.mod +++ b/go.mod @@ -219,7 +219,7 @@ require ( golang.org/x/net v0.38.0 golang.org/x/oauth2 v0.28.0 golang.org/x/sync v0.12.0 - golang.org/x/sys v0.31.0 + golang.org/x/sys v0.32.0 golang.org/x/term v0.30.0 golang.org/x/text v0.23.0 golang.org/x/time v0.11.0 diff --git a/go.sum b/go.sum index 9acd84eb6ec78..6e258c2ea0766 100644 --- a/go.sum +++ b/go.sum @@ -2719,6 +2719,8 @@ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/lib/hardwarekey/agent.go b/lib/hardwarekey/agent.go index 99d1b2157213f..6bd7d70a43103 100644 --- a/lib/hardwarekey/agent.go +++ b/lib/hardwarekey/agent.go @@ -25,8 +25,6 @@ import ( "net" "os" "path/filepath" - "strings" - "syscall" "github.com/gravitational/trace" "google.golang.org/grpc" @@ -36,6 +34,7 @@ import ( "github.com/gravitational/teleport/api/utils/keys" "github.com/gravitational/teleport/api/utils/keys/hardwarekey" "github.com/gravitational/teleport/api/utils/keys/hardwarekeyagent" + netutil "github.com/gravitational/teleport/api/utils/net" "github.com/gravitational/teleport/lib/utils/cert" ) @@ -102,15 +101,11 @@ func NewAgentServer(ctx context.Context, s hardwarekey.Service, keyAgentDir stri } func newAgentListener(ctx context.Context, keyAgentDir string) (net.Listener, error) { - // On windows, listening on an already existing unix socket results in a different, - // Windows specific [syscall.Bind] error not defined in the [syscall] library. - const windowsBindErrMessage = "bind: Only one usage of each socket address (protocol/network address/port) is normally permitted" - socketPath := filepath.Join(keyAgentDir, sockName) l, err := net.Listen("unix", socketPath) if err == nil { return l, nil - } else if !errors.Is(err, syscall.EADDRINUSE) && !strings.Contains(err.Error(), windowsBindErrMessage) { + } else if !errors.Is(err, netutil.ErrAddrInUse) { return nil, trace.Wrap(err) } From ef61991486ab0cf6ff9813497d61887bd37d2f98 Mon Sep 17 00:00:00 2001 From: joerger Date: Tue, 22 Apr 2025 11:42:29 -0700 Subject: [PATCH 6/6] Move error constants to hardwarekey package. --- go.mod | 2 +- go.sum | 2 -- lib/hardwarekey/agent.go | 3 +-- {api/utils/net => lib/hardwarekey}/errors_common.go | 6 +++--- {api/utils/net => lib/hardwarekey}/errors_windows.go | 6 +++--- 5 files changed, 8 insertions(+), 11 deletions(-) rename {api/utils/net => lib/hardwarekey}/errors_common.go (87%) rename {api/utils/net => lib/hardwarekey}/errors_windows.go (86%) diff --git a/go.mod b/go.mod index 2263afd5a3abc..36b1a997e702e 100644 --- a/go.mod +++ b/go.mod @@ -219,7 +219,7 @@ require ( golang.org/x/net v0.38.0 golang.org/x/oauth2 v0.28.0 golang.org/x/sync v0.12.0 - golang.org/x/sys v0.32.0 + golang.org/x/sys v0.31.0 golang.org/x/term v0.30.0 golang.org/x/text v0.23.0 golang.org/x/time v0.11.0 diff --git a/go.sum b/go.sum index 6e258c2ea0766..9acd84eb6ec78 100644 --- a/go.sum +++ b/go.sum @@ -2719,8 +2719,6 @@ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/lib/hardwarekey/agent.go b/lib/hardwarekey/agent.go index 6bd7d70a43103..e86cc4099c743 100644 --- a/lib/hardwarekey/agent.go +++ b/lib/hardwarekey/agent.go @@ -34,7 +34,6 @@ import ( "github.com/gravitational/teleport/api/utils/keys" "github.com/gravitational/teleport/api/utils/keys/hardwarekey" "github.com/gravitational/teleport/api/utils/keys/hardwarekeyagent" - netutil "github.com/gravitational/teleport/api/utils/net" "github.com/gravitational/teleport/lib/utils/cert" ) @@ -105,7 +104,7 @@ func newAgentListener(ctx context.Context, keyAgentDir string) (net.Listener, er l, err := net.Listen("unix", socketPath) if err == nil { return l, nil - } else if !errors.Is(err, netutil.ErrAddrInUse) { + } else if !errors.Is(err, errAddrInUse) { return nil, trace.Wrap(err) } diff --git a/api/utils/net/errors_common.go b/lib/hardwarekey/errors_common.go similarity index 87% rename from api/utils/net/errors_common.go rename to lib/hardwarekey/errors_common.go index c4bd3af94464f..3fd5ba4757646 100644 --- a/api/utils/net/errors_common.go +++ b/lib/hardwarekey/errors_common.go @@ -14,11 +14,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -package net +package hardwarekey import "syscall" const ( - // ErrAddrInUse is [syscall.EADDRINUSE] - ErrAddrInUse = syscall.EADDRINUSE + // errAddrInUse is [syscall.EADDRINUSE] + errAddrInUse = syscall.EADDRINUSE ) diff --git a/api/utils/net/errors_windows.go b/lib/hardwarekey/errors_windows.go similarity index 86% rename from api/utils/net/errors_windows.go rename to lib/hardwarekey/errors_windows.go index 0fdb2561baa90..f964daee5a00a 100644 --- a/api/utils/net/errors_windows.go +++ b/lib/hardwarekey/errors_windows.go @@ -14,11 +14,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -package net +package hardwarekey import "golang.org/x/sys/windows" const ( - // ErrAddrInUse is [windows.WSAEADDRINUSE] - ErrAddrInUse = windows.WSAEADDRINUSE + // errAddrInUse is [windows.WSAEADDRINUSE] + errAddrInUse = windows.WSAEADDRINUSE )