/// <summary> /// Sets up correct security context and invokes a target. /// This method may not throw any exceptions. /// </summary> /// <param name="message">The message to be performed.</param> /// <param name="connectionLevel">Indicates whether Security Session is used on the connection level.</param> public override void Invoke(Message message, bool connectionLevel) { bool impersonateContext = (this.KeyProvider_SspiServer.RequiredFeatures & SspiFeatureFlags.Impersonation) != 0 || (this.KeyProvider_SspiServer.RequiredFeatures & SspiFeatureFlags.Delegation) != 0; try { if (impersonateContext) { SspiApi.ImpersonateSecurityContext(this.SspiSecurityContext._phContext); } base.Invoke(message, connectionLevel); } finally { if (impersonateContext) { SspiApi.RevertSecurityContext(this.SspiSecurityContext._phContext); } } }
/// <summary> /// Initiates or continues establishing of the Security Session. /// Implementation notes: receiving of exceptions no more breaks up the connection like /// it was in the previous versions. /// </summary> /// <param name="input">A null reference or an incoming stream.</param> /// <param name="connectionLevel">Indicates whether the Security Session operates on connection level.</param> /// <returns>A stream containing data for sending to the remote host or a null reference if Security Session is established.</returns> public override GenuineChunkedStream EstablishSession(Stream input, bool connectionLevel) { bool passException = false; // a dance is over if (this.IsEstablished) { return(null); } GenuineChunkedStream outputStream = null; var binaryFormatter = new BinaryFormatter().Safe(); // skip the status flag if (connectionLevel) { if (input != null) { input.ReadByte(); } outputStream = new GenuineChunkedStream(false); } else { outputStream = this.CreateOutputStream(); } // write session is being established flag BinaryWriter binaryWriter = new BinaryWriter(outputStream); binaryWriter.Write((byte)0); try { lock (this) { if (input == Stream.Null) { if (this.KeyProvider_SspiClient.DelegatedContext != null) { try { SspiApi.ImpersonateSecurityContext(this.KeyProvider_SspiClient.DelegatedContext.SspiSecurityContext._phContext); // start new session this.SspiSecurityContext = new SspiClientSecurityContext(this.KeyProvider_SspiClient); binaryWriter.Write((byte)SspiPacketStatusFlags.InitializeFromScratch); this.SspiSecurityContext.BuildUpSecurityContext(null, outputStream); return(outputStream); } finally { SspiApi.RevertSecurityContext(this.KeyProvider_SspiClient.DelegatedContext.SspiSecurityContext._phContext); } } // start new session this.SspiSecurityContext = new SspiClientSecurityContext(this.KeyProvider_SspiClient); binaryWriter.Write((byte)SspiPacketStatusFlags.InitializeFromScratch); this.SspiSecurityContext.BuildUpSecurityContext(null, outputStream); return(outputStream); } SspiPacketStatusFlags sspiPacketStatusFlags = (SspiPacketStatusFlags)input.ReadByte(); switch (sspiPacketStatusFlags) { case SspiPacketStatusFlags.ContinueAuthentication: // continue building a security context GenuineChunkedStream sspiData = new GenuineChunkedStream(false); this.SspiSecurityContext.BuildUpSecurityContext(input, sspiData); if (sspiData.Length == 0) { // SSPI session has been built up outputStream.WriteByte((byte)SspiPacketStatusFlags.SessionEstablished); this.SessionEstablished(); } else { outputStream.WriteByte((byte)SspiPacketStatusFlags.ContinueAuthentication); outputStream.WriteStream(sspiData); } return(outputStream); case SspiPacketStatusFlags.ExceptionThrown: Exception receivedException = GenuineUtility.ReadException(input); #if DEBUG // this.Remote.ITransportContext.IEventLogger.Log(LogMessageCategory.Security, receivedException, "SecuritySession_SspiServer.EstablishSession", // null, "SSPI initialization ends up with an exception at the remote host. Remote host: {0}.", // this.Remote.ToString()); #endif if (this.Remote != null) { this.Remote.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs( GenuineEventType.SecuritySessionFailed, receivedException, this.Remote, this)); } this.DispatchException(receivedException); passException = true; throw receivedException; case SspiPacketStatusFlags.ForceInitialization: return(this.EstablishSession(Stream.Null, connectionLevel)); case SspiPacketStatusFlags.InitializeFromScratch: throw GenuineExceptions.Get_Processing_LogicError( string.Format("The remote host must have the Security Session of the type SecuritySession_SspiServer registered with the name {0}. SecuritySession_SspiServer never sends SspiPacketMark.InitializeFromScratch packet marker.", this.Name)); case SspiPacketStatusFlags.SessionEstablished: this.SessionEstablished(); break; } } } catch (Exception opEx) { #if DEBUG // this.Remote.ITransportContext.IEventLogger.Log(LogMessageCategory.Security, opEx, "SecuritySession_SspiServer.EstablishSession", // null, "Exception was thrown while establishing security context."); #endif if (this.Remote != null) { this.Remote.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs( GenuineEventType.SecuritySessionFailed, opEx, this.Remote, this)); } this.DispatchException(opEx); if (passException) { throw; } binaryWriter.Write((byte)SspiPacketStatusFlags.ExceptionThrown); binaryFormatter.Serialize(outputStream, opEx); return(outputStream); } return(null); }