< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 580
Coverable lines: 580
Total lines: 883
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 228
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Net.Security/src/System/Net/NegotiateAuthenticationPal.Unsupported.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Buffers;
 6using System.Diagnostics;
 7using System.Net.Security;
 8using System.Security.Principal;
 9
 10namespace System.Net
 11{
 12    internal abstract partial class NegotiateAuthenticationPal
 13    {
 14        internal sealed class UnsupportedNegotiateAuthenticationPal : NegotiateAuthenticationPal
 15        {
 16            private string _package;
 17            private string? _targetName;
 18            private NegotiateAuthenticationStatusCode _statusCode;
 19
 020            public override bool IsAuthenticated => false;
 021            public override bool IsSigned => false;
 022            public override bool IsEncrypted => false;
 023            public override bool IsMutuallyAuthenticated => false;
 024            public override string Package => _package;
 025            public override string? TargetName => _targetName;
 026            public override IIdentity RemoteIdentity => throw new InvalidOperationException();
 027            public override System.Security.Principal.TokenImpersonationLevel ImpersonationLevel => System.Security.Prin
 28
 029            public UnsupportedNegotiateAuthenticationPal(NegotiateAuthenticationClientOptions clientOptions, NegotiateAu
 030            {
 031                _package = clientOptions.Package;
 032                _targetName = clientOptions.TargetName;
 033                _statusCode = statusCode;
 034            }
 35
 036            public UnsupportedNegotiateAuthenticationPal(NegotiateAuthenticationServerOptions serverOptions, NegotiateAu
 037            {
 038                _package = serverOptions.Package;
 039                _statusCode = statusCode;
 040            }
 41
 42            public override void Dispose()
 043            {
 044            }
 45
 46            public override byte[]? GetOutgoingBlob(ReadOnlySpan<byte> incomingBlob, out NegotiateAuthenticationStatusCo
 047            {
 048                statusCode = _statusCode;
 049                return null;
 050            }
 51
 052            public override NegotiateAuthenticationStatusCode Wrap(ReadOnlySpan<byte> input, IBufferWriter<byte> outputW
 053            public override NegotiateAuthenticationStatusCode Unwrap(ReadOnlySpan<byte> input, IBufferWriter<byte> outpu
 054            public override NegotiateAuthenticationStatusCode UnwrapInPlace(Span<byte> input, out int unwrappedOffset, o
 055            public override void GetMIC(ReadOnlySpan<byte> message, IBufferWriter<byte> signature) => throw new InvalidO
 056            public override bool VerifyMIC(ReadOnlySpan<byte> message, ReadOnlySpan<byte> signature) => throw new Invali
 57        }
 58    }
 59}
 60

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Net.Security/src/System/Net/NegotiateAuthenticationPal.Windows.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Buffers;
 5using System.Buffers.Binary;
 6using System.ComponentModel;
 7using System.Diagnostics;
 8using System.Diagnostics.CodeAnalysis;
 9using System.Globalization;
 10using System.Net.Security;
 11using System.Runtime.InteropServices;
 12using System.Security;
 13using System.Security.Authentication.ExtendedProtection;
 14using System.Security.Principal;
 15
 16namespace System.Net
 17{
 18    internal partial class NegotiateAuthenticationPal
 19    {
 20        public static NegotiateAuthenticationPal Create(NegotiateAuthenticationClientOptions clientOptions)
 021        {
 22            try
 023            {
 024                return new WindowsNegotiateAuthenticationPal(clientOptions);
 25            }
 026            catch (NotSupportedException)
 027            {
 028                return new UnsupportedNegotiateAuthenticationPal(clientOptions);
 29            }
 030        }
 31
 32        public static NegotiateAuthenticationPal Create(NegotiateAuthenticationServerOptions serverOptions)
 033        {
 34            try
 035            {
 036                return new WindowsNegotiateAuthenticationPal(serverOptions);
 37            }
 038            catch (NotSupportedException)
 039            {
 040                return new UnsupportedNegotiateAuthenticationPal(serverOptions);
 41            }
 042        }
 43
 44        internal sealed class WindowsNegotiateAuthenticationPal : NegotiateAuthenticationPal
 45        {
 46            private bool _isServer;
 47            private bool _isAuthenticated;
 48            private int _tokenSize;
 49            private byte[]? _tokenBuffer;
 50            private SafeFreeCredentials? _credentialsHandle;
 51            private SafeDeleteContext? _securityContext;
 52            private Interop.SspiCli.ContextFlags _requestedContextFlags;
 53            private Interop.SspiCli.ContextFlags _contextFlags;
 54            private string _package;
 55            private string? _protocolName;
 56            private string? _spn;
 57            private ChannelBinding? _channelBinding;
 58
 059            public override bool IsAuthenticated => _isAuthenticated;
 60
 061            public override bool IsSigned => (_contextFlags & (_isServer ? Interop.SspiCli.ContextFlags.AcceptIntegrity 
 62
 063            public override bool IsEncrypted => (_contextFlags & Interop.SspiCli.ContextFlags.Confidentiality) != 0;
 64
 065            public override bool IsMutuallyAuthenticated => (_contextFlags & Interop.SspiCli.ContextFlags.MutualAuth) !=
 66
 67            public override string Package
 68            {
 69                get
 070                {
 71                    // Note: May return string.Empty if the auth is not done yet or failed.
 072                    if (_protocolName == null)
 073                    {
 074                        string? negotiationAuthenticationPackage = null;
 75
 076                        if (_securityContext is not null)
 077                        {
 078                            SecPkgContext_NegotiationInfoW ctx = default;
 079                            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, _securityCon
 080                            using (sspiHandle)
 081                            {
 082                                negotiationAuthenticationPackage = success ? NegotiationInfoClass.GetAuthenticationPacka
 083                            }
 084                            if (_isAuthenticated)
 085                            {
 086                                _protocolName = negotiationAuthenticationPackage;
 087                            }
 088                        }
 89
 090                        return negotiationAuthenticationPackage ?? string.Empty;
 91                    }
 92
 093                    return _protocolName;
 094                }
 95            }
 96
 97            public override string? TargetName
 98            {
 99                get
 0100                {
 0101                    if (_isServer && _spn == null)
 0102                    {
 0103                        Debug.Assert(_securityContext is not null && _isAuthenticated, "Trying to get the client SPN bef
 0104                        _spn = SSPIWrapper.QueryStringContextAttributes(GlobalSSPI.SSPIAuth, _securityContext, Interop.S
 0105                        if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"The client specified SPN is [{_s
 0106                    }
 0107                    return _spn;
 0108                }
 109            }
 110
 111            public override IIdentity RemoteIdentity
 112            {
 113                get
 0114                {
 115                    IIdentity? result;
 0116                    string? name = _isServer ? null : TargetName;
 0117                    string protocol = Package;
 118
 0119                    Debug.Assert(_securityContext is not null);
 120
 0121                    if (_isServer)
 0122                    {
 0123                        SecurityContextTokenHandle? token = null;
 124                        try
 0125                        {
 0126                            name = SSPIWrapper.QueryStringContextAttributes(GlobalSSPI.SSPIAuth, _securityContext, Inter
 0127                            if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"NTAuthentication: The contex
 128
 129                            // This will return a client token when conducted authentication on server side.
 130                            // This token can be used for impersonation. We use it to create a WindowsIdentity and hand 
 0131                            Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.QuerySecurityContex
 0132                                GlobalSSPI.SSPIAuth,
 0133                                _securityContext,
 0134                                out token);
 0135                            if (winStatus != Interop.SECURITY_STATUS.OK)
 0136                            {
 0137                                throw new Win32Exception((int)winStatus);
 138                            }
 139
 140                            // The following call was also specifying WindowsAccountType.Normal, true.
 141                            // WindowsIdentity.IsAuthenticated is no longer supported in .NET Core
 0142                            result = new WindowsIdentity(token.DangerousGetHandle(), protocol);
 0143                            return result;
 144                        }
 0145                        catch (SecurityException)
 0146                        {
 147                            // Ignore and construct generic Identity if failed due to security problem.
 0148                        }
 149                        finally
 0150                        {
 0151                            token?.Dispose();
 0152                        }
 0153                    }
 154
 155                    // On the client we don't have access to the remote side identity.
 0156                    result = new GenericIdentity(name ?? string.Empty, protocol);
 0157                    return result;
 0158                }
 159            }
 160
 161            public override System.Security.Principal.TokenImpersonationLevel ImpersonationLevel
 162            {
 163                get
 0164                {
 0165                    return
 0166                        (_contextFlags & Interop.SspiCli.ContextFlags.Delegate) != 0 && Package != NegotiationInfoClass.
 0167                        (_contextFlags & (_isServer ? Interop.SspiCli.ContextFlags.AcceptIdentify : Interop.SspiCli.Cont
 0168                        TokenImpersonationLevel.Impersonation;
 0169                }
 170            }
 171
 0172            public WindowsNegotiateAuthenticationPal(NegotiateAuthenticationClientOptions clientOptions)
 0173            {
 0174                Interop.SspiCli.ContextFlags contextFlags = Interop.SspiCli.ContextFlags.Connection;
 175
 0176                contextFlags |= clientOptions.RequiredProtectionLevel switch
 0177                {
 0178                    ProtectionLevel.Sign => Interop.SspiCli.ContextFlags.InitIntegrity,
 0179                    ProtectionLevel.EncryptAndSign => Interop.SspiCli.ContextFlags.InitIntegrity | Interop.SspiCli.Conte
 0180                    _ => 0
 0181                };
 182
 0183                contextFlags |= clientOptions.RequireMutualAuthentication ? Interop.SspiCli.ContextFlags.MutualAuth : 0;
 184
 0185                contextFlags |= clientOptions.AllowedImpersonationLevel switch
 0186                {
 0187                    TokenImpersonationLevel.Identification => Interop.SspiCli.ContextFlags.InitIdentify,
 0188                    TokenImpersonationLevel.Delegation => Interop.SspiCli.ContextFlags.Delegate,
 0189                    _ => 0
 0190                };
 191
 0192                _isServer = false;
 0193                _tokenSize = SSPIWrapper.GetVerifyPackageInfo(GlobalSSPI.SSPIAuth, clientOptions.Package, true)!.MaxToke
 0194                _spn = clientOptions.TargetName;
 0195                _securityContext = null;
 0196                _requestedContextFlags = contextFlags;
 0197                _package = clientOptions.Package;
 0198                _channelBinding = clientOptions.Binding;
 199
 0200                if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Peer SPN-> '{_spn}'");
 201
 202                //
 203                // Check if we're using DefaultCredentials.
 204                //
 205
 0206                Debug.Assert(CredentialCache.DefaultCredentials == CredentialCache.DefaultNetworkCredentials);
 0207                if (clientOptions.Credential == CredentialCache.DefaultCredentials)
 0208                {
 0209                    if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, "using DefaultCredentials");
 0210                    _credentialsHandle = AcquireDefaultCredential(_package, _isServer);
 0211                }
 212                else
 0213                {
 0214                    _credentialsHandle = AcquireCredentialsHandle(_package, _isServer, clientOptions.Credential);
 0215                }
 0216            }
 217
 0218            public WindowsNegotiateAuthenticationPal(NegotiateAuthenticationServerOptions serverOptions)
 0219            {
 0220                Interop.SspiCli.ContextFlags contextFlags = serverOptions.RequiredProtectionLevel switch
 0221                {
 0222                    ProtectionLevel.Sign => Interop.SspiCli.ContextFlags.AcceptIntegrity,
 0223                    ProtectionLevel.EncryptAndSign => Interop.SspiCli.ContextFlags.AcceptIntegrity | Interop.SspiCli.Con
 0224                    _ => 0
 0225                } | Interop.SspiCli.ContextFlags.Connection;
 226
 0227                if (serverOptions.Policy is not null)
 0228                {
 0229                    if (serverOptions.Policy.PolicyEnforcement == PolicyEnforcement.WhenSupported)
 0230                    {
 0231                        contextFlags |= Interop.SspiCli.ContextFlags.AllowMissingBindings;
 0232                    }
 233
 0234                    if (serverOptions.Policy.PolicyEnforcement != PolicyEnforcement.Never &&
 0235                        serverOptions.Policy.ProtectionScenario == ProtectionScenario.TrustedProxy)
 0236                    {
 0237                        contextFlags |= Interop.SspiCli.ContextFlags.ProxyBindings;
 0238                    }
 0239                }
 240
 0241                _isServer = true;
 0242                _tokenSize = SSPIWrapper.GetVerifyPackageInfo(GlobalSSPI.SSPIAuth, serverOptions.Package, true)!.MaxToke
 0243                _securityContext = null;
 0244                _requestedContextFlags = contextFlags;
 0245                _package = serverOptions.Package;
 0246                _channelBinding = serverOptions.Binding;
 247
 0248                if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Peer SPN-> '{_spn}'");
 249
 250                //
 251                // Check if we're using DefaultCredentials.
 252                //
 253
 0254                Debug.Assert(CredentialCache.DefaultCredentials == CredentialCache.DefaultNetworkCredentials);
 0255                if (serverOptions.Credential == CredentialCache.DefaultCredentials)
 0256                {
 0257                    if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, "using DefaultCredentials");
 0258                    _credentialsHandle = AcquireDefaultCredential(_package, _isServer);
 0259                }
 260                else
 0261                {
 0262                    _credentialsHandle = AcquireCredentialsHandle(_package, _isServer, serverOptions.Credential);
 0263                }
 0264            }
 265
 266            public override void Dispose()
 0267            {
 0268                _securityContext?.Dispose();
 0269            }
 270
 271            public override byte[]? GetOutgoingBlob(ReadOnlySpan<byte> incomingBlob, out NegotiateAuthenticationStatusCo
 0272            {
 0273                _tokenBuffer ??= _tokenSize == 0 ? Array.Empty<byte>() : new byte[_tokenSize];
 274
 0275                bool firstTime = _securityContext == null;
 276                int resultBlobLength;
 277                SecurityStatusPal platformStatusCode;
 278                try
 0279                {
 0280                    if (!_isServer)
 0281                    {
 282                        // client session
 0283                        platformStatusCode = InitializeSecurityContext(
 0284                            ref _credentialsHandle!,
 0285                            ref _securityContext,
 0286                            _spn,
 0287                            _requestedContextFlags,
 0288                            incomingBlob,
 0289                            _channelBinding,
 0290                            ref _tokenBuffer,
 0291                            out resultBlobLength,
 0292                            ref _contextFlags);
 293
 0294                        if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"SSPIWrapper.InitializeSecurityCo
 295
 0296                        if (platformStatusCode.ErrorCode == SecurityStatusPalErrorCode.CompleteNeeded)
 0297                        {
 0298                            platformStatusCode = CompleteAuthToken(ref _securityContext, _tokenBuffer.AsSpan(0, resultBl
 299
 0300                            if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"SSPIWrapper.CompleteAuthToke
 301
 0302                            resultBlobLength = 0;
 0303                        }
 0304                    }
 305                    else
 0306                    {
 307                        // Server session.
 0308                        platformStatusCode = AcceptSecurityContext(
 0309                            _credentialsHandle,
 0310                            ref _securityContext,
 0311                            _requestedContextFlags,
 0312                            incomingBlob,
 0313                            _channelBinding,
 0314                            ref _tokenBuffer,
 0315                            out resultBlobLength,
 0316                            ref _contextFlags);
 317
 0318                        if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"SSPIWrapper.AcceptSecurityContex
 0319                    }
 0320                }
 321                finally
 0322                {
 323                    //
 324                    // Assuming the ISC or ASC has referenced the credential on the first successful call,
 325                    // we want to decrement the effective ref count by "disposing" it.
 326                    // The real dispose will happen when the security context is closed.
 327                    // Note if the first call was not successful the handle is physically destroyed here.
 328                    //
 0329                    if (firstTime)
 0330                    {
 0331                        _credentialsHandle?.Dispose();
 0332                    }
 0333                }
 334
 335                // Map error codes
 336                // TODO: Remove double mapping from Win32 codes
 0337                statusCode = platformStatusCode.ErrorCode switch
 0338                {
 0339                    SecurityStatusPalErrorCode.OK => NegotiateAuthenticationStatusCode.Completed,
 0340                    SecurityStatusPalErrorCode.ContinueNeeded => NegotiateAuthenticationStatusCode.ContinueNeeded,
 0341
 0342                    // These code should never be returned and they should be handled internally
 0343                    SecurityStatusPalErrorCode.CompleteNeeded => NegotiateAuthenticationStatusCode.Completed,
 0344                    SecurityStatusPalErrorCode.CompAndContinue => NegotiateAuthenticationStatusCode.ContinueNeeded,
 0345
 0346                    SecurityStatusPalErrorCode.ContextExpired => NegotiateAuthenticationStatusCode.ContextExpired,
 0347                    SecurityStatusPalErrorCode.Unsupported => NegotiateAuthenticationStatusCode.Unsupported,
 0348                    SecurityStatusPalErrorCode.PackageNotFound => NegotiateAuthenticationStatusCode.Unsupported,
 0349                    SecurityStatusPalErrorCode.CannotInstall => NegotiateAuthenticationStatusCode.Unsupported,
 0350                    SecurityStatusPalErrorCode.InvalidToken => NegotiateAuthenticationStatusCode.InvalidToken,
 0351                    SecurityStatusPalErrorCode.QopNotSupported => NegotiateAuthenticationStatusCode.QopNotSupported,
 0352                    SecurityStatusPalErrorCode.NoImpersonation => NegotiateAuthenticationStatusCode.UnknownCredentials,
 0353                    SecurityStatusPalErrorCode.LogonDenied => NegotiateAuthenticationStatusCode.UnknownCredentials,
 0354                    SecurityStatusPalErrorCode.UnknownCredentials => NegotiateAuthenticationStatusCode.UnknownCredential
 0355                    SecurityStatusPalErrorCode.NoCredentials => NegotiateAuthenticationStatusCode.UnknownCredentials,
 0356                    SecurityStatusPalErrorCode.MessageAltered => NegotiateAuthenticationStatusCode.MessageAltered,
 0357                    SecurityStatusPalErrorCode.OutOfSequence => NegotiateAuthenticationStatusCode.OutOfSequence,
 0358                    SecurityStatusPalErrorCode.NoAuthenticatingAuthority => NegotiateAuthenticationStatusCode.InvalidCre
 0359                    SecurityStatusPalErrorCode.IncompleteCredentials => NegotiateAuthenticationStatusCode.InvalidCredent
 0360                    SecurityStatusPalErrorCode.IllegalMessage => NegotiateAuthenticationStatusCode.InvalidToken,
 0361                    SecurityStatusPalErrorCode.CertExpired => NegotiateAuthenticationStatusCode.CredentialsExpired,
 0362                    SecurityStatusPalErrorCode.SecurityQosFailed => NegotiateAuthenticationStatusCode.QopNotSupported,
 0363                    SecurityStatusPalErrorCode.UnsupportedPreauth => NegotiateAuthenticationStatusCode.InvalidToken,
 0364                    SecurityStatusPalErrorCode.BadBinding => NegotiateAuthenticationStatusCode.BadBinding,
 0365                    SecurityStatusPalErrorCode.UntrustedRoot => NegotiateAuthenticationStatusCode.UnknownCredentials,
 0366                    SecurityStatusPalErrorCode.SmartcardLogonRequired => NegotiateAuthenticationStatusCode.UnknownCreden
 0367                    SecurityStatusPalErrorCode.WrongPrincipal => NegotiateAuthenticationStatusCode.UnknownCredentials,
 0368                    SecurityStatusPalErrorCode.CannotPack => NegotiateAuthenticationStatusCode.InvalidToken,
 0369                    SecurityStatusPalErrorCode.TimeSkew => NegotiateAuthenticationStatusCode.InvalidToken,
 0370                    SecurityStatusPalErrorCode.AlgorithmMismatch => NegotiateAuthenticationStatusCode.InvalidToken,
 0371                    SecurityStatusPalErrorCode.CertUnknown => NegotiateAuthenticationStatusCode.UnknownCredentials,
 0372                    SecurityStatusPalErrorCode.TargetUnknown => NegotiateAuthenticationStatusCode.TargetUnknown,
 0373
 0374                    // Processing partial inputs is not supported, so this is result of incorrect input
 0375                    SecurityStatusPalErrorCode.IncompleteMessage => NegotiateAuthenticationStatusCode.InvalidToken,
 0376
 0377                    _ => NegotiateAuthenticationStatusCode.GenericFailure,
 0378                };
 379
 0380                if (((int)platformStatusCode.ErrorCode >= (int)SecurityStatusPalErrorCode.OutOfMemory))
 0381                {
 382                    //CloseContext();
 0383                    _securityContext?.Dispose();
 0384                    _isAuthenticated = true;
 0385                    _tokenBuffer = null;
 0386                    return null;
 387                }
 0388                else if (firstTime && _credentialsHandle != null)
 0389                {
 390                    // Cache until it is pushed out by newly incoming handles.
 0391                    SSPIHandleCache.CacheCredential(_credentialsHandle);
 0392                }
 393
 0394                byte[]? result =
 0395                    resultBlobLength == 0 || _tokenBuffer == null ? null :
 0396                    _tokenBuffer.Length == resultBlobLength ? _tokenBuffer :
 0397                    _tokenBuffer[0..resultBlobLength];
 398
 399                // The return value will tell us correctly if the handshake is over or not
 0400                if (platformStatusCode.ErrorCode == SecurityStatusPalErrorCode.OK
 0401                    || (_isServer && platformStatusCode.ErrorCode == SecurityStatusPalErrorCode.CompleteNeeded))
 0402                {
 403                    // Success.
 0404                    _isAuthenticated = true;
 0405                    _tokenBuffer = null;
 0406                }
 407                else
 0408                {
 409                    // We need to continue.
 0410                    if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"need continue statusCode:0x{((int)pl
 0411                }
 412
 0413                return result;
 0414            }
 415
 416            public override unsafe NegotiateAuthenticationStatusCode Wrap(ReadOnlySpan<byte> input, IBufferWriter<byte> 
 0417            {
 0418                Debug.Assert(_securityContext is not null);
 419
 0420                SecPkgContext_Sizes sizes = default;
 0421                bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, _securityContext, Intero
 0422                Debug.Assert(success);
 423
 424                // alloc new output buffer if not supplied or too small
 0425                int resultSize = input.Length + sizes.cbSecurityTrailer + sizes.cbBlockSize;
 0426                Span<byte> outputBuffer = outputWriter.GetSpan(resultSize);
 427
 428                // make a copy of user data for in-place encryption
 0429                input.CopyTo(outputBuffer.Slice(sizes.cbSecurityTrailer, input.Length));
 430
 0431                isEncrypted = requestEncryption;
 432
 0433                fixed (byte* outputPtr = outputBuffer)
 0434                {
 435                    // Prepare buffers TOKEN(signature), DATA and Padding.
 0436                    Interop.SspiCli.SecBuffer* unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[3];
 0437                    Interop.SspiCli.SecBuffer* tokenBuffer = &unmanagedBuffer[0];
 0438                    Interop.SspiCli.SecBuffer* dataBuffer = &unmanagedBuffer[1];
 0439                    Interop.SspiCli.SecBuffer* paddingBuffer = &unmanagedBuffer[2];
 0440                    tokenBuffer->BufferType = SecurityBufferType.SECBUFFER_TOKEN;
 0441                    tokenBuffer->pvBuffer = (IntPtr)(outputPtr);
 0442                    tokenBuffer->cbBuffer = sizes.cbSecurityTrailer;
 0443                    dataBuffer->BufferType = SecurityBufferType.SECBUFFER_DATA;
 0444                    dataBuffer->pvBuffer = (IntPtr)(outputPtr + sizes.cbSecurityTrailer);
 0445                    dataBuffer->cbBuffer = input.Length;
 0446                    paddingBuffer->BufferType = SecurityBufferType.SECBUFFER_PADDING;
 0447                    paddingBuffer->pvBuffer = (IntPtr)(outputPtr + sizes.cbSecurityTrailer + input.Length);
 0448                    paddingBuffer->cbBuffer = sizes.cbBlockSize;
 449
 0450                    Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(3)
 0451                    {
 0452                        pBuffers = unmanagedBuffer
 0453                    };
 454
 0455                    uint qop = requestEncryption ? 0 : Interop.SspiCli.SECQOP_WRAP_NO_ENCRYPT;
 0456                    int errorCode = GlobalSSPI.SSPIAuth.EncryptMessage(_securityContext, ref sdcInOut, qop);
 457
 0458                    if (errorCode != 0)
 0459                    {
 0460                        return errorCode switch
 0461                        {
 0462                            (int)Interop.SECURITY_STATUS.ContextExpired => NegotiateAuthenticationStatusCode.ContextExpi
 0463                            (int)Interop.SECURITY_STATUS.QopNotSupported => NegotiateAuthenticationStatusCode.QopNotSupp
 0464                            _ => NegotiateAuthenticationStatusCode.GenericFailure,
 0465                        };
 466                    }
 467
 468                    // Compact the result
 0469                    if (tokenBuffer->cbBuffer != sizes.cbSecurityTrailer)
 0470                    {
 0471                        outputBuffer.Slice(sizes.cbSecurityTrailer, dataBuffer->cbBuffer).CopyTo(
 0472                            outputBuffer.Slice(tokenBuffer->cbBuffer, dataBuffer->cbBuffer));
 0473                    }
 0474                    if (tokenBuffer->cbBuffer != sizes.cbSecurityTrailer ||
 0475                        paddingBuffer->cbBuffer != sizes.cbBlockSize)
 0476                    {
 0477                        outputBuffer.Slice(sizes.cbSecurityTrailer + input.Length, paddingBuffer->cbBuffer).CopyTo(
 0478                            outputBuffer.Slice(tokenBuffer->cbBuffer + dataBuffer->cbBuffer, paddingBuffer->cbBuffer));
 0479                    }
 480
 0481                    outputWriter.Advance(tokenBuffer->cbBuffer + dataBuffer->cbBuffer + paddingBuffer->cbBuffer);
 0482                    return NegotiateAuthenticationStatusCode.Completed;
 483                }
 0484            }
 485
 486            public override NegotiateAuthenticationStatusCode Unwrap(ReadOnlySpan<byte> input, IBufferWriter<byte> outpu
 0487            {
 0488                Span<byte> outputBuffer = outputWriter.GetSpan(input.Length).Slice(0, input.Length);
 489                NegotiateAuthenticationStatusCode statusCode;
 490
 0491                input.CopyTo(outputBuffer);
 0492                statusCode = UnwrapInPlace(outputBuffer, out int unwrappedOffset, out int unwrappedLength, out wasEncryp
 493
 0494                if (statusCode == NegotiateAuthenticationStatusCode.Completed)
 0495                {
 0496                    if (unwrappedOffset > 0)
 0497                    {
 0498                        outputBuffer.Slice(unwrappedOffset, unwrappedLength).CopyTo(outputBuffer);
 0499                    }
 0500                    outputWriter.Advance(unwrappedLength);
 0501                }
 502
 0503                return statusCode;
 0504            }
 505
 506            public override unsafe NegotiateAuthenticationStatusCode UnwrapInPlace(Span<byte> input, out int unwrappedOf
 0507            {
 0508                Debug.Assert(_securityContext is not null);
 509
 0510                fixed (byte* inputPtr = input)
 0511                {
 0512                    Interop.SspiCli.SecBuffer* unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[2];
 0513                    Interop.SspiCli.SecBuffer* streamBuffer = &unmanagedBuffer[0];
 0514                    Interop.SspiCli.SecBuffer* dataBuffer = &unmanagedBuffer[1];
 0515                    streamBuffer->BufferType = SecurityBufferType.SECBUFFER_STREAM;
 0516                    streamBuffer->pvBuffer = (IntPtr)inputPtr;
 0517                    streamBuffer->cbBuffer = input.Length;
 0518                    dataBuffer->BufferType = SecurityBufferType.SECBUFFER_DATA;
 0519                    dataBuffer->pvBuffer = IntPtr.Zero;
 0520                    dataBuffer->cbBuffer = 0;
 521
 0522                    Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(2)
 0523                    {
 0524                        pBuffers = unmanagedBuffer
 0525                    };
 526
 527                    uint qop;
 0528                    int errorCode = GlobalSSPI.SSPIAuth.DecryptMessage(_securityContext, ref sdcInOut, out qop);
 0529                    if (errorCode != 0)
 0530                    {
 0531                        unwrappedOffset = 0;
 0532                        unwrappedLength = 0;
 0533                        wasEncrypted = false;
 0534                        return errorCode switch
 0535                        {
 0536                            (int)Interop.SECURITY_STATUS.MessageAltered => NegotiateAuthenticationStatusCode.MessageAlte
 0537                            _ => NegotiateAuthenticationStatusCode.InvalidToken
 0538                        };
 539                    }
 540
 0541                    if (dataBuffer->BufferType != SecurityBufferType.SECBUFFER_DATA)
 0542                    {
 0543                        throw new InternalException(dataBuffer->BufferType);
 544                    }
 545
 0546                    wasEncrypted = qop != Interop.SspiCli.SECQOP_WRAP_NO_ENCRYPT;
 547
 0548                    Debug.Assert((nint)dataBuffer->pvBuffer >= (nint)inputPtr);
 0549                    Debug.Assert((nint)dataBuffer->pvBuffer + dataBuffer->cbBuffer <= (nint)inputPtr + input.Length);
 0550                    unwrappedOffset = (int)((byte*)dataBuffer->pvBuffer - inputPtr);
 0551                    unwrappedLength = dataBuffer->cbBuffer;
 0552                    return NegotiateAuthenticationStatusCode.Completed;
 553                }
 0554            }
 555
 556            public override unsafe void GetMIC(ReadOnlySpan<byte> message, IBufferWriter<byte> signature)
 0557            {
 0558                bool refAdded = false;
 559
 0560                Debug.Assert(_securityContext is not null);
 561
 562                try
 0563                {
 0564                    _securityContext.DangerousAddRef(ref refAdded);
 565
 0566                    SecPkgContext_Sizes sizes = default;
 0567                    bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, _securityContext, In
 0568                    Debug.Assert(success);
 569
 0570                    Span<byte> signatureBuffer = signature.GetSpan(sizes.cbMaxSignature);
 571
 0572                    fixed (byte* messagePtr = message)
 0573                    fixed (byte* signaturePtr = signatureBuffer)
 0574                    {
 575                        // Prepare buffers TOKEN(signature), DATA.
 0576                        Interop.SspiCli.SecBuffer* unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[2];
 0577                        Interop.SspiCli.SecBuffer* tokenBuffer = &unmanagedBuffer[0];
 0578                        Interop.SspiCli.SecBuffer* dataBuffer = &unmanagedBuffer[1];
 0579                        tokenBuffer->BufferType = SecurityBufferType.SECBUFFER_TOKEN;
 0580                        tokenBuffer->pvBuffer = (IntPtr)signaturePtr;
 0581                        tokenBuffer->cbBuffer = sizes.cbMaxSignature;
 0582                        dataBuffer->BufferType = SecurityBufferType.SECBUFFER_DATA;
 0583                        dataBuffer->pvBuffer = (IntPtr)messagePtr;
 0584                        dataBuffer->cbBuffer = message.Length;
 585
 0586                        Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(2)
 0587                        {
 0588                            pBuffers = unmanagedBuffer
 0589                        };
 590
 0591                        int errorCode = Interop.SspiCli.MakeSignature(ref _securityContext._handle, 0, ref sdcInOut, 0);
 592
 0593                        if (errorCode != 0)
 0594                        {
 0595                            Exception e = new Win32Exception(errorCode);
 0596                            if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, e);
 0597                            throw new Win32Exception(errorCode);
 598                        }
 599
 0600                        signature.Advance(tokenBuffer->cbBuffer);
 0601                    }
 0602                }
 603                finally
 0604                {
 0605                    if (refAdded)
 0606                    {
 0607                        _securityContext.DangerousRelease();
 0608                    }
 0609                }
 0610            }
 611
 612            public override unsafe bool VerifyMIC(ReadOnlySpan<byte> message, ReadOnlySpan<byte> signature)
 0613            {
 0614                bool refAdded = false;
 615
 0616                Debug.Assert(_securityContext is not null);
 617
 618                try
 0619                {
 0620                    _securityContext.DangerousAddRef(ref refAdded);
 621
 0622                    fixed (byte* messagePtr = message)
 0623                    fixed (byte* signaturePtr = signature)
 0624                    {
 0625                        Interop.SspiCli.SecBuffer* unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[2];
 0626                        Interop.SspiCli.SecBuffer* tokenBuffer = &unmanagedBuffer[0];
 0627                        Interop.SspiCli.SecBuffer* dataBuffer = &unmanagedBuffer[1];
 0628                        tokenBuffer->BufferType = SecurityBufferType.SECBUFFER_TOKEN;
 0629                        tokenBuffer->pvBuffer = (IntPtr)signaturePtr;
 0630                        tokenBuffer->cbBuffer = signature.Length;
 0631                        dataBuffer->BufferType = SecurityBufferType.SECBUFFER_DATA;
 0632                        dataBuffer->pvBuffer = (IntPtr)messagePtr;
 0633                        dataBuffer->cbBuffer = message.Length;
 634
 0635                        Interop.SspiCli.SecBufferDesc sdcIn = new Interop.SspiCli.SecBufferDesc(2)
 0636                        {
 0637                            pBuffers = unmanagedBuffer
 0638                        };
 639
 640                        uint qop;
 0641                        int errorCode = Interop.SspiCli.VerifySignature(ref _securityContext._handle, in sdcIn, 0, &qop)
 642
 0643                        if (errorCode != 0)
 0644                        {
 0645                            Exception e = new Win32Exception(errorCode);
 0646                            if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, e);
 0647                            throw new Win32Exception(errorCode);
 648                        }
 649
 0650                        if (IsEncrypted && qop == Interop.SspiCli.SECQOP_WRAP_NO_ENCRYPT)
 0651                        {
 0652                            Debug.Fail($"Expected qop = 0, returned value = {qop}");
 653                            throw new InvalidOperationException(SR.net_auth_message_not_encrypted);
 654                        }
 655
 0656                        return true;
 657                    }
 658                }
 659                finally
 0660                {
 0661                    if (refAdded)
 0662                    {
 0663                        _securityContext.DangerousRelease();
 0664                    }
 0665                }
 0666            }
 667
 668            private static SafeFreeCredentials AcquireDefaultCredential(string package, bool isServer)
 0669            {
 0670                return SSPIWrapper.AcquireDefaultCredential(
 0671                    GlobalSSPI.SSPIAuth,
 0672                    package,
 0673                    (isServer ? Interop.SspiCli.CredentialUse.SECPKG_CRED_INBOUND : Interop.SspiCli.CredentialUse.SECPKG
 0674            }
 675
 676            private static SafeFreeCredentials AcquireCredentialsHandle(string package, bool isServer, NetworkCredential
 0677            {
 0678                SafeSspiAuthDataHandle? authData = null;
 679                try
 0680                {
 0681                    Interop.SECURITY_STATUS result = Interop.SspiCli.SspiEncodeStringsAsAuthIdentity(
 0682                        credential.UserName, credential.Domain,
 0683                        credential.Password, out authData);
 684
 0685                    if (result != Interop.SECURITY_STATUS.OK)
 0686                    {
 0687                        if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, SR.Format(SR.net_log_operation_fa
 0688                        throw new Win32Exception((int)result);
 689                    }
 690
 0691                    return SSPIWrapper.AcquireCredentialsHandle(GlobalSSPI.SSPIAuth,
 0692                        package, (isServer ? Interop.SspiCli.CredentialUse.SECPKG_CRED_INBOUND : Interop.SspiCli.Credent
 693                }
 694                finally
 0695                {
 0696                    authData?.Dispose();
 0697                }
 0698            }
 699
 700            private static SecurityStatusPal InitializeSecurityContext(
 701                ref SafeFreeCredentials? credentialsHandle,
 702                ref SafeDeleteContext? securityContext,
 703                string? spn,
 704                Interop.SspiCli.ContextFlags requestedContextFlags,
 705                ReadOnlySpan<byte> incomingBlob,
 706                ChannelBinding? channelBinding,
 707                ref byte[]? resultBlob,
 708                out int resultBlobLength,
 709                ref Interop.SspiCli.ContextFlags contextFlags)
 0710            {
 711
 0712                InputSecurityBuffers inputBuffers = default;
 0713                if (!incomingBlob.IsEmpty)
 0714                {
 0715                    inputBuffers.SetNextBuffer(new InputSecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN)
 0716                }
 717
 0718                if (channelBinding != null)
 0719                {
 0720                    inputBuffers.SetNextBuffer(new InputSecurityBuffer(channelBinding));
 0721                }
 722
 0723                ProtocolToken token = default;
 0724                if (resultBlob != null)
 0725                {
 0726                    token.Payload = resultBlob;
 0727                    token.Size = resultBlob.Length;
 0728                }
 729
 0730                contextFlags = Interop.SspiCli.ContextFlags.Zero;
 731                // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is saf
 0732                SafeDeleteSslContext? sslContext = (SafeDeleteSslContext?)securityContext;
 0733                Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.InitializeSecurityContext(
 0734                    GlobalSSPI.SSPIAuth,
 0735                    ref credentialsHandle,
 0736                    ref sslContext,
 0737                    spn,
 0738                    requestedContextFlags,
 0739                    Interop.SspiCli.Endianness.SECURITY_NETWORK_DREP,
 0740                    ref inputBuffers,
 0741                    ref token,
 0742                    ref contextFlags);
 0743                securityContext = sslContext;
 0744                resultBlob = token.Payload;
 0745                resultBlobLength = token.Size;
 746
 0747                return SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus);
 0748            }
 749
 750            private static SecurityStatusPal CompleteAuthToken(
 751                ref SafeDeleteContext? securityContext,
 752                ReadOnlySpan<byte> incomingBlob)
 0753            {
 754                // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is saf
 0755                SafeDeleteSslContext? sslContext = (SafeDeleteSslContext?)securityContext;
 0756                var inSecurityBuffer = new InputSecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN);
 0757                Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.CompleteAuthToken(
 0758                    GlobalSSPI.SSPIAuth,
 0759                    ref sslContext,
 0760                    in inSecurityBuffer);
 0761                securityContext = sslContext;
 0762                return SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus);
 0763            }
 764
 765            private static SecurityStatusPal AcceptSecurityContext(
 766                SafeFreeCredentials? credentialsHandle,
 767                ref SafeDeleteContext? securityContext,
 768                Interop.SspiCli.ContextFlags requestedContextFlags,
 769                ReadOnlySpan<byte> incomingBlob,
 770                ChannelBinding? channelBinding,
 771                ref byte[]? resultBlob,
 772                out int resultBlobLength,
 773                ref Interop.SspiCli.ContextFlags contextFlags)
 0774            {
 0775                InputSecurityBuffers inputBuffers = default;
 0776                if (!incomingBlob.IsEmpty)
 0777                {
 0778                    inputBuffers.SetNextBuffer(new InputSecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN)
 0779                }
 780
 0781                if (channelBinding != null)
 0782                {
 0783                    inputBuffers.SetNextBuffer(new InputSecurityBuffer(channelBinding));
 0784                }
 785
 0786                ProtocolToken token = default;
 0787                if (resultBlob != null)
 0788                {
 0789                    token.Payload = resultBlob;
 0790                    token.Size = resultBlob.Length;
 0791                }
 792
 0793                contextFlags = Interop.SspiCli.ContextFlags.Zero;
 794                // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is saf
 0795                SafeDeleteSslContext? sslContext = (SafeDeleteSslContext?)securityContext;
 0796                Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.AcceptSecurityContext(
 0797                    GlobalSSPI.SSPIAuth,
 0798                    credentialsHandle,
 0799                    ref sslContext,
 0800                    requestedContextFlags,
 0801                    Interop.SspiCli.Endianness.SECURITY_NETWORK_DREP,
 0802                    ref inputBuffers,
 0803                    ref token,
 0804                    ref contextFlags);
 805
 806                // SSPI Workaround
 807                // If a client sends up a blob on the initial request, Negotiate returns SEC_E_INVALID_HANDLE
 808                // when it should return SEC_E_INVALID_TOKEN.
 0809                if (winStatus == Interop.SECURITY_STATUS.InvalidHandle && securityContext == null && !incomingBlob.IsEmp
 0810                {
 0811                    winStatus = Interop.SECURITY_STATUS.InvalidToken;
 0812                }
 813
 0814                resultBlob = token.Payload;
 0815                resultBlobLength = token.Size;
 816
 0817                securityContext = sslContext;
 0818                return SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus);
 0819            }
 820        }
 821    }
 822}
 823

Methods/Properties

IsAuthenticated()
IsSigned()
IsEncrypted()
IsMutuallyAuthenticated()
Package()
TargetName()
RemoteIdentity()
ImpersonationLevel()
.ctor(System.Net.Security.NegotiateAuthenticationClientOptions,System.Net.Security.NegotiateAuthenticationStatusCode)
.ctor(System.Net.Security.NegotiateAuthenticationServerOptions,System.Net.Security.NegotiateAuthenticationStatusCode)
Dispose()
GetOutgoingBlob(System.ReadOnlySpan`1<System.Byte>,System.Net.Security.NegotiateAuthenticationStatusCode&)
Wrap(System.ReadOnlySpan`1<System.Byte>,System.Buffers.IBufferWriter`1<System.Byte>,System.Boolean,System.Boolean&)
Unwrap(System.ReadOnlySpan`1<System.Byte>,System.Buffers.IBufferWriter`1<System.Byte>,System.Boolean&)
UnwrapInPlace(System.Span`1<System.Byte>,System.Int32&,System.Int32&,System.Boolean&)
GetMIC(System.ReadOnlySpan`1<System.Byte>,System.Buffers.IBufferWriter`1<System.Byte>)
VerifyMIC(System.ReadOnlySpan`1<System.Byte>,System.ReadOnlySpan`1<System.Byte>)
Create(System.Net.Security.NegotiateAuthenticationClientOptions)
Create(System.Net.Security.NegotiateAuthenticationServerOptions)
IsAuthenticated()
IsSigned()
IsEncrypted()
IsMutuallyAuthenticated()
Package()
TargetName()
RemoteIdentity()
ImpersonationLevel()
.ctor(System.Net.Security.NegotiateAuthenticationClientOptions)
.ctor(System.Net.Security.NegotiateAuthenticationServerOptions)
Dispose()
GetOutgoingBlob(System.ReadOnlySpan`1<System.Byte>,System.Net.Security.NegotiateAuthenticationStatusCode&)
Wrap(System.ReadOnlySpan`1<System.Byte>,System.Buffers.IBufferWriter`1<System.Byte>,System.Boolean,System.Boolean&)
Unwrap(System.ReadOnlySpan`1<System.Byte>,System.Buffers.IBufferWriter`1<System.Byte>,System.Boolean&)
UnwrapInPlace(System.Span`1<System.Byte>,System.Int32&,System.Int32&,System.Boolean&)
GetMIC(System.ReadOnlySpan`1<System.Byte>,System.Buffers.IBufferWriter`1<System.Byte>)
VerifyMIC(System.ReadOnlySpan`1<System.Byte>,System.ReadOnlySpan`1<System.Byte>)
AcquireDefaultCredential(System.String,System.Boolean)
AcquireCredentialsHandle(System.String,System.Boolean,System.Net.NetworkCredential)
InitializeSecurityContext(System.Net.Security.SafeFreeCredentials&,System.Net.Security.SafeDeleteContext&,System.String,Interop/SspiCli/ContextFlags,System.ReadOnlySpan`1<System.Byte>,System.Security.Authentication.ExtendedProtection.ChannelBinding,System.Byte[]&,System.Int32&,Interop/SspiCli/ContextFlags&)
CompleteAuthToken(System.Net.Security.SafeDeleteContext&,System.ReadOnlySpan`1<System.Byte>)
AcceptSecurityContext(System.Net.Security.SafeFreeCredentials,System.Net.Security.SafeDeleteContext&,Interop/SspiCli/ContextFlags,System.ReadOnlySpan`1<System.Byte>,System.Security.Authentication.ExtendedProtection.ChannelBinding,System.Byte[]&,System.Int32&,Interop/SspiCli/ContextFlags&)