public static QueryContextAttributes ( System.Net.Security.SSPIInterface secModule, SafeDeleteContext securityContext, System.Net.Interop contextAttribute ) : object | ||
secModule | System.Net.Security.SSPIInterface | |
securityContext | SafeDeleteContext | |
contextAttribute | System.Net.Interop | |
리턴 | object |
public static void QueryContextStreamSizes(SafeDeleteContext securityContext, out StreamSizes streamSizes) { streamSizes = SSPIWrapper.QueryContextAttributes( GlobalSSPI.SSPISecureChannel, securityContext, Interop.SspiCli.ContextAttribute.StreamSizes) as StreamSizes; }
public static void QueryContextConnectionInfo(SafeDeleteContext securityContext, out SslConnectionInfo connectionInfo) { connectionInfo = SSPIWrapper.QueryContextAttributes( GlobalSSPI.SSPISecureChannel, securityContext, Interop.SspiCli.ContextAttribute.ConnectionInfo) as SslConnectionInfo; }
// // Used only by client SSL code, never returns null. // internal static string[] GetRequestCertificateAuthorities(SafeDeleteContext securityContext) { Interop.SspiCli.IssuerListInfoEx issuerList = (Interop.SspiCli.IssuerListInfoEx)SSPIWrapper.QueryContextAttributes( GlobalSSPI.SSPISecureChannel, securityContext, Interop.SspiCli.ContextAttribute.IssuerListInfoEx); string[] issuers = Array.Empty <string>(); try { if (issuerList.cIssuers > 0) { unsafe { uint count = issuerList.cIssuers; issuers = new string[issuerList.cIssuers]; Interop.SspiCli._CERT_CHAIN_ELEMENT *pIL = (Interop.SspiCli._CERT_CHAIN_ELEMENT *)issuerList.aIssuers.DangerousGetHandle(); for (int i = 0; i < count; ++i) { Interop.SspiCli._CERT_CHAIN_ELEMENT *pIL2 = pIL + i; if (GlobalLog.IsEnabled && pIL2->cbSize <= 0) { GlobalLog.Assert("SecureChannel::GetIssuers()", "Interop.SspiCli._CERT_CHAIN_ELEMENT size is not positive: " + pIL2->cbSize.ToString()); } if (pIL2->cbSize > 0) { uint size = pIL2->cbSize; byte * ptr = (byte *)(pIL2->pCertContext); byte[] x = new byte[size]; for (int j = 0; j < size; j++) { x[j] = *(ptr + j); } X500DistinguishedName x500DistinguishedName = new X500DistinguishedName(x); issuers[i] = x500DistinguishedName.Name; if (GlobalLog.IsEnabled) { GlobalLog.Print("SecureChannel#" + LoggingHash.HashString(securityContext) + "::GetIssuers() IssuerListEx[" + i + "]:" + issuers[i]); } } } } } } finally { if (issuerList.aIssuers != null) { issuerList.aIssuers.Dispose(); } } return(issuers); }
// // Used only by client SSL code, never returns null. // internal static string[] GetRequestCertificateAuthorities(SafeDeleteContext securityContext) { Interop.SspiCli.SecPkgContext_IssuerListInfoEx issuerList = (Interop.SspiCli.SecPkgContext_IssuerListInfoEx)SSPIWrapper.QueryContextAttributes( GlobalSSPI.SSPISecureChannel, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_ISSUER_LIST_EX); string[] issuers = Array.Empty <string>(); try { if (issuerList.cIssuers > 0) { unsafe { uint count = issuerList.cIssuers; issuers = new string[issuerList.cIssuers]; Interop.SspiCli.CERT_CHAIN_ELEMENT *pIL = (Interop.SspiCli.CERT_CHAIN_ELEMENT *)issuerList.aIssuers.DangerousGetHandle(); for (int i = 0; i < count; ++i) { Interop.SspiCli.CERT_CHAIN_ELEMENT *pIL2 = pIL + i; if (pIL2->cbSize <= 0) { NetEventSource.Fail(securityContext, $"Interop.SspiCli._CERT_CHAIN_ELEMENT size is not positive: {pIL2->cbSize}"); } if (pIL2->cbSize > 0) { uint size = pIL2->cbSize; byte * ptr = (byte *)(pIL2->pCertContext); byte[] x = new byte[size]; for (int j = 0; j < size; j++) { x[j] = *(ptr + j); } X500DistinguishedName x500DistinguishedName = new X500DistinguishedName(x); issuers[i] = x500DistinguishedName.Name; if (NetEventSource.IsEnabled) { NetEventSource.Info(securityContext, "IssuerListEx[{issuers[i]}]"); } } } } } } finally { if (issuerList.aIssuers != null) { issuerList.aIssuers.Dispose(); } } return(issuers); }
private string GetClientSpecifiedSpn() { if ((IsValidContext && IsCompleted) && GlobalLog.IsEnabled) { GlobalLog.Assert("NTAuthentication: Trying to get the client SPN before handshaking is done!"); } string spn = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, _securityContext, Interop.SspiCli.ContextAttribute.ClientSpecifiedSpn) as string; GlobalLog.Print("NTAuthentication: The client specified SPN is [" + spn + "]"); return(spn); }
// // Extracts a remote certificate upon request. // internal static X509Certificate2 GetRemoteCertificate(SafeDeleteContext securityContext, out X509Certificate2Collection remoteCertificateCollection) { remoteCertificateCollection = null; if (securityContext == null) { return(null); } if (GlobalLog.IsEnabled) { GlobalLog.Enter("CertificateValidationPal.Windows SecureChannel#" + LoggingHash.HashString(securityContext) + "::GetRemoteCertificate()"); } X509Certificate2 result = null; SafeFreeCertContext remoteContext = null; try { remoteContext = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPISecureChannel, securityContext, Interop.SspiCli.ContextAttribute.RemoteCertificate) as SafeFreeCertContext; if (remoteContext != null && !remoteContext.IsInvalid) { result = new X509Certificate2(remoteContext.DangerousGetHandle()); } } finally { if (remoteContext != null && !remoteContext.IsInvalid) { remoteCertificateCollection = UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(remoteContext); remoteContext.Dispose(); } } if (SecurityEventSource.Log.IsEnabled()) { SecurityEventSource.Log.RemoteCertificate(result == null ? "null" : result.ToString(true)); } if (GlobalLog.IsEnabled) { GlobalLog.Leave("CertificateValidationPal.Windows SecureChannel#" + LoggingHash.HashString(securityContext) + "::GetRemoteCertificate()", (result == null ? "null" : result.Subject)); } return(result); }
// // Extracts a remote certificate upon request. // internal static X509Certificate2 GetRemoteCertificate(SafeDeleteContext securityContext, out X509Certificate2Collection remoteCertificateCollection) { remoteCertificateCollection = null; if (securityContext == null) { return(null); } if (NetEventSource.IsEnabled) { NetEventSource.Enter(securityContext); } X509Certificate2 result = null; SafeFreeCertContext remoteContext = null; try { remoteContext = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPISecureChannel, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_REMOTE_CERT_CONTEXT) as SafeFreeCertContext; if (remoteContext != null && !remoteContext.IsInvalid) { result = new X509Certificate2(remoteContext.DangerousGetHandle()); } } finally { if (remoteContext != null && !remoteContext.IsInvalid) { remoteCertificateCollection = UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(remoteContext); remoteContext.Dispose(); } } if (NetEventSource.IsEnabled) { NetEventSource.Log.RemoteCertificate(result); NetEventSource.Exit(null, result, securityContext); } return(result); }
// // Extracts a remote certificate upon request. // internal static X509Certificate2 GetRemoteCertificate(SafeDeleteContext securityContext, out X509Certificate2Collection remoteCertificateStore) { remoteCertificateStore = null; if (securityContext == null) { return(null); } GlobalLog.Enter("CertificateValidationPal.Windows SecureChannel#" + Logging.HashString(securityContext) + "::GetRemoteCertificate()"); X509Certificate2 result = null; SafeFreeCertContext remoteContext = null; try { remoteContext = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPISecureChannel, securityContext, Interop.Secur32.ContextAttribute.RemoteCertificate) as SafeFreeCertContext; if (remoteContext != null && !remoteContext.IsInvalid) { result = new X509Certificate2(remoteContext.DangerousGetHandle()); } } finally { if (remoteContext != null && !remoteContext.IsInvalid) { remoteCertificateStore = UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(remoteContext); remoteContext.Dispose(); } } if (Logging.On) { Logging.PrintInfo(Logging.Web, SR.Format(SR.net_log_remote_certificate, (result == null ? "null" : result.ToString(true)))); } GlobalLog.Leave("CertificateValidationPal.Windows SecureChannel#" + Logging.HashString(securityContext) + "::GetRemoteCertificate()", (result == null ? "null" : result.Subject)); return(result); }
private string GetClientSpecifiedSpn() { return(SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, this.m_SecurityContext, ContextAttribute.ClientSpecifiedSpn) as string); }
// // for Digest, the server will send us the blob immediately, so we need to make sure we // call InitializeSecurityContext() a first time with a null input buffer, otherwise // the next call will fail. do so here: // WDigest.dll requires us to pass in 3 security buffers here // 1) BufferType: SECBUFFER_TOKEN, Content: server's challenge (incoming) // 2) BufferType: SECBUFFER_PKG_PARAMS, Content: request's HTTP Method // 3) BufferType: SECBUFFER_PKG_PARAMS, Content: the HEntity (this would be the MD5 footprint of the request entity // body, we can pass in NULL as this is not required) // public string GetOutgoingDigestBlob(string incomingBlob, string requestMethod, out bool handshakeComplete) { GlobalLog.Enter("NTAuthentication::GetOutgoingDigestBlob", incomingBlob); // // first time call with null incoming buffer to initialize. // we should get back a 0x90312 and a null outgoingBlob. // byte[] decodedOutgoingBlob = GetOutgoingBlob(null, out handshakeComplete); GlobalLog.Assert(!handshakeComplete, "NTAuthentication::GetOutgoingDigestBlob() handshakeComplete==true", ""); GlobalLog.Assert(decodedOutgoingBlob == null, "NTAuthentication::GetOutgoingDigestBlob() decodedOutgoingBlob!=null", ""); // // second time call with 3 incoming buffers to select HTTP client. // we should get back a SecurityStatus.OK and a non null outgoingBlob. // byte[] decodedIncomingBlob = Encoding.Default.GetBytes(incomingBlob); byte[] decodedRequestMethod = Encoding.Default.GetBytes(requestMethod); int requestedFlags = (int)ContextFlags.Delegate | (int)ContextFlags.MutualAuth | (int)ContextFlags.ReplayDetect | (int)ContextFlags.SequenceDetect | // (int)ContextFlags.Confidentiality | // this would only work if the server provided a qop="auth-conf" directive // (int)ContextFlags.ClientIntegrity | // this would only work if the server provided a qop="auth-int" directive (int)ContextFlags.Connection; SecurityBufferClass[] inSecurityBuffers = new SecurityBufferClass[] { new SecurityBufferClass(decodedIncomingBlob, BufferType.Token), new SecurityBufferClass(decodedRequestMethod, BufferType.Parameters), new SecurityBufferClass(null, BufferType.Parameters), }; SecurityBufferClass[] outSecurityBuffers = new SecurityBufferClass[] { new SecurityBufferClass(m_TokenSize, BufferType.Token), }; SecurityContext newSecurityContext = new SecurityContext(GlobalSSPI.SSPIAuth); // // this call is still returning an error. fix together with Kevin Damour // int status = SSPIWrapper.InitializeSecurityContext( GlobalSSPI.SSPIAuth, m_CredentialsHandle.Handle, m_SecurityContext.Handle, m_RemotePeerId, // this must match the Uri in the HTTP status line for the current request requestedFlags, m_Endianness, inSecurityBuffers, ref newSecurityContext.Handle, outSecurityBuffers, ref m_ContextFlags, ref newSecurityContext.TimeStamp); GlobalLog.Print("NTAuthentication::GetOutgoingDigestBlob() SSPIWrapper.InitializeSecurityContext() returns 0x" + string.Format("{0:x}", status)); int errorCode = status & unchecked ((int)0x80000000); if (errorCode != 0) { throw new Win32Exception(status); } // // the return value from SSPI will tell us correctly if the // handshake is over or not: http://msdn.microsoft.com/library/psdk/secspi/sspiref_67p0.htm // we also have to consider the case in which SSPI formed a new context, in this case we're done as well. // IsCompleted = (status == (int)SecurityStatus.OK) || (m_SecurityContext.Handle != -1 && m_SecurityContext.Handle != newSecurityContext.Handle); if (IsCompleted) { // ... if we're done, clean the handle up or the call to UpdateHandle() might leak it. SSPIWrapper.DeleteSecurityContext(m_SecurityContext.m_SecModule, m_SecurityContext.Handle); } handshakeComplete = IsCompleted; m_Authenticated = m_SecurityContext.Handle != -1; m_SecurityContext.UpdateHandle(newSecurityContext); #if TRAVE if (handshakeComplete) { // // Kevin Damour says: // You should not query the securitycontext until you have actually formed one ( // with a success return form ISC). It is only a partially formed context and // no info is available to user applications (at least for digest). // SecurityPackageInfoClass securityPackageInfo = (SecurityPackageInfoClass)SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, m_SecurityContext, ContextAttribute.PackageInfo); GlobalLog.Print("SecurityPackageInfoClass: using:[" + ((securityPackageInfo == null)?"null":securityPackageInfo.ToString()) + "]"); } #endif // #if TRAVE GlobalLog.Assert(outSecurityBuffers.Length == 1, "NTAuthentication::GetOutgoingDigestBlob() outSecurityBuffers.Length==" + outSecurityBuffers.Length.ToString(), ""); GlobalLog.Print("out token = " + m_TokenSize.ToString() + " size = " + outSecurityBuffers[0].size.ToString()); GlobalLog.Dump(outSecurityBuffers[0].token); GlobalLog.Print("NTAuthentication::GetOutgoingDigestBlob() handshakeComplete:" + handshakeComplete.ToString()); decodedOutgoingBlob = outSecurityBuffers[0].token; string outgoingBlob = null; if (decodedOutgoingBlob != null && decodedOutgoingBlob.Length > 0) { // CONSIDER V.NEXT // review Encoding.Default.GetString usage here because it might // end up creating non ANSI characters in the string outgoingBlob = Encoding.Default.GetString(decodedOutgoingBlob, 0, outSecurityBuffers[0].size); } GlobalLog.Leave("NTAuthentication::GetOutgoingDigestBlob", outgoingBlob); return(outgoingBlob); }
// // NTAuth::GetOutgoingBlob() // Created: 12-01-1999: L.M. // Description: // Accepts an incoming binary security blob and returns // an outgoing binary security blob // private byte[] GetOutgoingBlob(byte[] incomingBlob, out bool handshakeComplete) { GlobalLog.Enter("NTAuthentication::GetOutgoingBlob", ((incomingBlob == null) ? "0" : incomingBlob.Length.ToString()) + " bytes"); // default to true in case of failure handshakeComplete = true; if (m_SecurityContext.Handle != -1 && incomingBlob == null) { // we tried auth previously, now we got a null blob, we're done. this happens // with Kerberos & valid credentials on the domain but no ACLs on the resource // the handle for m_SecurityContext will be collected at GC time. GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingBlob() null blob AND m_SecurityContext#" + ValidationHelper.HashString(m_SecurityContext) + "::Handle:[0x" + m_SecurityContext.Handle.ToString("x8") + "]"); m_SecurityContext.Close(); IsCompleted = true; return(null); } int requestedFlags = (int)ContextFlags.Delegate | (int)ContextFlags.MutualAuth | (int)ContextFlags.ReplayDetect | (int)ContextFlags.SequenceDetect | (int)ContextFlags.Confidentiality | (int)ContextFlags.Connection; SecurityBufferClass inSecurityBuffer = null; if (incomingBlob != null) { GlobalLog.Print("in blob = "); GlobalLog.Dump(incomingBlob); inSecurityBuffer = new SecurityBufferClass(incomingBlob, BufferType.Token); } SecurityBufferClass outSecurityBuffer = new SecurityBufferClass(m_TokenSize, BufferType.Token); int status; #if SERVER_SIDE_SSPI if (m_SecureSessionType == SecureSessionType.ClientSession) { #endif // // client session // requestedFlags |= (int)ContextFlags.ClientIntegrity; status = SSPIWrapper.InitializeSecurityContext( GlobalSSPI.SSPIAuth, m_CredentialsHandle.Handle, m_SecurityContext.Handle, m_RemotePeerId, requestedFlags, m_Endianness, inSecurityBuffer, ref m_SecurityContext.Handle, outSecurityBuffer, ref m_ContextFlags, ref m_SecurityContext.TimeStamp ); GlobalLog.Print("SSPIWrapper.InitializeSecurityContext() returns 0x" + string.Format("{0:x}", status)); #if SERVER_SIDE_SSPI } else { // // server session // requestedFlags |= (int)ContextFlags.ServerIntegrity; status = SSPIWrapper.AcceptSecurityContext( GlobalSSPI.SSPIAuth, m_CredentialsHandle.Handle, m_SecurityContext.Handle, requestedFlags, m_Endianness, inSecurityBuffer, ref m_SecurityContext.Handle, outSecurityBuffer, out m_ContextFlags, out m_SecurityContext.TimeStamp ); GlobalLog.Print("SSPIWrapper.AcceptSecurityContext() returns 0x" + string.Format("{0:x}", status)); } #endif // SERVER_SIDE_SSPI int errorCode = status & unchecked ((int)0x80000000); if (errorCode != 0) { throw new Win32Exception(status); } // // the return value from SSPI will tell us correctly if the // handshake is over or not: http://msdn.microsoft.com/library/psdk/secspi/sspiref_67p0.htm // we also have to consider the case in which SSPI formed a new context, in this case we're done as well. // if (status != (int)SecurityStatus.OK && m_SecurityContext.Handle != -1) { // we need to continue GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingBlob() need continue status:[0x" + status.ToString("x8") + "] m_SecurityContext#" + ValidationHelper.HashString(m_SecurityContext) + "::Handle:[0x" + m_SecurityContext.Handle.ToString("x8") + "]"); handshakeComplete = false; } else { // we're done, cleanup GlobalLog.Assert(status == (int)SecurityStatus.OK, "NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingBlob() status:[0x" + status.ToString("x8") + "] m_SecurityContext#" + ValidationHelper.HashString(m_SecurityContext) + "::Handle:[0x" + m_SecurityContext.Handle.ToString("x8") + "]", "[STATUS != OK]"); m_SecurityContext.Close(); IsCompleted = true; } #if TRAVE if (handshakeComplete) { // // Kevin Damour says: // You should not query the securitycontext until you have actually formed one ( // with a success return form ISC). It is only a partially formed context and // no info is available to user applications (at least for digest). // SecurityPackageInfoClass securityPackageInfo = (SecurityPackageInfoClass)SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, m_SecurityContext, ContextAttribute.PackageInfo); GlobalLog.Print("SecurityPackageInfoClass: using:[" + ((securityPackageInfo == null)?"null":securityPackageInfo.ToString()) + "]"); } #endif // #if TRAVE GlobalLog.Print("out token = " + m_TokenSize.ToString()); GlobalLog.Dump(outSecurityBuffer.token); GlobalLog.Leave("NTAuthentication::GetOutgoingBlob", "handshakeComplete:" + handshakeComplete.ToString()); return(outSecurityBuffer.token); }