Skip to content

NegotiateStream fails when authenticating from linux client to windows server #100231

Open
@wimme

Description

@wimme

Description

We're using NegotiateStream to authenticate clients on our server application. This works on Windows clients, but we would like to get it working on Linux clients as well.

Reproduction Steps

The server application always runs on a Windows Server OS and uses .NET Framework 4.6.2.
In this case, the Windows Server is part of a local domain (I didn't test it on a server that is not in a domain).

The client application makes use of a library dll that gets build in both .NET Framework 4.6.2 and .NET Standard 2.0.

Clients using the .NET Framework 4.6.2 library dll on Windows works.
Clients using the .NET Standard 2.0 library on .NET 8 applications on Windows works.
Clients using the .NET Standard 2.0 library on .NET 8 applications on Linux does not work.

Linux clients are running:

  • Ubuntu Server 22.04 LTS
  • dotnet-runtime-8.0
  • aspnetcore-runtime-8.0

Server implementation:

_authStream = new SSPIAuthStream();
_negotiateStream = new NegotiateStream(_authStream);

NegotiateStream stream = _negotiateStream;
stream.AuthenticateAsServer(
    (NetworkCredential)CredentialCache.DefaultCredentials,
    ProtectionLevel.None,                               // min. protectionlevel required
    TokenImpersonationLevel.Identification              // min. impersonationlevel required
);

if (stream.RemoteIdentity != null)
    name = stream.RemoteIdentity.Name;

authenticated = stream.IsAuthenticated;

Client implementation:

_authStream = new SSPIAuthStream();
_negotiateStream = new NegotiateStream(_authStream);

// determine client credentials
NetworkCredential credentials = null;
if (String.IsNullOrEmpty(userName))
    credentials = (NetworkCredential)CredentialCache.DefaultCredentials;
else
    credentials = new NetworkCredential(userName, password, domainName);

// launch client authentication process asynchronously.
_arAuthenticateAsClient = _negotiateStream.BeginAuthenticateAsClient(
    credentials,
    String.Empty,                                       // target name
    ProtectionLevel.None,                               // we don't need sign or encrypt since we'll ditch the stream once authenticated
    TokenImpersonationLevel.Identification,             // we only need to identify ourselves
    new AsyncCallback(callback_onAuthenticateComplete), // callback method when done
    null
    );

Expected behavior

I would expect when specifying a username/password that the authentication step works on Linux as well, just like on Windows.

Actual behavior

When a client running on Linux connects, the following error gets thrown on the server:

System.Security.Authentication.AuthenticationException: Authentication failed on the remote side (the stream might still be available for additional authentication attempts). ---> System.ComponentModel.Win32Exception: Unknown error (0xffffffff)
   --- End of inner exception stack trace ---
   at System.Net.Security.NegoState.ProcessReceivedBlob(Byte[] message, LazyAsyncResult lazyResult)
   at System.Net.Security.NegoState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.NegotiateStream.AuthenticateAsServer(NetworkCredential credential, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel)

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions