/// <summary> /// Constructs an instance of the SecuritySession_ZpaServer class. /// </summary> /// <param name="name">Name of the SecuritySession being created.</param> /// <param name="remote">The remote host.</param> /// <param name="keyProvider_ZpaServer">The server key provider.</param> public SecuritySession_ZpaServer(string name, HostInformation remote, KeyProvider_ZpaServer keyProvider_ZpaServer) : base(name, remote, keyProvider_ZpaServer.ZpaFeatureFlags) { this.KeyProvider_ZpaServer = keyProvider_ZpaServer; Random random = new Random(); this.Salt = ZeroProofAuthorizationUtility.GenerateArbitrarySequence(128 + random.Next(128)); }
/// <summary> /// Creates and returns a stream containing decrypted data. /// </summary> /// <param name="input">A stream containing encrypted data.</param> /// <returns>A stream with decrypted data.</returns> public override Stream Decrypt(Stream input) { // check on view whether it's session's packet if (input.ReadByte() == 0) { // continue the Security Session establishing Stream outputStream = this.EstablishSession(input, false); if (outputStream != null) { GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.SendMessage), outputStream, false); } return(null); } lock (this) { GenuineChunkedStream output = new GenuineChunkedStream(false); byte[] sign = null; int signSize = 0; if (this.KeyedHashAlgorithm != null) { signSize = this.KeyedHashAlgorithm.HashSize / 8; } // decrypt the content and fetch the sign if (this._decryptor != null) { CryptoStream cryptoStream = new CryptoStream(new FinishReadingStream(output), this._decryptor, CryptoStreamMode.Write); sign = GenuineUtility.CopyStreamToStreamExceptSign(input, cryptoStream, signSize); cryptoStream.FlushFinalBlock(); } else { sign = GenuineUtility.CopyStreamToStreamExceptSign(input, output, signSize); } // check the sign if (this.KeyedHashAlgorithm != null) { if (!ZeroProofAuthorizationUtility.CompareBuffers(sign, this.KeyedHashAlgorithm.ComputeHash(output), sign.Length)) { throw GenuineExceptions.Get_Security_WrongSignature(); } output.Position = 0; } output.ReleaseOnReadMode = true; return(output); } }
/// <summary> /// Sets up all security stuff for encrypting content and checking integrity. /// </summary> /// <param name="password">The password.</param> protected void SetupSecurityAlgorithms(string password) { lock (this) { if ((this.ZpaFeatureFlags & ZpaFeatureFlags.ElectronicCodebookEncryption) != 0 || (this.ZpaFeatureFlags & ZpaFeatureFlags.CipherBlockChainingEncryption) != 0) { // encryption this.SymmetricAlgorithm = Rijndael.Create(); this.SymmetricAlgorithm.Key = ZeroProofAuthorizationUtility.GeneratePasswordBasedSequence("Key" + password, this.Salt, 32); this.SymmetricAlgorithm.IV = ZeroProofAuthorizationUtility.GeneratePasswordBasedSequence("IV" + password, this.Salt, 16); this.SymmetricAlgorithm.Mode = (this.ZpaFeatureFlags & ZpaFeatureFlags.ElectronicCodebookEncryption) != 0 ? CipherMode.ECB : CipherMode.CBC; this._encryptor = this.SymmetricAlgorithm.CreateEncryptor(); this._decryptor = this.SymmetricAlgorithm.CreateDecryptor(); } // and integrity checking if ((this.ZpaFeatureFlags & ZpaFeatureFlags.Mac3DesCbcSigning) != 0) { this.KeyedHashAlgorithm = MACTripleDES.Create(); } if ((this.ZpaFeatureFlags & ZpaFeatureFlags.HmacSha1Signing) != 0) { this.KeyedHashAlgorithm = HMACSHA1.Create(); } if (this.KeyedHashAlgorithm != null) { this.KeyedHashAlgorithm.Key = ZeroProofAuthorizationUtility.GeneratePasswordBasedSequence("M3D" + password, this.Salt, 24); } // LOG: BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; if (binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0) { binaryLogWriter.WriteEvent(LogCategory.Security, "SecuritySession_BaseZpaSession.SetupSecurityAlgorithms", LogMessageType.SecuritySessionKey, null, null, this.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, this, this.Name, -1, 0, 0, 0, string.Format("Zero Proof Authorization Flags: {0} Encryption: {1} Data Integrity: {2}", Enum.Format(typeof(ZpaFeatureFlags), this.ZpaFeatureFlags, "g"), this.SymmetricAlgorithm == null ? "No" : this.SymmetricAlgorithm.GetType().ToString(), this.KeyedHashAlgorithm == null ? "No" : this.KeyedHashAlgorithm.GetType().ToString()), null, null, null, "Security Session security information is initialized."); } } }
/// <summary> /// Initiates or continues establishing of the Security Session. /// </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) { BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; 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) { ZpaPacketStatusFlag zpaPacketStatusFlag; if (input == Stream.Null) { zpaPacketStatusFlag = ZpaPacketStatusFlag.ForceInitialization; } else { zpaPacketStatusFlag = (ZpaPacketStatusFlag)input.ReadByte(); } // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0) { binaryLogWriter.WriteEvent(LogCategory.Security, "SecuritySession_ZpaServer.EstablishSession", LogMessageType.SecuritySessionEstablishing, null, null, this.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, this, this.Name, -1, 0, 0, 0, Enum.Format(typeof(ZpaPacketStatusFlag), zpaPacketStatusFlag, "g"), null, null, null, "ZPA Server Session is being established. Status: {0}.", Enum.Format(typeof(ZpaPacketStatusFlag), zpaPacketStatusFlag, "g")); } switch (zpaPacketStatusFlag) { case ZpaPacketStatusFlag.ExceptionThrown: Exception receivedException = GenuineUtility.ReadException(input); #if DEBUG // this.Remote.ITransportContext.IEventLogger.Log(LogMessageCategory.Security, receivedException, "SecuritySession_ZpaServer.EstablishSession", // null, "Zero Proof Authorization ends up with an exception at the remote host. Remote host: {0}.", // this.Remote.ToString()); #endif this.Remote.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs( GenuineEventType.SecuritySessionFailed, receivedException, this.Remote, this)); this.DispatchException(receivedException); passException = true; throw receivedException; case ZpaPacketStatusFlag.ForceInitialization: // send the sault to the remote host binaryWriter.Write((byte)ZpaPacketStatusFlag.Salt); binaryFormatter.Serialize(outputStream, this.Salt); return(outputStream); case ZpaPacketStatusFlag.HashedPassword: // the the password this._login = binaryFormatter.Deserialize(input); string password = this.KeyProvider_ZpaServer.IAuthorizationManager.GetPassword(this._login); // and check on the hash byte[] calculatedHash = (byte[])binaryFormatter.Deserialize(input); byte[] expectedHash = ZeroProofAuthorizationUtility.CalculateDefaultKeyedHash(password, this.Salt); if (!ZeroProofAuthorizationUtility.CompareBuffers(calculatedHash, expectedHash, expectedHash.Length)) { throw GenuineExceptions.Get_Security_PasswordKnowledgeIsNotProved(); } // ok the hash is correct. Complete the authorization this.SetupSecurityAlgorithms(password); this.SessionEstablished(); binaryWriter.Write((byte)ZpaPacketStatusFlag.SessionEstablished); return(outputStream); case ZpaPacketStatusFlag.Salt: case ZpaPacketStatusFlag.SessionEstablished: throw GenuineExceptions.Get_Processing_LogicError( string.Format("The remote host must have the Security Session of the type SecuritySession_ZpaServer registered with the name {0}. SecuritySession_ZpaServer never sends {1} packet marker.", this.Name, Enum.GetName(typeof(ZpaPacketStatusFlag), zpaPacketStatusFlag))); } } } 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)ZpaPacketStatusFlag.ExceptionThrown); binaryFormatter.Serialize(outputStream, opEx); return(outputStream); } return(null); }