// // 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); }