diff --git a/lib/auth/webauthnwin/webauthn_windows.go b/lib/auth/webauthnwin/webauthn_windows.go index 5a3eb4f3d0e58..59f423b76a5ef 100644 --- a/lib/auth/webauthnwin/webauthn_windows.go +++ b/lib/auth/webauthnwin/webauthn_windows.go @@ -48,27 +48,36 @@ type nativeImpl struct { // could change during program invocation. // Client will be always created, even if dll is missing on system. func newNativeImpl() *nativeImpl { - v, err := checkIfDLLExistsAndGetAPIVersionNumber() + n := &nativeImpl{ + hasCompileSupport: true, + } + + // Explicitly loading the module avoids a panic when calling DLL functions if + // the DLL is missing. + // https://github.com/gravitational/teleport/issues/36851 + if err := modWebAuthn.Load(); err != nil { + log. + WithError(err). + Debug("WebAuthnWin: failed to load WebAuthn.dll (it's likely missing)") + return n + } + + v, err := webAuthNGetApiVersionNumber() if err != nil { log.WithError(err).Debug("WebAuthnWin: failed to check version") - return &nativeImpl{ - hasCompileSupport: true, - isAvailable: false, - } + return n } - uvPlatform, err := isUVPlatformAuthenticatorAvailable() + n.webauthnAPIVersion = v + n.isAvailable = v > 0 + + n.hasPlatformUV, err = isUVPlatformAuthenticatorAvailable() if err != nil { // This should not happen if dll exists, however we are fine with // to proceed without uvPlatform. log.WithError(err).Debug("WebAuthnWin: failed to check isUVPlatformAuthenticatorAvailable") } - return &nativeImpl{ - webauthnAPIVersion: v, - hasCompileSupport: true, - hasPlatformUV: uvPlatform, - isAvailable: v > 0, - } + return n } func (n *nativeImpl) CheckSupport() CheckSupportResult { @@ -176,13 +185,6 @@ func (n *nativeImpl) MakeCredential(origin string, in *makeCredentialRequest) (* }, nil } -// checkIfDLLExistsAndGetAPIVersionNumber checks if dll exists and tries to load -// it's version via API call. This function makes sure to not panic if dll is -// missing. -func checkIfDLLExistsAndGetAPIVersionNumber() (int, error) { - return webAuthNGetApiVersionNumber() -} - func getErrorNameOrLastErr(in uintptr, lastError error) error { ret := webAuthNGetErrorName(in) if ret == 0 {