< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 239
Coverable lines: 239
Total lines: 363
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 116
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/Common/src/Interop/Windows/SspiCli/SSPIWrapper.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.ComponentModel;
 5using System.Diagnostics;
 6using System.Globalization;
 7using System.Net.Security;
 8using System.Runtime.InteropServices;
 9
 10namespace System.Net
 11{
 12    internal static class SSPIWrapper
 13    {
 14        internal static SecurityPackageInfoClass[] EnumerateSecurityPackages(ISSPIInterface secModule)
 015        {
 016            if (secModule.SecurityPackages == null)
 017            {
 018                lock (secModule)
 019                {
 020                    if (secModule.SecurityPackages == null)
 021                    {
 022                        int moduleCount = 0;
 023                        SafeFreeContextBuffer? arrayBaseHandle = null;
 24                        try
 025                        {
 026                            int errorCode = secModule.EnumerateSecurityPackages(out moduleCount, out arrayBaseHandle);
 027                            if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(null, $"arrayBase: {arrayBaseHandle}
 028                            if (errorCode != 0)
 029                            {
 030                                throw new Win32Exception(errorCode);
 31                            }
 32
 033                            var securityPackages = new SecurityPackageInfoClass[moduleCount];
 34
 35                            int i;
 036                            for (i = 0; i < moduleCount; i++)
 037                            {
 038                                securityPackages[i] = new SecurityPackageInfoClass(arrayBaseHandle, i);
 039                                if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.EnumerateSecurityPackages(securit
 040                            }
 41
 042                            secModule.SecurityPackages = securityPackages;
 043                        }
 44                        finally
 045                        {
 046                            arrayBaseHandle?.Dispose();
 047                        }
 048                    }
 049                }
 050            }
 51
 052            return secModule.SecurityPackages;
 053        }
 54
 55        internal static SecurityPackageInfoClass? GetVerifyPackageInfo(ISSPIInterface secModule, string packageName, boo
 056        {
 057            SecurityPackageInfoClass[] supportedSecurityPackages = EnumerateSecurityPackages(secModule);
 058            if (supportedSecurityPackages != null)
 059            {
 060                for (int i = 0; i < supportedSecurityPackages.Length; i++)
 061                {
 062                    if (string.Equals(supportedSecurityPackages[i].Name, packageName, StringComparison.OrdinalIgnoreCase
 063                    {
 064                        return supportedSecurityPackages[i];
 65                    }
 066                }
 067            }
 68
 069            if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.SspiPackageNotFound(packageName);
 70
 071            if (throwIfMissing)
 072            {
 073                throw new NotSupportedException(SR.net_securitypackagesupport);
 74            }
 75
 076            return null;
 077        }
 78
 79        public static SafeFreeCredentials AcquireDefaultCredential(ISSPIInterface secModule, string package, Interop.Ssp
 080        {
 081            if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.AcquireDefaultCredential(package, intent);
 82
 083            SafeFreeCredentials? outCredential = null;
 084            int errorCode = secModule.AcquireDefaultCredential(package, intent, out outCredential);
 85
 086            if (errorCode != 0)
 087            {
 088                if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_wit
 089                throw new Win32Exception(errorCode);
 90            }
 091            return outCredential;
 092        }
 93
 94        public static SafeFreeCredentials AcquireCredentialsHandle(ISSPIInterface secModule, string package, Interop.Ssp
 095        {
 096            if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.AcquireCredentialsHandle(package, intent, authdata);
 97
 098            SafeFreeCredentials? credentialsHandle = null;
 099            int errorCode = secModule.AcquireCredentialsHandle(package, intent, ref authdata, out credentialsHandle);
 100
 0101            if (errorCode != 0)
 0102            {
 0103                if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_wit
 0104                throw new Win32Exception(errorCode);
 105            }
 106
 0107            return credentialsHandle;
 0108        }
 109
 110        public static unsafe SafeFreeCredentials AcquireCredentialsHandle(ISSPIInterface secModule, string package, Inte
 0111        {
 0112            int errorCode = secModule.AcquireCredentialsHandle(
 0113                                            package,
 0114                                            intent,
 0115                                            scc,
 0116                                            out SafeFreeCredentials outCredential);
 117
 0118            if (errorCode != 0)
 0119            {
 0120                if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_wit
 0121                throw new Win32Exception(errorCode);
 122            }
 123
 0124            return outCredential;
 0125        }
 126
 127        public static unsafe SafeFreeCredentials AcquireCredentialsHandle(ISSPIInterface secModule, string package, Inte
 0128        {
 0129            int errorCode = secModule.AcquireCredentialsHandle(
 0130                                            package,
 0131                                            intent,
 0132                                            scc,
 0133                                            out SafeFreeCredentials outCredential);
 134
 0135            if (errorCode != 0)
 0136            {
 0137                if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_wit
 0138                throw new Win32Exception(errorCode);
 139            }
 140
 0141            return outCredential;
 0142        }
 143
 144        internal static int InitializeSecurityContext(ISSPIInterface secModule, ref SafeFreeCredentials? credential, ref
 0145        {
 0146            if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.InitializeSecurityContext(credential, context, target
 147
 0148            int errorCode = secModule.InitializeSecurityContext(ref credential, ref context, targetName, inFlags, datare
 149
 0150            if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.SecurityContextInputBuffers(nameof(InitializeSecurity
 151
 0152            return errorCode;
 0153        }
 154
 155        internal static int AcceptSecurityContext(ISSPIInterface secModule, SafeFreeCredentials? credential, ref SafeDel
 0156        {
 0157            if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.AcceptSecurityContext(credential, context, inFlags);
 158
 0159            int errorCode = secModule.AcceptSecurityContext(credential, ref context, ref inputBuffers, inFlags, datarep,
 160
 0161            if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.SecurityContextInputBuffers(nameof(AcceptSecurityCont
 162
 0163            return errorCode;
 0164        }
 165
 166        internal static int CompleteAuthToken(ISSPIInterface secModule, ref SafeDeleteSslContext? context, in InputSecur
 0167        {
 0168            int errorCode = secModule.CompleteAuthToken(ref context, in inputBuffer);
 169
 0170            if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.OperationReturnedSomething(nameof(CompleteAuthToken),
 171
 0172            return errorCode;
 0173        }
 174
 175        internal static int ApplyControlToken(ISSPIInterface secModule, ref SafeDeleteSslContext? context, in SecurityBu
 0176        {
 0177            int errorCode = secModule.ApplyControlToken(ref context, in inputBuffer);
 178
 0179            if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.OperationReturnedSomething(nameof(ApplyControlToken),
 180
 0181            return errorCode;
 0182        }
 183
 184        public static int QuerySecurityContextToken(ISSPIInterface secModule, SafeDeleteContext context, out SecurityCon
 0185        {
 0186            return secModule.QuerySecurityContextToken(context, out token);
 0187        }
 188
 189        public static SafeFreeContextBufferChannelBinding? QueryContextChannelBinding(ISSPIInterface secModule, SafeDele
 0190        {
 191            SafeFreeContextBufferChannelBinding result;
 0192            int errorCode = secModule.QueryContextChannelBinding(securityContext, contextAttribute, out result);
 0193            if (errorCode != 0)
 0194            {
 0195                result.Dispose();
 0196                if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, $"ERROR = {ErrorDescription(errorCode)}")
 0197                return null;
 198            }
 199
 0200            return result;
 0201        }
 202
 203        public static bool QueryBlittableContextAttributes<T>(ISSPIInterface secModule, SafeDeleteContext securityContex
 0204        {
 0205            Span<T> span = new Span<T>(ref attribute);
 0206            int errorCode = secModule.QueryContextAttributes(
 0207                securityContext, contextAttribute,
 0208                MemoryMarshal.AsBytes(span),
 0209                null,
 0210                out SafeHandle? sspiHandle);
 211
 0212            using (sspiHandle)
 0213            {
 0214                if (errorCode != 0)
 0215                {
 0216                    if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, $"ERROR = {ErrorDescription(errorCode
 0217                    return false;
 218                }
 219
 0220                return true;
 221            }
 0222        }
 223
 224        public static bool QueryBlittableContextAttributes<T>(ISSPIInterface secModule, SafeDeleteContext securityContex
 0225        {
 0226            Span<T> span = new Span<T>(ref attribute);
 0227            int errorCode = secModule.QueryContextAttributes(
 0228                securityContext, contextAttribute,
 0229                MemoryMarshal.AsBytes(span),
 0230                safeHandleType,
 0231                out sspiHandle);
 232
 0233            if (errorCode != 0)
 0234            {
 0235                if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, $"ERROR = {ErrorDescription(errorCode)}")
 0236                return false;
 237            }
 238
 0239            return true;
 0240        }
 241
 242        public static unsafe string? QueryStringContextAttributes(ISSPIInterface secModule, SafeDeleteContext securityCo
 0243        {
 0244            Debug.Assert(
 0245                contextAttribute == Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NAMES ||
 0246                contextAttribute == Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CLIENT_SPECIFIED_TARGET);
 247
 248
 0249            Span<byte> buffer = stackalloc byte[IntPtr.Size];
 0250            int errorCode = secModule.QueryContextAttributes(
 0251                securityContext,
 0252                contextAttribute,
 0253                buffer,
 0254                typeof(SafeFreeContextBuffer),
 0255                out SafeHandle? sspiHandle);
 256
 0257            Debug.Assert(sspiHandle != null);
 258
 0259            using (sspiHandle)
 0260            {
 0261                if (errorCode != 0)
 0262                {
 0263                    if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, $"ERROR = {ErrorDescription(errorCode
 0264                    return null;
 265                }
 266
 0267                string? result = Marshal.PtrToStringUni(sspiHandle.DangerousGetHandle());
 0268                if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(null, result);
 0269                return result;
 270            }
 0271        }
 272
 273        private static unsafe bool QueryCertContextAttribute(ISSPIInterface secModule, SafeDeleteContext securityContext
 0274        {
 0275            IntPtr handle = IntPtr.Zero;
 0276            certContext = null;
 277
 278            try
 0279            {
 0280                int errorCode = secModule.QueryContextAttributes(
 0281                    securityContext,
 0282                    attribute,
 0283                    &handle);
 284
 285                // certificate is not always present (e.g. on server when querying client certificate)
 286                // but we still want to consider such case as a success.
 0287                bool success = errorCode == 0 || errorCode == (int)Interop.SECURITY_STATUS.NoCredentials;
 288
 0289                if (errorCode == 0 && handle != IntPtr.Zero)
 0290                {
 0291                    certContext = new SafeFreeCertContext();
 0292                    certContext.Set(handle);
 293                    // Handle was successfully transferred to SafeHandle
 0294                    handle = IntPtr.Zero;
 0295                }
 0296                if (!success)
 0297                {
 0298                    if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, $"ERROR = {ErrorDescription(errorCode
 0299                }
 0300                return success;
 301            }
 302            finally
 0303            {
 0304                if (handle != IntPtr.Zero)
 0305                {
 0306                    Interop.Crypt32.CertFreeCertificateContext(handle);
 0307                }
 0308            }
 0309        }
 310
 311        public static bool QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CONTEXT(ISSPIInterface secModule, SafeDeleteCo
 0312            => QueryCertContextAttribute(secModule, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_REMOTE
 313
 314        public static bool QueryContextAttributes_SECPKG_ATTR_LOCAL_CERT_CONTEXT(ISSPIInterface secModule, SafeDeleteCon
 0315            => QueryCertContextAttribute(secModule, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_LOCAL_
 316
 317        public static bool QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CHAIN(ISSPIInterface secModule, SafeDeleteCont
 0318            => QueryCertContextAttribute(secModule, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_REMOTE
 319
 320        public static bool QueryContextAttributes_SECPKG_ATTR_ISSUER_LIST_EX(ISSPIInterface secModule, SafeDeleteContext
 0321        {
 0322            Span<Interop.SspiCli.SecPkgContext_IssuerListInfoEx> buffer = new Span<Interop.SspiCli.SecPkgContext_IssuerL
 0323            int errorCode = secModule.QueryContextAttributes(
 0324                securityContext,
 0325                Interop.SspiCli.ContextAttribute.SECPKG_ATTR_ISSUER_LIST_EX,
 0326                MemoryMarshal.AsBytes(buffer),
 0327                typeof(SafeFreeContextBuffer),
 0328                out sspiHandle);
 329
 0330            if (errorCode != 0)
 0331            {
 0332                if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, $"ERROR = {ErrorDescription(errorCode)}")
 0333                return false;
 334            }
 335
 0336            return true;
 0337        }
 338
 339        public static string ErrorDescription(int errorCode)
 0340        {
 0341            if (errorCode == -1)
 0342            {
 0343                return "An exception when invoking Win32 API";
 344            }
 345
 0346            return (Interop.SECURITY_STATUS)errorCode switch
 0347            {
 0348                Interop.SECURITY_STATUS.InvalidHandle => "Invalid handle",
 0349                Interop.SECURITY_STATUS.InvalidToken => "Invalid token",
 0350                Interop.SECURITY_STATUS.ContinueNeeded => "Continue needed",
 0351                Interop.SECURITY_STATUS.IncompleteMessage => "Message incomplete",
 0352                Interop.SECURITY_STATUS.WrongPrincipal => "Wrong principal",
 0353                Interop.SECURITY_STATUS.TargetUnknown => "Target unknown",
 0354                Interop.SECURITY_STATUS.PackageNotFound => "Package not found",
 0355                Interop.SECURITY_STATUS.BufferNotEnough => "Buffer not enough",
 0356                Interop.SECURITY_STATUS.MessageAltered => "Message altered",
 0357                Interop.SECURITY_STATUS.UntrustedRoot => "Untrusted root",
 0358                _ => "0x" + errorCode.ToString("x", NumberFormatInfo.InvariantInfo),
 0359            };
 0360        }
 361    } // class SSPIWrapper
 362}
 363

Methods/Properties

EnumerateSecurityPackages(System.Net.ISSPIInterface)
GetVerifyPackageInfo(System.Net.ISSPIInterface,System.String,System.Boolean)
AcquireDefaultCredential(System.Net.ISSPIInterface,System.String,Interop/SspiCli/CredentialUse)
AcquireCredentialsHandle(System.Net.ISSPIInterface,System.String,Interop/SspiCli/CredentialUse,System.Net.Security.SafeSspiAuthDataHandle&)
AcquireCredentialsHandle(System.Net.ISSPIInterface,System.String,Interop/SspiCli/CredentialUse,Interop/SspiCli/SCHANNEL_CRED*)
AcquireCredentialsHandle(System.Net.ISSPIInterface,System.String,Interop/SspiCli/CredentialUse,Interop/SspiCli/SCH_CREDENTIALS*)
InitializeSecurityContext(System.Net.ISSPIInterface,System.Net.Security.SafeFreeCredentials&,System.Net.Security.SafeDeleteSslContext&,System.String,Interop/SspiCli/ContextFlags,Interop/SspiCli/Endianness,System.Net.Security.InputSecurityBuffers&,System.Net.Security.ProtocolToken&,Interop/SspiCli/ContextFlags&)
AcceptSecurityContext(System.Net.ISSPIInterface,System.Net.Security.SafeFreeCredentials,System.Net.Security.SafeDeleteSslContext&,Interop/SspiCli/ContextFlags,Interop/SspiCli/Endianness,System.Net.Security.InputSecurityBuffers&,System.Net.Security.ProtocolToken&,Interop/SspiCli/ContextFlags&)
CompleteAuthToken(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteSslContext&,System.Net.Security.InputSecurityBuffer&)
ApplyControlToken(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteSslContext&,System.Net.Security.SecurityBuffer&)
QuerySecurityContextToken(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteContext,System.Net.Security.SecurityContextTokenHandle&)
QueryContextChannelBinding(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteContext,Interop/SspiCli/ContextAttribute)
QueryBlittableContextAttributes(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteContext,Interop/SspiCli/ContextAttribute,T&)
QueryBlittableContextAttributes(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteContext,Interop/SspiCli/ContextAttribute,System.Type,System.Runtime.InteropServices.SafeHandle&,T&)
QueryStringContextAttributes(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteContext,Interop/SspiCli/ContextAttribute)
QueryCertContextAttribute(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteContext,Interop/SspiCli/ContextAttribute,System.Net.Security.SafeFreeCertContext&)
QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CONTEXT(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteContext,System.Net.Security.SafeFreeCertContext&)
QueryContextAttributes_SECPKG_ATTR_LOCAL_CERT_CONTEXT(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteContext,System.Net.Security.SafeFreeCertContext&)
QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CHAIN(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteContext,System.Net.Security.SafeFreeCertContext&)
QueryContextAttributes_SECPKG_ATTR_ISSUER_LIST_EX(System.Net.ISSPIInterface,System.Net.Security.SafeDeleteContext,Interop/SspiCli/SecPkgContext_IssuerListInfoEx&,System.Runtime.InteropServices.SafeHandle&)
ErrorDescription(System.Int32)