Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Net / System / Net / _SSPIWrapper.cs / 1 / _SSPIWrapper.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Net { using System.Runtime.InteropServices; using System.Diagnostics; using System.ComponentModel; using System.Net.Sockets; using System.Security.Permissions; using System.Globalization; using System.Net.Security; internal static class SSPIWrapper { internal static SecurityPackageInfoClass[] EnumerateSecurityPackages(SSPIInterface SecModule) { GlobalLog.Enter("EnumerateSecurityPackages"); if (SecModule.SecurityPackages==null) { lock (SecModule) { if (SecModule.SecurityPackages==null) { int moduleCount = 0; SafeFreeContextBuffer arrayBaseHandle = null; try { int errorCode = SecModule.EnumerateSecurityPackages(out moduleCount, out arrayBaseHandle); GlobalLog.Print("SSPIWrapper::arrayBase: " + (arrayBaseHandle.DangerousGetHandle().ToString("x"))); if (errorCode != 0) { throw new Win32Exception(errorCode); } SecurityPackageInfoClass[] securityPackages = new SecurityPackageInfoClass[moduleCount]; if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_enumerating_security_packages)); int i; for (i = 0; i < moduleCount; i++) { securityPackages[i] = new SecurityPackageInfoClass(arrayBaseHandle, i); if (Logging.On) Logging.PrintInfo(Logging.Web, " " + securityPackages[i].Name); } SecModule.SecurityPackages = securityPackages; } finally { if (arrayBaseHandle != null) { arrayBaseHandle.Close(); } } } } } GlobalLog.Leave("EnumerateSecurityPackages"); return SecModule.SecurityPackages; } internal static SecurityPackageInfoClass GetVerifyPackageInfo(SSPIInterface secModule, string packageName) { return GetVerifyPackageInfo(secModule, packageName, false); } internal static SecurityPackageInfoClass GetVerifyPackageInfo(SSPIInterface secModule, string packageName, bool throwIfMissing) { SecurityPackageInfoClass[] supportedSecurityPackages = EnumerateSecurityPackages(secModule); if (supportedSecurityPackages != null) { for (int i = 0; i < supportedSecurityPackages.Length; i++) { if (string.Compare(supportedSecurityPackages[i].Name, packageName, StringComparison.OrdinalIgnoreCase) == 0) { return supportedSecurityPackages[i]; } } } if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_package_not_found, packageName)); // error if (throwIfMissing) { throw new NotSupportedException(SR.GetString(SR.net_securitypackagesupport)); } return null; } public static SafeFreeCredentials AcquireDefaultCredential(SSPIInterface SecModule, string package, CredentialUse intent) { GlobalLog.Print("SSPIWrapper::AcquireDefaultCredential(): using " + package); if (Logging.On) Logging.PrintInfo(Logging.Web, "AcquireDefaultCredential(" + "package = " + package + ", " + "intent = " + intent + ")"); SafeFreeCredentials outCredential = null; int errorCode = SecModule.AcquireDefaultCredential(package, intent, out outCredential ); if (errorCode != 0) { #if TRAVE GlobalLog.Print("SSPIWrapper::AcquireDefaultCredential(): error " + SecureChannel.MapSecurityStatus((uint)errorCode)); #endif if (Logging.On) Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, "AcquireDefaultCredential()", String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode))); throw new Win32Exception(errorCode); } return outCredential; } public static SafeFreeCredentials AcquireCredentialsHandle(SSPIInterface SecModule, string package, CredentialUse intent, ref AuthIdentity authdata) { GlobalLog.Print("SSPIWrapper::AcquireCredentialsHandle#2(): using " + package); if (Logging.On) Logging.PrintInfo(Logging.Web, "AcquireCredentialsHandle(" + "package = " + package + ", " + "intent = " + intent + ", " + "authdata = " + authdata + ")"); SafeFreeCredentials credentialsHandle = null; int errorCode = SecModule.AcquireCredentialsHandle(package, intent, ref authdata, out credentialsHandle ); if (errorCode != 0) { #if TRAVE GlobalLog.Print("SSPIWrapper::AcquireCredentialsHandle#2(): error " + SecureChannel.MapSecurityStatus((uint)errorCode)); #endif if (Logging.On) Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, "AcquireCredentialsHandle()", String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode))); throw new Win32Exception(errorCode); } return credentialsHandle; } public static SafeFreeCredentials AcquireCredentialsHandle(SSPIInterface SecModule, string package, CredentialUse intent, SecureCredential scc) { GlobalLog.Print("SSPIWrapper::AcquireCredentialsHandle#3(): using " + package); if (Logging.On) Logging.PrintInfo(Logging.Web, "AcquireCredentialsHandle(" + "package = " + package + ", " + "intent = " + intent + ", " + "scc = " + scc + ")"); SafeFreeCredentials outCredential = null; int errorCode = SecModule.AcquireCredentialsHandle( package, intent, ref scc, out outCredential ); if (errorCode != 0) { #if TRAVE GlobalLog.Print("SSPIWrapper::AcquireCredentialsHandle#3(): error " + SecureChannel.MapSecurityStatus((uint)errorCode)); #endif if (Logging.On) Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, "AcquireCredentialsHandle()", String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode))); throw new Win32Exception(errorCode); } #if TRAVE GlobalLog.Print("SSPIWrapper::AcquireCredentialsHandle#3(): cred handle = " + outCredential.ToString()); #endif return outCredential; } internal static int InitializeSecurityContext(SSPIInterface SecModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, ContextFlags inFlags, Endianness datarep, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref ContextFlags outFlags) { if (Logging.On) Logging.PrintInfo(Logging.Web, "InitializeSecurityContext(" + "credential = " + credential.ToString() + ", " + "context = " + ValidationHelper.ToString(context) + ", " + "targetName = " + targetName + ", " + "inFlags = " + inFlags + ")"); int errorCode = SecModule.InitializeSecurityContext(ref credential, ref context, targetName, inFlags, datarep, inputBuffer, outputBuffer, ref outFlags); if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_context_input_buffer, "InitializeSecurityContext", (inputBuffer == null ? 0 : inputBuffer.size), outputBuffer.size, (SecurityStatus) errorCode)); return errorCode; } internal static int InitializeSecurityContext(SSPIInterface SecModule, SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, ContextFlags inFlags, Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref ContextFlags outFlags) { if (Logging.On) Logging.PrintInfo(Logging.Web, "InitializeSecurityContext(" + "credential = " + credential.ToString() + ", " + "context = " + ValidationHelper.ToString(context) + ", " + "targetName = " + targetName + ", " + "inFlags = " + inFlags + ")"); int errorCode = SecModule.InitializeSecurityContext(credential, ref context, targetName, inFlags, datarep, inputBuffers, outputBuffer, ref outFlags); if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_context_input_buffers, "InitializeSecurityContext", (inputBuffers == null ? 0 : inputBuffers.Length), outputBuffer.size, (SecurityStatus) errorCode)); return errorCode; } internal static int AcceptSecurityContext(SSPIInterface SecModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, ContextFlags inFlags, Endianness datarep, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref ContextFlags outFlags) { if (Logging.On) Logging.PrintInfo(Logging.Web, "AcceptSecurityContext(" + "credential = " + credential.ToString() + ", " + "context = " + ValidationHelper.ToString(context) + ", " + "inFlags = " + inFlags + ")"); int errorCode = SecModule.AcceptSecurityContext(ref credential, ref context, inputBuffer, inFlags, datarep, outputBuffer, ref outFlags); if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_context_input_buffer, "AcceptSecurityContext", (inputBuffer == null ? 0 : inputBuffer.size), outputBuffer.size, (SecurityStatus) errorCode)); return errorCode; } internal static int AcceptSecurityContext(SSPIInterface SecModule, SafeFreeCredentials credential, ref SafeDeleteContext context, ContextFlags inFlags, Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref ContextFlags outFlags) { if (Logging.On) Logging.PrintInfo(Logging.Web, "AcceptSecurityContext(" + "credential = " + credential.ToString() + ", " + "context = " + ValidationHelper.ToString(context) + ", " + "inFlags = " + inFlags + ")"); int errorCode = SecModule.AcceptSecurityContext(credential, ref context, inputBuffers, inFlags, datarep, outputBuffer, ref outFlags); if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_context_input_buffers, "AcceptSecurityContext", (inputBuffers == null ? 0 : inputBuffers.Length), outputBuffer.size, (SecurityStatus) errorCode)); return errorCode; } internal static int CompleteAuthToken(SSPIInterface SecModule, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers) { int errorCode = SecModule.CompleteAuthToken(ref context, inputBuffers); if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_operation_returned_something, "CompleteAuthToken()", (SecurityStatus) errorCode)); return errorCode; } public static int QuerySecurityContextToken(SSPIInterface SecModule, SafeDeleteContext context, out SafeCloseHandle token) { return SecModule.QuerySecurityContextToken(context, out token); } public static int EncryptMessage(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { return EncryptDecryptHelper(OP.Encrypt, secModule, context, input, sequenceNumber); } public static int DecryptMessage(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { return EncryptDecryptHelper(OP.Decrypt, secModule, context, input, sequenceNumber); } internal static int MakeSignature(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { return EncryptDecryptHelper(OP.MakeSignature, secModule, context, input, sequenceNumber); } public static int VerifySignature(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { return EncryptDecryptHelper(OP.VerifySignature, secModule, context, input, sequenceNumber); } private enum OP { Encrypt = 1, Decrypt, MakeSignature, VerifySignature } // private unsafe static int EncryptDecryptHelper(OP op, SSPIInterface SecModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { SecurityBufferDescriptor sdcInOut = new SecurityBufferDescriptor(input.Length); SecurityBufferStruct[] unmanagedBuffer = new SecurityBufferStruct[input.Length]; fixed (SecurityBufferStruct* unmanagedBufferPtr = unmanagedBuffer) { sdcInOut.UnmanagedPointer = unmanagedBufferPtr; GCHandle[] pinnedBuffers = new GCHandle[input.Length]; byte[][] buffers = new byte[input.Length][]; try { for (int i = 0; i < input.Length; i++) { SecurityBuffer iBuffer = input[i]; unmanagedBuffer[i].count = iBuffer.size; unmanagedBuffer[i].type = iBuffer.type; if (iBuffer.token == null || iBuffer.token.Length == 0) { unmanagedBuffer[i].token = IntPtr.Zero; } else { pinnedBuffers[i] = GCHandle.Alloc(iBuffer.token, GCHandleType.Pinned); unmanagedBuffer[i].token = Marshal.UnsafeAddrOfPinnedArrayElement(iBuffer.token, iBuffer.offset); buffers[i] = iBuffer.token; } } // The result is written in the input Buffer passed as type=BufferType.Data. int errorCode; switch (op) { case OP.Encrypt: errorCode = SecModule.EncryptMessage(context, sdcInOut, sequenceNumber); break; case OP.Decrypt: errorCode = SecModule.DecryptMessage(context, sdcInOut, sequenceNumber); break; case OP.MakeSignature: errorCode = SecModule.MakeSignature(context, sdcInOut, sequenceNumber); break; case OP.VerifySignature: errorCode = SecModule.VerifySignature(context, sdcInOut, sequenceNumber); break; default: throw ExceptionHelper.MethodNotImplementedException; } // Marshalling back returned sizes / data. for (int i = 0; i < input.Length; i++) { SecurityBuffer iBuffer = input[i]; iBuffer.size = unmanagedBuffer[i].count; iBuffer.type = unmanagedBuffer[i].type; if (iBuffer.size == 0) { iBuffer.offset = 0; iBuffer.token = null; } else checked { // Find the buffer this is inside of. Usually they all point inside buffer 0. int j; for (j = 0; j < input.Length; j++) { if (buffers[j] == null) { continue; } byte* bufferAddress = (byte*) Marshal.UnsafeAddrOfPinnedArrayElement(buffers[j], 0); if ((byte*) unmanagedBuffer[i].token >= bufferAddress && (byte*) unmanagedBuffer[i].token + iBuffer.size <= bufferAddress + buffers[j].Length) { iBuffer.offset = (int) ((byte*) unmanagedBuffer[i].token - bufferAddress); iBuffer.token = buffers[j]; break; } } if (j >= input.Length) { GlobalLog.Assert("SSPIWrapper::EncryptDecryptHelper", "Output buffer out of range."); iBuffer.size = 0; iBuffer.offset = 0; iBuffer.token = null; } } // Backup validate the new sizes. GlobalLog.Assert(iBuffer.offset >= 0 && iBuffer.offset <= (iBuffer.token == null ? 0 : iBuffer.token.Length), "SSPIWrapper::EncryptDecryptHelper|'offset' out of range. [{0}]", iBuffer.offset); GlobalLog.Assert(iBuffer.size >= 0 && iBuffer.size <= (iBuffer.token == null ? 0 : iBuffer.token.Length - iBuffer.offset), "SSPIWrapper::EncryptDecryptHelper|'size' out of range. [{0}]", iBuffer.size); } if (errorCode !=0) if (Logging.On) { if (errorCode == 0x90321) Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_returned_something, op, "SEC_I_RENEGOTIATE")); else Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, op, String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode))); } return errorCode; } finally { for (int i = 0; i < pinnedBuffers.Length; ++i) { if (pinnedBuffers[i].IsAllocated) { pinnedBuffers[i].Free(); } } } } } public static object QueryContextAttributes(SSPIInterface SecModule, SafeDeleteContext securityContext, ContextAttribute contextAttribute) { GlobalLog.Enter("QueryContextAttributes", contextAttribute.ToString()); int nativeBlockSize = IntPtr.Size; Type handleType = null; switch (contextAttribute) { case ContextAttribute.Sizes: nativeBlockSize = SecSizes.SizeOf; break; case ContextAttribute.StreamSizes: nativeBlockSize = StreamSizes.SizeOf; break; case ContextAttribute.Names: handleType = typeof(SafeFreeContextBuffer); break; case ContextAttribute.PackageInfo: handleType = typeof(SafeFreeContextBuffer); break; case ContextAttribute.NegotiationInfo: handleType = typeof(SafeFreeContextBuffer); nativeBlockSize = Marshal.SizeOf(typeof(NegotiationInfo)); break; case ContextAttribute.RemoteCertificate: handleType = typeof(SafeFreeCertContext); break; case ContextAttribute.LocalCertificate: handleType = typeof(SafeFreeCertContext); break; case ContextAttribute.IssuerListInfoEx: nativeBlockSize = Marshal.SizeOf(typeof(IssuerListInfoEx)); handleType = typeof(SafeFreeContextBuffer); break; case ContextAttribute.ConnectionInfo: nativeBlockSize = Marshal.SizeOf(typeof(SslConnectionInfo)); break; default: throw new ArgumentException(SR.GetString(SR.net_invalid_enum, "ContextAttribute"), "contextAttribute"); } SafeHandle SspiHandle = null; object attribute = null; try { byte[] nativeBuffer = new byte[nativeBlockSize]; int errorCode = SecModule.QueryContextAttributes(securityContext, contextAttribute, nativeBuffer, handleType, out SspiHandle); if (errorCode != 0) { GlobalLog.Leave("Win32:QueryContextAttributes", "ERROR = " + ErrorDescription(errorCode)); return null; } switch (contextAttribute) { case ContextAttribute.Sizes: attribute = new SecSizes(nativeBuffer); break; case ContextAttribute.StreamSizes: attribute = new StreamSizes(nativeBuffer); break; case ContextAttribute.Names: if (ComNetOS.IsWin9x) { attribute = Marshal.PtrToStringAnsi(SspiHandle.DangerousGetHandle()); } else { attribute = Marshal.PtrToStringUni(SspiHandle.DangerousGetHandle()); } break; case ContextAttribute.PackageInfo: attribute = new SecurityPackageInfoClass(SspiHandle, 0); break; case ContextAttribute.NegotiationInfo: unsafe { fixed (void* ptr=nativeBuffer) { attribute = new NegotiationInfoClass(SspiHandle, Marshal.ReadInt32(new IntPtr(ptr), NegotiationInfo.NegotiationStateOffest)); } } break; case ContextAttribute.LocalCertificate: goto case ContextAttribute.RemoteCertificate; case ContextAttribute.RemoteCertificate: attribute = SspiHandle; SspiHandle = null; break; case ContextAttribute.IssuerListInfoEx: attribute = new IssuerListInfoEx(SspiHandle, nativeBuffer); SspiHandle = null; break; case ContextAttribute.ConnectionInfo: attribute = new SslConnectionInfo(nativeBuffer); break; default: // will return null break; } } finally { if (SspiHandle != null) { SspiHandle.Close(); } } GlobalLog.Leave("QueryContextAttributes", ValidationHelper.ToString(attribute)); return attribute; } public static string ErrorDescription(int errorCode) { if (errorCode == -1) { return "An exception when invoking Win32 API"; } switch ((SecurityStatus)errorCode) { case SecurityStatus.InvalidHandle: return "Invalid handle"; case SecurityStatus.InvalidToken: return "Invalid token"; case SecurityStatus.ContinueNeeded: return "Continue needed"; case SecurityStatus.IncompleteMessage: return "Message incomplete"; case SecurityStatus.WrongPrincipal: return "Wrong principal"; case SecurityStatus.TargetUnknown: return "Target unknown"; case SecurityStatus.PackageNotFound: return "Package not found"; case SecurityStatus.BufferNotEnough: return "Buffer not enough"; case SecurityStatus.MessageAltered: return "Message altered"; case SecurityStatus.UntrustedRoot: return "Untrusted root"; default: return "0x"+errorCode.ToString("x", NumberFormatInfo.InvariantInfo); } } } // class SSPIWrapper [StructLayout(LayoutKind.Sequential)] internal class StreamSizes { public int header; public int trailer; public int maximumMessage; public int buffersCount; public int blockSize; internal unsafe StreamSizes(byte[] memory) { fixed(void* voidPtr = memory) { IntPtr unmanagedAddress = new IntPtr(voidPtr); try { header = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress)); trailer = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 4)); maximumMessage = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 8)); buffersCount = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 12)); blockSize = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 16)); } catch (OverflowException) { GlobalLog.Assert(false, "StreamSizes::.ctor", "Negative size."); throw; } } } public static readonly int SizeOf = Marshal.SizeOf(typeof(StreamSizes)); } [StructLayout(LayoutKind.Sequential)] internal class SecSizes { public readonly int MaxToken; public readonly int MaxSignature; public readonly int BlockSize; public readonly int SecurityTrailer; internal unsafe SecSizes(byte[] memory) { fixed(void* voidPtr = memory) { IntPtr unmanagedAddress = new IntPtr(voidPtr); try { MaxToken = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress)); MaxSignature = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 4)); BlockSize = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 8)); SecurityTrailer = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 12)); } catch (OverflowException) { GlobalLog.Assert(false, "SecSizes::.ctor", "Negative size."); throw; } } } public static readonly int SizeOf = Marshal.SizeOf(typeof(SecSizes)); } //From Schannel.h internal enum SchProtocols { Zero = 0, PctClient = 0x00000002, PctServer = 0x00000001, Pct = (PctClient | PctServer), Ssl2Client = 0x00000008, Ssl2Server = 0x00000004, Ssl2 = (Ssl2Client | Ssl2Server), Ssl3Client = 0x00000020, Ssl3Server = 0x00000010, Ssl3 = (Ssl3Client | Ssl3Server), TlsClient = 0x00000080, TlsServer = 0x00000040, Tls = (TlsClient | TlsServer), Ssl3Tls = (Ssl3 | Tls), UniClient = unchecked((int)0x80000000), UniServer = 0x40000000, Unified = (UniClient | UniServer), ClientMask = (PctClient | Ssl2Client | Ssl3Client | TlsClient |UniClient), ServerMask = (PctServer | Ssl2Server | Ssl3Server | TlsServer |UniServer) }; //From WinCrypt.h [Flags] internal enum Alg { Any = 0, ClassSignture = (1 << 13), ClassEncrypt = (3 << 13), ClassHash = (4 << 13), ClassKeyXch = (5 << 13), TypeRSA = (2 << 9), TypeBlock = (3 << 9), TypeStream = (4 << 9), TypeDH = (5 << 9), NameDES = 1, NameRC2 = 2, Name3DES = 3, NameAES_128 = 14, NameAES_192 = 15, NameAES_256 = 16, NameAES = 17, NameRC4 = 1, NameMD5 = 3, NameSHA = 4, NameDH_Ephem = 2, } //From Schannel.h [StructLayout(LayoutKind.Sequential)] internal class SslConnectionInfo { public readonly int Protocol; public readonly int DataCipherAlg; public readonly int DataKeySize; public readonly int DataHashAlg; public readonly int DataHashKeySize; public readonly int KeyExchangeAlg; public readonly int KeyExchKeySize; internal unsafe SslConnectionInfo(byte[] nativeBuffer) { fixed(void* voidPtr = nativeBuffer) { IntPtr unmanagedAddress = new IntPtr(voidPtr); Protocol = Marshal.ReadInt32(unmanagedAddress); DataCipherAlg = Marshal.ReadInt32(unmanagedAddress, 4); DataKeySize = Marshal.ReadInt32(unmanagedAddress, 8); DataHashAlg = Marshal.ReadInt32(unmanagedAddress, 12); DataHashKeySize = Marshal.ReadInt32(unmanagedAddress, 16); KeyExchangeAlg = Marshal.ReadInt32(unmanagedAddress, 20); KeyExchKeySize = Marshal.ReadInt32(unmanagedAddress, 24); } } } [StructLayout(LayoutKind.Sequential)] internal struct NegotiationInfo { // see SecPkgContext_NegotiationInfoW in// [MarshalAs(UnmanagedType.LPStruct)] internal SecurityPackageInfo PackageInfo; internal IntPtr PackageInfo; internal uint NegotiationState; internal static readonly int Size = Marshal.SizeOf(typeof(NegotiationInfo)); internal static readonly int NegotiationStateOffest = (int)Marshal.OffsetOf(typeof(NegotiationInfo), "NegotiationState"); } // we keep it simple since we use this only to know if NTLM or // Kerberos are used in the context of a Negotiate handshake internal class NegotiationInfoClass { internal const string NTLM = "NTLM"; internal const string Kerberos = "Kerberos"; internal const string WDigest = "WDigest"; internal const string Negotiate = "Negotiate"; internal string AuthenticationPackage; internal NegotiationInfoClass(SafeHandle safeHandle, int negotiationState) { if (safeHandle.IsInvalid) { GlobalLog.Print("NegotiationInfoClass::.ctor() the handle is invalid:" + (safeHandle.DangerousGetHandle()).ToString("x")); return; } IntPtr packageInfo = safeHandle.DangerousGetHandle(); GlobalLog.Print("NegotiationInfoClass::.ctor() packageInfo:" + packageInfo.ToString("x8") + " negotiationState:" + negotiationState.ToString("x8")); const int SECPKG_NEGOTIATION_COMPLETE = 0; const int SECPKG_NEGOTIATION_OPTIMISTIC = 1; // const int SECPKG_NEGOTIATION_IN_PROGRESS = 2; // const int SECPKG_NEGOTIATION_DIRECT = 3; // const int SECPKG_NEGOTIATION_TRY_MULTICRED = 4; if (negotiationState==SECPKG_NEGOTIATION_COMPLETE || negotiationState==SECPKG_NEGOTIATION_OPTIMISTIC) { IntPtr unmanagedString = Marshal.ReadIntPtr(packageInfo, SecurityPackageInfo.NameOffest); string name = null; if (unmanagedString!=IntPtr.Zero) { name = ComNetOS.IsWin9x ? Marshal.PtrToStringAnsi(unmanagedString) : Marshal.PtrToStringUni(unmanagedString); } GlobalLog.Print("NegotiationInfoClass::.ctor() packageInfo:" + packageInfo.ToString("x8") + " negotiationState:" + negotiationState.ToString("x8") + " name:" + ValidationHelper.ToString(name)); // an optimization for future string comparisons if (string.Compare(name, Kerberos, StringComparison.OrdinalIgnoreCase)==0) { AuthenticationPackage = Kerberos; } else if (string.Compare(name, NTLM, StringComparison.OrdinalIgnoreCase)==0) { AuthenticationPackage = NTLM; } else if (string.Compare(name, WDigest, StringComparison.OrdinalIgnoreCase)==0) { AuthenticationPackage = WDigest; } else { AuthenticationPackage = name; } } } } [StructLayout(LayoutKind.Sequential)] internal struct SecurityPackageInfo { // see SecPkgInfoW in internal int Capabilities; internal short Version; internal short RPCID; internal int MaxToken; internal IntPtr Name; internal IntPtr Comment; internal static readonly int Size = Marshal.SizeOf(typeof(SecurityPackageInfo)); internal static readonly int NameOffest = (int)Marshal.OffsetOf(typeof(SecurityPackageInfo), "Name"); } internal class SecurityPackageInfoClass { internal int Capabilities = 0; internal short Version = 0; internal short RPCID = 0; internal int MaxToken = 0; internal string Name = null; internal string Comment = null; /* * This is to support SSL under semi trusted enviornment. * Note that it is only for SSL with no client cert */ internal SecurityPackageInfoClass(SafeHandle safeHandle, int index) { if (safeHandle.IsInvalid) { GlobalLog.Print("SecurityPackageInfoClass::.ctor() the pointer is invalid: " + (safeHandle.DangerousGetHandle()).ToString("x")); return; } IntPtr unmanagedAddress = IntPtrHelper.Add(safeHandle.DangerousGetHandle(), SecurityPackageInfo.Size * index); GlobalLog.Print("SecurityPackageInfoClass::.ctor() unmanagedPointer: " + ((long)unmanagedAddress).ToString("x")); Capabilities = Marshal.ReadInt32(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"Capabilities")); Version = Marshal.ReadInt16(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"Version")); RPCID = Marshal.ReadInt16(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"RPCID")); MaxToken = Marshal.ReadInt32(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"MaxToken")); IntPtr unmanagedString; unmanagedString = Marshal.ReadIntPtr(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"Name")); if (unmanagedString != IntPtr.Zero) { if (ComNetOS.IsWin9x) { Name = Marshal.PtrToStringAnsi(unmanagedString); } else { Name = Marshal.PtrToStringUni(unmanagedString); } GlobalLog.Print("Name: " + Name); } unmanagedString = Marshal.ReadIntPtr(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"Comment")); if (unmanagedString != IntPtr.Zero) { if (ComNetOS.IsWin9x) { Comment = Marshal.PtrToStringAnsi(unmanagedString); } else { Comment = Marshal.PtrToStringUni(unmanagedString); } GlobalLog.Print("Comment: " + Comment); } GlobalLog.Print("SecurityPackageInfoClass::.ctor(): " + ToString()); } public override string ToString() { return "Capabilities:" + String.Format(CultureInfo.InvariantCulture, "0x{0:x}", Capabilities) + " Version:" + Version.ToString(NumberFormatInfo.InvariantInfo) + " RPCID:" + RPCID.ToString(NumberFormatInfo.InvariantInfo) + " MaxToken:" + MaxToken.ToString(NumberFormatInfo.InvariantInfo) + " Name:" + ((Name==null)?"(null)":Name) + " Comment:" + ((Comment==null)?"(null)":Comment ); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Net { using System.Runtime.InteropServices; using System.Diagnostics; using System.ComponentModel; using System.Net.Sockets; using System.Security.Permissions; using System.Globalization; using System.Net.Security; internal static class SSPIWrapper { internal static SecurityPackageInfoClass[] EnumerateSecurityPackages(SSPIInterface SecModule) { GlobalLog.Enter("EnumerateSecurityPackages"); if (SecModule.SecurityPackages==null) { lock (SecModule) { if (SecModule.SecurityPackages==null) { int moduleCount = 0; SafeFreeContextBuffer arrayBaseHandle = null; try { int errorCode = SecModule.EnumerateSecurityPackages(out moduleCount, out arrayBaseHandle); GlobalLog.Print("SSPIWrapper::arrayBase: " + (arrayBaseHandle.DangerousGetHandle().ToString("x"))); if (errorCode != 0) { throw new Win32Exception(errorCode); } SecurityPackageInfoClass[] securityPackages = new SecurityPackageInfoClass[moduleCount]; if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_enumerating_security_packages)); int i; for (i = 0; i < moduleCount; i++) { securityPackages[i] = new SecurityPackageInfoClass(arrayBaseHandle, i); if (Logging.On) Logging.PrintInfo(Logging.Web, " " + securityPackages[i].Name); } SecModule.SecurityPackages = securityPackages; } finally { if (arrayBaseHandle != null) { arrayBaseHandle.Close(); } } } } } GlobalLog.Leave("EnumerateSecurityPackages"); return SecModule.SecurityPackages; } internal static SecurityPackageInfoClass GetVerifyPackageInfo(SSPIInterface secModule, string packageName) { return GetVerifyPackageInfo(secModule, packageName, false); } internal static SecurityPackageInfoClass GetVerifyPackageInfo(SSPIInterface secModule, string packageName, bool throwIfMissing) { SecurityPackageInfoClass[] supportedSecurityPackages = EnumerateSecurityPackages(secModule); if (supportedSecurityPackages != null) { for (int i = 0; i < supportedSecurityPackages.Length; i++) { if (string.Compare(supportedSecurityPackages[i].Name, packageName, StringComparison.OrdinalIgnoreCase) == 0) { return supportedSecurityPackages[i]; } } } if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_package_not_found, packageName)); // error if (throwIfMissing) { throw new NotSupportedException(SR.GetString(SR.net_securitypackagesupport)); } return null; } public static SafeFreeCredentials AcquireDefaultCredential(SSPIInterface SecModule, string package, CredentialUse intent) { GlobalLog.Print("SSPIWrapper::AcquireDefaultCredential(): using " + package); if (Logging.On) Logging.PrintInfo(Logging.Web, "AcquireDefaultCredential(" + "package = " + package + ", " + "intent = " + intent + ")"); SafeFreeCredentials outCredential = null; int errorCode = SecModule.AcquireDefaultCredential(package, intent, out outCredential ); if (errorCode != 0) { #if TRAVE GlobalLog.Print("SSPIWrapper::AcquireDefaultCredential(): error " + SecureChannel.MapSecurityStatus((uint)errorCode)); #endif if (Logging.On) Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, "AcquireDefaultCredential()", String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode))); throw new Win32Exception(errorCode); } return outCredential; } public static SafeFreeCredentials AcquireCredentialsHandle(SSPIInterface SecModule, string package, CredentialUse intent, ref AuthIdentity authdata) { GlobalLog.Print("SSPIWrapper::AcquireCredentialsHandle#2(): using " + package); if (Logging.On) Logging.PrintInfo(Logging.Web, "AcquireCredentialsHandle(" + "package = " + package + ", " + "intent = " + intent + ", " + "authdata = " + authdata + ")"); SafeFreeCredentials credentialsHandle = null; int errorCode = SecModule.AcquireCredentialsHandle(package, intent, ref authdata, out credentialsHandle ); if (errorCode != 0) { #if TRAVE GlobalLog.Print("SSPIWrapper::AcquireCredentialsHandle#2(): error " + SecureChannel.MapSecurityStatus((uint)errorCode)); #endif if (Logging.On) Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, "AcquireCredentialsHandle()", String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode))); throw new Win32Exception(errorCode); } return credentialsHandle; } public static SafeFreeCredentials AcquireCredentialsHandle(SSPIInterface SecModule, string package, CredentialUse intent, SecureCredential scc) { GlobalLog.Print("SSPIWrapper::AcquireCredentialsHandle#3(): using " + package); if (Logging.On) Logging.PrintInfo(Logging.Web, "AcquireCredentialsHandle(" + "package = " + package + ", " + "intent = " + intent + ", " + "scc = " + scc + ")"); SafeFreeCredentials outCredential = null; int errorCode = SecModule.AcquireCredentialsHandle( package, intent, ref scc, out outCredential ); if (errorCode != 0) { #if TRAVE GlobalLog.Print("SSPIWrapper::AcquireCredentialsHandle#3(): error " + SecureChannel.MapSecurityStatus((uint)errorCode)); #endif if (Logging.On) Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, "AcquireCredentialsHandle()", String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode))); throw new Win32Exception(errorCode); } #if TRAVE GlobalLog.Print("SSPIWrapper::AcquireCredentialsHandle#3(): cred handle = " + outCredential.ToString()); #endif return outCredential; } internal static int InitializeSecurityContext(SSPIInterface SecModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, ContextFlags inFlags, Endianness datarep, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref ContextFlags outFlags) { if (Logging.On) Logging.PrintInfo(Logging.Web, "InitializeSecurityContext(" + "credential = " + credential.ToString() + ", " + "context = " + ValidationHelper.ToString(context) + ", " + "targetName = " + targetName + ", " + "inFlags = " + inFlags + ")"); int errorCode = SecModule.InitializeSecurityContext(ref credential, ref context, targetName, inFlags, datarep, inputBuffer, outputBuffer, ref outFlags); if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_context_input_buffer, "InitializeSecurityContext", (inputBuffer == null ? 0 : inputBuffer.size), outputBuffer.size, (SecurityStatus) errorCode)); return errorCode; } internal static int InitializeSecurityContext(SSPIInterface SecModule, SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, ContextFlags inFlags, Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref ContextFlags outFlags) { if (Logging.On) Logging.PrintInfo(Logging.Web, "InitializeSecurityContext(" + "credential = " + credential.ToString() + ", " + "context = " + ValidationHelper.ToString(context) + ", " + "targetName = " + targetName + ", " + "inFlags = " + inFlags + ")"); int errorCode = SecModule.InitializeSecurityContext(credential, ref context, targetName, inFlags, datarep, inputBuffers, outputBuffer, ref outFlags); if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_context_input_buffers, "InitializeSecurityContext", (inputBuffers == null ? 0 : inputBuffers.Length), outputBuffer.size, (SecurityStatus) errorCode)); return errorCode; } internal static int AcceptSecurityContext(SSPIInterface SecModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, ContextFlags inFlags, Endianness datarep, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref ContextFlags outFlags) { if (Logging.On) Logging.PrintInfo(Logging.Web, "AcceptSecurityContext(" + "credential = " + credential.ToString() + ", " + "context = " + ValidationHelper.ToString(context) + ", " + "inFlags = " + inFlags + ")"); int errorCode = SecModule.AcceptSecurityContext(ref credential, ref context, inputBuffer, inFlags, datarep, outputBuffer, ref outFlags); if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_context_input_buffer, "AcceptSecurityContext", (inputBuffer == null ? 0 : inputBuffer.size), outputBuffer.size, (SecurityStatus) errorCode)); return errorCode; } internal static int AcceptSecurityContext(SSPIInterface SecModule, SafeFreeCredentials credential, ref SafeDeleteContext context, ContextFlags inFlags, Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref ContextFlags outFlags) { if (Logging.On) Logging.PrintInfo(Logging.Web, "AcceptSecurityContext(" + "credential = " + credential.ToString() + ", " + "context = " + ValidationHelper.ToString(context) + ", " + "inFlags = " + inFlags + ")"); int errorCode = SecModule.AcceptSecurityContext(credential, ref context, inputBuffers, inFlags, datarep, outputBuffer, ref outFlags); if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_context_input_buffers, "AcceptSecurityContext", (inputBuffers == null ? 0 : inputBuffers.Length), outputBuffer.size, (SecurityStatus) errorCode)); return errorCode; } internal static int CompleteAuthToken(SSPIInterface SecModule, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers) { int errorCode = SecModule.CompleteAuthToken(ref context, inputBuffers); if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_operation_returned_something, "CompleteAuthToken()", (SecurityStatus) errorCode)); return errorCode; } public static int QuerySecurityContextToken(SSPIInterface SecModule, SafeDeleteContext context, out SafeCloseHandle token) { return SecModule.QuerySecurityContextToken(context, out token); } public static int EncryptMessage(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { return EncryptDecryptHelper(OP.Encrypt, secModule, context, input, sequenceNumber); } public static int DecryptMessage(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { return EncryptDecryptHelper(OP.Decrypt, secModule, context, input, sequenceNumber); } internal static int MakeSignature(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { return EncryptDecryptHelper(OP.MakeSignature, secModule, context, input, sequenceNumber); } public static int VerifySignature(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { return EncryptDecryptHelper(OP.VerifySignature, secModule, context, input, sequenceNumber); } private enum OP { Encrypt = 1, Decrypt, MakeSignature, VerifySignature } // private unsafe static int EncryptDecryptHelper(OP op, SSPIInterface SecModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { SecurityBufferDescriptor sdcInOut = new SecurityBufferDescriptor(input.Length); SecurityBufferStruct[] unmanagedBuffer = new SecurityBufferStruct[input.Length]; fixed (SecurityBufferStruct* unmanagedBufferPtr = unmanagedBuffer) { sdcInOut.UnmanagedPointer = unmanagedBufferPtr; GCHandle[] pinnedBuffers = new GCHandle[input.Length]; byte[][] buffers = new byte[input.Length][]; try { for (int i = 0; i < input.Length; i++) { SecurityBuffer iBuffer = input[i]; unmanagedBuffer[i].count = iBuffer.size; unmanagedBuffer[i].type = iBuffer.type; if (iBuffer.token == null || iBuffer.token.Length == 0) { unmanagedBuffer[i].token = IntPtr.Zero; } else { pinnedBuffers[i] = GCHandle.Alloc(iBuffer.token, GCHandleType.Pinned); unmanagedBuffer[i].token = Marshal.UnsafeAddrOfPinnedArrayElement(iBuffer.token, iBuffer.offset); buffers[i] = iBuffer.token; } } // The result is written in the input Buffer passed as type=BufferType.Data. int errorCode; switch (op) { case OP.Encrypt: errorCode = SecModule.EncryptMessage(context, sdcInOut, sequenceNumber); break; case OP.Decrypt: errorCode = SecModule.DecryptMessage(context, sdcInOut, sequenceNumber); break; case OP.MakeSignature: errorCode = SecModule.MakeSignature(context, sdcInOut, sequenceNumber); break; case OP.VerifySignature: errorCode = SecModule.VerifySignature(context, sdcInOut, sequenceNumber); break; default: throw ExceptionHelper.MethodNotImplementedException; } // Marshalling back returned sizes / data. for (int i = 0; i < input.Length; i++) { SecurityBuffer iBuffer = input[i]; iBuffer.size = unmanagedBuffer[i].count; iBuffer.type = unmanagedBuffer[i].type; if (iBuffer.size == 0) { iBuffer.offset = 0; iBuffer.token = null; } else checked { // Find the buffer this is inside of. Usually they all point inside buffer 0. int j; for (j = 0; j < input.Length; j++) { if (buffers[j] == null) { continue; } byte* bufferAddress = (byte*) Marshal.UnsafeAddrOfPinnedArrayElement(buffers[j], 0); if ((byte*) unmanagedBuffer[i].token >= bufferAddress && (byte*) unmanagedBuffer[i].token + iBuffer.size <= bufferAddress + buffers[j].Length) { iBuffer.offset = (int) ((byte*) unmanagedBuffer[i].token - bufferAddress); iBuffer.token = buffers[j]; break; } } if (j >= input.Length) { GlobalLog.Assert("SSPIWrapper::EncryptDecryptHelper", "Output buffer out of range."); iBuffer.size = 0; iBuffer.offset = 0; iBuffer.token = null; } } // Backup validate the new sizes. GlobalLog.Assert(iBuffer.offset >= 0 && iBuffer.offset <= (iBuffer.token == null ? 0 : iBuffer.token.Length), "SSPIWrapper::EncryptDecryptHelper|'offset' out of range. [{0}]", iBuffer.offset); GlobalLog.Assert(iBuffer.size >= 0 && iBuffer.size <= (iBuffer.token == null ? 0 : iBuffer.token.Length - iBuffer.offset), "SSPIWrapper::EncryptDecryptHelper|'size' out of range. [{0}]", iBuffer.size); } if (errorCode !=0) if (Logging.On) { if (errorCode == 0x90321) Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_returned_something, op, "SEC_I_RENEGOTIATE")); else Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, op, String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode))); } return errorCode; } finally { for (int i = 0; i < pinnedBuffers.Length; ++i) { if (pinnedBuffers[i].IsAllocated) { pinnedBuffers[i].Free(); } } } } } public static object QueryContextAttributes(SSPIInterface SecModule, SafeDeleteContext securityContext, ContextAttribute contextAttribute) { GlobalLog.Enter("QueryContextAttributes", contextAttribute.ToString()); int nativeBlockSize = IntPtr.Size; Type handleType = null; switch (contextAttribute) { case ContextAttribute.Sizes: nativeBlockSize = SecSizes.SizeOf; break; case ContextAttribute.StreamSizes: nativeBlockSize = StreamSizes.SizeOf; break; case ContextAttribute.Names: handleType = typeof(SafeFreeContextBuffer); break; case ContextAttribute.PackageInfo: handleType = typeof(SafeFreeContextBuffer); break; case ContextAttribute.NegotiationInfo: handleType = typeof(SafeFreeContextBuffer); nativeBlockSize = Marshal.SizeOf(typeof(NegotiationInfo)); break; case ContextAttribute.RemoteCertificate: handleType = typeof(SafeFreeCertContext); break; case ContextAttribute.LocalCertificate: handleType = typeof(SafeFreeCertContext); break; case ContextAttribute.IssuerListInfoEx: nativeBlockSize = Marshal.SizeOf(typeof(IssuerListInfoEx)); handleType = typeof(SafeFreeContextBuffer); break; case ContextAttribute.ConnectionInfo: nativeBlockSize = Marshal.SizeOf(typeof(SslConnectionInfo)); break; default: throw new ArgumentException(SR.GetString(SR.net_invalid_enum, "ContextAttribute"), "contextAttribute"); } SafeHandle SspiHandle = null; object attribute = null; try { byte[] nativeBuffer = new byte[nativeBlockSize]; int errorCode = SecModule.QueryContextAttributes(securityContext, contextAttribute, nativeBuffer, handleType, out SspiHandle); if (errorCode != 0) { GlobalLog.Leave("Win32:QueryContextAttributes", "ERROR = " + ErrorDescription(errorCode)); return null; } switch (contextAttribute) { case ContextAttribute.Sizes: attribute = new SecSizes(nativeBuffer); break; case ContextAttribute.StreamSizes: attribute = new StreamSizes(nativeBuffer); break; case ContextAttribute.Names: if (ComNetOS.IsWin9x) { attribute = Marshal.PtrToStringAnsi(SspiHandle.DangerousGetHandle()); } else { attribute = Marshal.PtrToStringUni(SspiHandle.DangerousGetHandle()); } break; case ContextAttribute.PackageInfo: attribute = new SecurityPackageInfoClass(SspiHandle, 0); break; case ContextAttribute.NegotiationInfo: unsafe { fixed (void* ptr=nativeBuffer) { attribute = new NegotiationInfoClass(SspiHandle, Marshal.ReadInt32(new IntPtr(ptr), NegotiationInfo.NegotiationStateOffest)); } } break; case ContextAttribute.LocalCertificate: goto case ContextAttribute.RemoteCertificate; case ContextAttribute.RemoteCertificate: attribute = SspiHandle; SspiHandle = null; break; case ContextAttribute.IssuerListInfoEx: attribute = new IssuerListInfoEx(SspiHandle, nativeBuffer); SspiHandle = null; break; case ContextAttribute.ConnectionInfo: attribute = new SslConnectionInfo(nativeBuffer); break; default: // will return null break; } } finally { if (SspiHandle != null) { SspiHandle.Close(); } } GlobalLog.Leave("QueryContextAttributes", ValidationHelper.ToString(attribute)); return attribute; } public static string ErrorDescription(int errorCode) { if (errorCode == -1) { return "An exception when invoking Win32 API"; } switch ((SecurityStatus)errorCode) { case SecurityStatus.InvalidHandle: return "Invalid handle"; case SecurityStatus.InvalidToken: return "Invalid token"; case SecurityStatus.ContinueNeeded: return "Continue needed"; case SecurityStatus.IncompleteMessage: return "Message incomplete"; case SecurityStatus.WrongPrincipal: return "Wrong principal"; case SecurityStatus.TargetUnknown: return "Target unknown"; case SecurityStatus.PackageNotFound: return "Package not found"; case SecurityStatus.BufferNotEnough: return "Buffer not enough"; case SecurityStatus.MessageAltered: return "Message altered"; case SecurityStatus.UntrustedRoot: return "Untrusted root"; default: return "0x"+errorCode.ToString("x", NumberFormatInfo.InvariantInfo); } } } // class SSPIWrapper [StructLayout(LayoutKind.Sequential)] internal class StreamSizes { public int header; public int trailer; public int maximumMessage; public int buffersCount; public int blockSize; internal unsafe StreamSizes(byte[] memory) { fixed(void* voidPtr = memory) { IntPtr unmanagedAddress = new IntPtr(voidPtr); try { header = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress)); trailer = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 4)); maximumMessage = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 8)); buffersCount = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 12)); blockSize = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 16)); } catch (OverflowException) { GlobalLog.Assert(false, "StreamSizes::.ctor", "Negative size."); throw; } } } public static readonly int SizeOf = Marshal.SizeOf(typeof(StreamSizes)); } [StructLayout(LayoutKind.Sequential)] internal class SecSizes { public readonly int MaxToken; public readonly int MaxSignature; public readonly int BlockSize; public readonly int SecurityTrailer; internal unsafe SecSizes(byte[] memory) { fixed(void* voidPtr = memory) { IntPtr unmanagedAddress = new IntPtr(voidPtr); try { MaxToken = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress)); MaxSignature = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 4)); BlockSize = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 8)); SecurityTrailer = (int) checked((uint) Marshal.ReadInt32(unmanagedAddress, 12)); } catch (OverflowException) { GlobalLog.Assert(false, "SecSizes::.ctor", "Negative size."); throw; } } } public static readonly int SizeOf = Marshal.SizeOf(typeof(SecSizes)); } //From Schannel.h internal enum SchProtocols { Zero = 0, PctClient = 0x00000002, PctServer = 0x00000001, Pct = (PctClient | PctServer), Ssl2Client = 0x00000008, Ssl2Server = 0x00000004, Ssl2 = (Ssl2Client | Ssl2Server), Ssl3Client = 0x00000020, Ssl3Server = 0x00000010, Ssl3 = (Ssl3Client | Ssl3Server), TlsClient = 0x00000080, TlsServer = 0x00000040, Tls = (TlsClient | TlsServer), Ssl3Tls = (Ssl3 | Tls), UniClient = unchecked((int)0x80000000), UniServer = 0x40000000, Unified = (UniClient | UniServer), ClientMask = (PctClient | Ssl2Client | Ssl3Client | TlsClient |UniClient), ServerMask = (PctServer | Ssl2Server | Ssl3Server | TlsServer |UniServer) }; //From WinCrypt.h [Flags] internal enum Alg { Any = 0, ClassSignture = (1 << 13), ClassEncrypt = (3 << 13), ClassHash = (4 << 13), ClassKeyXch = (5 << 13), TypeRSA = (2 << 9), TypeBlock = (3 << 9), TypeStream = (4 << 9), TypeDH = (5 << 9), NameDES = 1, NameRC2 = 2, Name3DES = 3, NameAES_128 = 14, NameAES_192 = 15, NameAES_256 = 16, NameAES = 17, NameRC4 = 1, NameMD5 = 3, NameSHA = 4, NameDH_Ephem = 2, } //From Schannel.h [StructLayout(LayoutKind.Sequential)] internal class SslConnectionInfo { public readonly int Protocol; public readonly int DataCipherAlg; public readonly int DataKeySize; public readonly int DataHashAlg; public readonly int DataHashKeySize; public readonly int KeyExchangeAlg; public readonly int KeyExchKeySize; internal unsafe SslConnectionInfo(byte[] nativeBuffer) { fixed(void* voidPtr = nativeBuffer) { IntPtr unmanagedAddress = new IntPtr(voidPtr); Protocol = Marshal.ReadInt32(unmanagedAddress); DataCipherAlg = Marshal.ReadInt32(unmanagedAddress, 4); DataKeySize = Marshal.ReadInt32(unmanagedAddress, 8); DataHashAlg = Marshal.ReadInt32(unmanagedAddress, 12); DataHashKeySize = Marshal.ReadInt32(unmanagedAddress, 16); KeyExchangeAlg = Marshal.ReadInt32(unmanagedAddress, 20); KeyExchKeySize = Marshal.ReadInt32(unmanagedAddress, 24); } } } [StructLayout(LayoutKind.Sequential)] internal struct NegotiationInfo { // see SecPkgContext_NegotiationInfoW in// [MarshalAs(UnmanagedType.LPStruct)] internal SecurityPackageInfo PackageInfo; internal IntPtr PackageInfo; internal uint NegotiationState; internal static readonly int Size = Marshal.SizeOf(typeof(NegotiationInfo)); internal static readonly int NegotiationStateOffest = (int)Marshal.OffsetOf(typeof(NegotiationInfo), "NegotiationState"); } // we keep it simple since we use this only to know if NTLM or // Kerberos are used in the context of a Negotiate handshake internal class NegotiationInfoClass { internal const string NTLM = "NTLM"; internal const string Kerberos = "Kerberos"; internal const string WDigest = "WDigest"; internal const string Negotiate = "Negotiate"; internal string AuthenticationPackage; internal NegotiationInfoClass(SafeHandle safeHandle, int negotiationState) { if (safeHandle.IsInvalid) { GlobalLog.Print("NegotiationInfoClass::.ctor() the handle is invalid:" + (safeHandle.DangerousGetHandle()).ToString("x")); return; } IntPtr packageInfo = safeHandle.DangerousGetHandle(); GlobalLog.Print("NegotiationInfoClass::.ctor() packageInfo:" + packageInfo.ToString("x8") + " negotiationState:" + negotiationState.ToString("x8")); const int SECPKG_NEGOTIATION_COMPLETE = 0; const int SECPKG_NEGOTIATION_OPTIMISTIC = 1; // const int SECPKG_NEGOTIATION_IN_PROGRESS = 2; // const int SECPKG_NEGOTIATION_DIRECT = 3; // const int SECPKG_NEGOTIATION_TRY_MULTICRED = 4; if (negotiationState==SECPKG_NEGOTIATION_COMPLETE || negotiationState==SECPKG_NEGOTIATION_OPTIMISTIC) { IntPtr unmanagedString = Marshal.ReadIntPtr(packageInfo, SecurityPackageInfo.NameOffest); string name = null; if (unmanagedString!=IntPtr.Zero) { name = ComNetOS.IsWin9x ? Marshal.PtrToStringAnsi(unmanagedString) : Marshal.PtrToStringUni(unmanagedString); } GlobalLog.Print("NegotiationInfoClass::.ctor() packageInfo:" + packageInfo.ToString("x8") + " negotiationState:" + negotiationState.ToString("x8") + " name:" + ValidationHelper.ToString(name)); // an optimization for future string comparisons if (string.Compare(name, Kerberos, StringComparison.OrdinalIgnoreCase)==0) { AuthenticationPackage = Kerberos; } else if (string.Compare(name, NTLM, StringComparison.OrdinalIgnoreCase)==0) { AuthenticationPackage = NTLM; } else if (string.Compare(name, WDigest, StringComparison.OrdinalIgnoreCase)==0) { AuthenticationPackage = WDigest; } else { AuthenticationPackage = name; } } } } [StructLayout(LayoutKind.Sequential)] internal struct SecurityPackageInfo { // see SecPkgInfoW in internal int Capabilities; internal short Version; internal short RPCID; internal int MaxToken; internal IntPtr Name; internal IntPtr Comment; internal static readonly int Size = Marshal.SizeOf(typeof(SecurityPackageInfo)); internal static readonly int NameOffest = (int)Marshal.OffsetOf(typeof(SecurityPackageInfo), "Name"); } internal class SecurityPackageInfoClass { internal int Capabilities = 0; internal short Version = 0; internal short RPCID = 0; internal int MaxToken = 0; internal string Name = null; internal string Comment = null; /* * This is to support SSL under semi trusted enviornment. * Note that it is only for SSL with no client cert */ internal SecurityPackageInfoClass(SafeHandle safeHandle, int index) { if (safeHandle.IsInvalid) { GlobalLog.Print("SecurityPackageInfoClass::.ctor() the pointer is invalid: " + (safeHandle.DangerousGetHandle()).ToString("x")); return; } IntPtr unmanagedAddress = IntPtrHelper.Add(safeHandle.DangerousGetHandle(), SecurityPackageInfo.Size * index); GlobalLog.Print("SecurityPackageInfoClass::.ctor() unmanagedPointer: " + ((long)unmanagedAddress).ToString("x")); Capabilities = Marshal.ReadInt32(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"Capabilities")); Version = Marshal.ReadInt16(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"Version")); RPCID = Marshal.ReadInt16(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"RPCID")); MaxToken = Marshal.ReadInt32(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"MaxToken")); IntPtr unmanagedString; unmanagedString = Marshal.ReadIntPtr(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"Name")); if (unmanagedString != IntPtr.Zero) { if (ComNetOS.IsWin9x) { Name = Marshal.PtrToStringAnsi(unmanagedString); } else { Name = Marshal.PtrToStringUni(unmanagedString); } GlobalLog.Print("Name: " + Name); } unmanagedString = Marshal.ReadIntPtr(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo),"Comment")); if (unmanagedString != IntPtr.Zero) { if (ComNetOS.IsWin9x) { Comment = Marshal.PtrToStringAnsi(unmanagedString); } else { Comment = Marshal.PtrToStringUni(unmanagedString); } GlobalLog.Print("Comment: " + Comment); } GlobalLog.Print("SecurityPackageInfoClass::.ctor(): " + ToString()); } public override string ToString() { return "Capabilities:" + String.Format(CultureInfo.InvariantCulture, "0x{0:x}", Capabilities) + " Version:" + Version.ToString(NumberFormatInfo.InvariantInfo) + " RPCID:" + RPCID.ToString(NumberFormatInfo.InvariantInfo) + " MaxToken:" + MaxToken.ToString(NumberFormatInfo.InvariantInfo) + " Name:" + ((Name==null)?"(null)":Name) + " Comment:" + ((Comment==null)?"(null)":Comment ); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CodeTypeDeclarationCollection.cs
- WorkflowFileItem.cs
- FreezableOperations.cs
- AddingNewEventArgs.cs
- ICollection.cs
- RenderingBiasValidation.cs
- SqlClientPermission.cs
- RSAPKCS1KeyExchangeFormatter.cs
- _LoggingObject.cs
- CopyOnWriteList.cs
- ValueHandle.cs
- TextElementEditingBehaviorAttribute.cs
- Constants.cs
- MimePart.cs
- ImageCollectionCodeDomSerializer.cs
- TreeIterator.cs
- ToolStripContainerDesigner.cs
- KeyInterop.cs
- DataGridLengthConverter.cs
- FlowDocumentPaginator.cs
- DefaultProfileManager.cs
- StringAnimationBase.cs
- SQLGuid.cs
- SqlDuplicator.cs
- HtmlInputControl.cs
- AssemblyLoader.cs
- CursorInteropHelper.cs
- BooleanExpr.cs
- RadialGradientBrush.cs
- LoginCancelEventArgs.cs
- CheckBoxPopupAdapter.cs
- WinFormsSecurity.cs
- Geometry.cs
- SqlResolver.cs
- AnyAllSearchOperator.cs
- ViewValidator.cs
- SQLResource.cs
- SqlDataSourceConnectionPanel.cs
- ConfigXmlText.cs
- WmpBitmapDecoder.cs
- RoleServiceManager.cs
- MarkerProperties.cs
- WebPartZone.cs
- StreamSecurityUpgradeInitiatorAsyncResult.cs
- EntityViewGenerator.cs
- WebPartManager.cs
- BrowsableAttribute.cs
- DataGridViewRowHeightInfoNeededEventArgs.cs
- ArrayExtension.cs
- HtmlInputCheckBox.cs
- ListMarkerSourceInfo.cs
- ElementInit.cs
- LightweightCodeGenerator.cs
- SiteMapDataSource.cs
- AssemblyAttributes.cs
- CompositeFontInfo.cs
- DynamicExpression.cs
- CacheDependency.cs
- BackStopAuthenticationModule.cs
- ExceptionList.cs
- NetNamedPipeBinding.cs
- ScrollContentPresenter.cs
- ValidationEventArgs.cs
- TextFindEngine.cs
- RunInstallerAttribute.cs
- LogEntryHeaderv1Deserializer.cs
- DataPager.cs
- AssemblyCache.cs
- TypedCompletedAsyncResult.cs
- FilteredDataSetHelper.cs
- JsonStringDataContract.cs
- Command.cs
- FlowDocumentReaderAutomationPeer.cs
- HtmlTableCellCollection.cs
- NativeMethods.cs
- DocumentGridPage.cs
- EntityContainerEmitter.cs
- Pkcs7Recipient.cs
- Baml2006ReaderSettings.cs
- TraceContext.cs
- StrokeSerializer.cs
- DBSchemaRow.cs
- MaterialGroup.cs
- ChannelManagerService.cs
- NativeMethods.cs
- PenContext.cs
- ReferenceEqualityComparer.cs
- VisualBrush.cs
- ConfigurationPropertyAttribute.cs
- BreakRecordTable.cs
- KernelTypeValidation.cs
- StylusTip.cs
- TimeSpanMinutesConverter.cs
- IriParsingElement.cs
- CommandPlan.cs
- DesignerSerializationVisibilityAttribute.cs
- MemberMaps.cs
- TraceHwndHost.cs
- CancellationTokenSource.cs
- PolyQuadraticBezierSegment.cs