public static object QueryContextAttributes(SSPIInterface secModule, SafeDeleteContext securityContext, Interop.SspiCli.ContextAttribute contextAttribute, out int errorCode)
{
if (NetEventSource.IsEnabled) NetEventSource.Enter(null, contextAttribute);
int nativeBlockSize = IntPtr.Size;
Type handleType = null;
switch (contextAttribute)
{
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES:
nativeBlockSize = SecPkgContext_Sizes.SizeOf;
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_STREAM_SIZES:
nativeBlockSize = SecPkgContext_StreamSizes.SizeOf;
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NAMES:
handleType = typeof(SafeFreeContextBuffer);
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_PACKAGE_INFO:
handleType = typeof(SafeFreeContextBuffer);
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NEGOTIATION_INFO:
handleType = typeof(SafeFreeContextBuffer);
nativeBlockSize = Marshal.SizeOf<SecPkgContext_NegotiationInfoW>();
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CLIENT_SPECIFIED_TARGET:
handleType = typeof(SafeFreeContextBuffer);
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_REMOTE_CERT_CONTEXT:
handleType = typeof(SafeFreeCertContext);
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_LOCAL_CERT_CONTEXT:
handleType = typeof(SafeFreeCertContext);
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_ISSUER_LIST_EX:
nativeBlockSize = Marshal.SizeOf<Interop.SspiCli.SecPkgContext_IssuerListInfoEx>();
handleType = typeof(SafeFreeContextBuffer);
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CONNECTION_INFO:
nativeBlockSize = Marshal.SizeOf<SecPkgContext_ConnectionInfo>();
break;
default:
throw new ArgumentException(SR.Format(SR.net_invalid_enum, nameof(contextAttribute)), nameof(contextAttribute));
}
SafeHandle sspiHandle = null;
object attribute = null;
try
{
var nativeBuffer = new byte[nativeBlockSize];
errorCode = secModule.QueryContextAttributes(securityContext, contextAttribute, nativeBuffer, handleType, out sspiHandle);
if (errorCode != 0)
{
if (NetEventSource.IsEnabled) NetEventSource.Exit(null, $"ERROR = {ErrorDescription(errorCode)}");
return null;
}
switch (contextAttribute)
{
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES:
attribute = new SecPkgContext_Sizes(nativeBuffer);
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_STREAM_SIZES:
attribute = new SecPkgContext_StreamSizes(nativeBuffer);
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NAMES:
attribute = Marshal.PtrToStringUni(sspiHandle.DangerousGetHandle());
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_PACKAGE_INFO:
attribute = new SecurityPackageInfoClass(sspiHandle, 0);
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NEGOTIATION_INFO:
unsafe
{
fixed (void* ptr = nativeBuffer)
{
attribute = new NegotiationInfoClass(sspiHandle, Marshal.ReadInt32(new IntPtr(ptr), SecPkgContext_NegotiationInfoW.NegotiationStateOffest));
}
}
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CLIENT_SPECIFIED_TARGET:
attribute = Marshal.PtrToStringUni(sspiHandle.DangerousGetHandle());
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_LOCAL_CERT_CONTEXT:
// Fall-through to RemoteCertificate is intentional.
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_REMOTE_CERT_CONTEXT:
attribute = sspiHandle;
sspiHandle = null;
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_ISSUER_LIST_EX:
attribute = new Interop.SspiCli.SecPkgContext_IssuerListInfoEx(sspiHandle, nativeBuffer);
sspiHandle = null;
break;
case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CONNECTION_INFO:
attribute = new SecPkgContext_ConnectionInfo(nativeBuffer);
break;
default:
// Will return null.
break;
}
}
finally
{
if (sspiHandle != null)
{
sspiHandle.Dispose();
}
}
if (NetEventSource.IsEnabled) NetEventSource.Exit(null, attribute);
return attribute;
}