/// <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);
            }
        }
Esempio n. 2
0
        /// <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);
        }