Esempio n. 1
0
        /// <summary>
        /// Read auth_verifier from binary reader.
        /// </summary>
        /// <param name="binaryReader">binary reader</param>
        /// <param name="authLength">auth_length</param>
        /// <returns>auth_varifier</returns>
        internal static auth_verifier_co_t?AuthVerifierFromBytes(
            BinaryReader binaryReader,
            ushort authLength)
        {
            if (authLength == 0)
            {
                return(null);
            }

            long currentPosition = binaryReader.BaseStream.Position;

            int fragLength           = (int)binaryReader.BaseStream.Length;
            int authVerifierStartPos = fragLength - authLength - AUTH_VERIFIER_SIZE;

            binaryReader.BaseStream.Position = authVerifierStartPos;

            auth_verifier_co_t authVerifier = new auth_verifier_co_t();

            authVerifier.auth_type       = binaryReader.ReadByte();
            authVerifier.auth_level      = binaryReader.ReadByte();
            authVerifier.auth_pad_length = binaryReader.ReadByte();
            authVerifier.auth_reserved   = binaryReader.ReadByte();
            authVerifier.auth_context_id = binaryReader.ReadUInt32();
            authVerifier.auth_value      = binaryReader.ReadBytes(authLength);

            binaryReader.BaseStream.Position
                = authVerifierStartPos - authVerifier.auth_pad_length;
            authVerifier.auth_pad = binaryReader.ReadBytes(authVerifier.auth_pad_length);

            binaryReader.BaseStream.Position = currentPosition;

            return(authVerifier);
        }
        /// <summary>
        /// Append verification_trailer to stub.
        /// </summary>
        /// <param name="verificationTrailer">verification_trailer</param>
        /// <exception cref="ArgumentNullException">Thrown when verificationTrailer is null.</exception>
        public void AppendVerificationTrailerToStub(verification_trailer_t verificationTrailer)
        {
            if (verificationTrailer == null)
            {
                throw new ArgumentNullException("verificationTrailer");
            }

            if (stub == null)
            {
                stub = new byte[0];
            }

            stub = RpceUtility.AppendVerificationTrailerToStub(stub, verificationTrailer);

            if (auth_verifier != null)
            {
                auth_verifier_co_t authVerifier = auth_verifier.Value;
                authVerifier.auth_pad_length = (byte)(
                    RpceUtility.Align(stub.Length, RpceUtility.STUB_PAD_LENGTH) - stub.Length);
                authVerifier.auth_pad = new byte[authVerifier.auth_pad_length];
                auth_verifier         = authVerifier;
            }

            SetLength();
        }
Esempio n. 3
0
        /// <summary>
        /// Encrypt stub and initial auth_token.
        /// </summary>
        public override void InitializeAuthenticationToken()
        {
            if (context.AuthenticationType == RpceAuthenticationType.RPC_C_AUTHN_NONE ||
                context.AuthenticationLevel == RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_NONE)
            {
                // AUTHN_NONE and AUTHN_LEVEL_NONE, do nothing.
                return;
            }

            FieldInfo fieldInfo = this.GetType().GetField("auth_verifier");

            if (fieldInfo == null)
            {
                // PDU has no auth_verifier field, do nothing.
                return;
            }

            auth_verifier_co_t?authVerifier = (auth_verifier_co_t?)fieldInfo.GetValue(this);

            if (authVerifier == null)
            {
                // PDU has no auth_verifier, do nothing.
                return;
            }

            if (PTYPE == RpcePacketType.Bind ||
                PTYPE == RpcePacketType.AlterContext ||
                PTYPE == RpcePacketType.Auth3)
            {
                //Bind PDU, First call to GSS_Init_sec_context, as specified in [RFC2743] section 2.2.1.
                //alter_context, rpc_auth_3, Second and subsequent calls to GSS_Init_sec_context,
                //as specified in [RFC2743] section 2.2.1.
                auth_verifier_co_t newAuthVerifier = authVerifier.Value;
                newAuthVerifier.auth_value = context.SecurityContext.Token;
                authVerifier = newAuthVerifier;
            }
            else if (PTYPE == RpcePacketType.BindAck ||
                     PTYPE == RpcePacketType.AlterContextResp)
            {
                auth_verifier_co_t newAuthVerifier = authVerifier.Value;
                newAuthVerifier.auth_value = context.SecurityContext.Token;
                authVerifier = newAuthVerifier;
            }
            else if (context.AuthenticationLevel != RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_DEFAULT &&
                     context.AuthenticationLevel != RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_CONNECT)
            {
                auth_verifier_co_t newAuthVerifier = authVerifier.Value;
                EncryptAndSign(ref newAuthVerifier);
                authVerifier = newAuthVerifier;
            }

            // set it back to PDU.
            fieldInfo.SetValue(this, authVerifier);
        }
        /// <summary>
        /// Encrypt and sign to get auth_token.
        /// </summary>
        /// <param name="authVerifier">auth_verifier, not null.</param>
        private void EncryptAndSign(ref auth_verifier_co_t authVerifier)
        {
            //Request, Response, Fault
            //Get stub, pad the length to a multiple of 4 bytes.
            byte[] stub = GetStub();
            if (stub == null)
            {
                stub = new byte[0];
                SetStub(stub);
            }

            //Get SecurityBuffers.
            int stubSecBufIndex;
            int tokenSecBufIndex;
            SecurityBufferType readonlyFlag;
            List<SecurityBuffer> securityBufferList = new List<SecurityBuffer>();
            if (context.SupportsHeaderSign)
            {
                readonlyFlag = SecurityBufferType.ReadOnlyWithChecksum;
            }
            else
            {
                readonlyFlag = SecurityBufferType.ReadOnly;
            }
            int headerSize = GetSize();
            byte[] buf = new byte[
                headerSize
                + stub.Length
                + RpceUtility.AuthVerifierGetSize(authVerifier)];
            using (BinaryWriter binaryWriter = new BinaryWriter(new MemoryStream(buf)))
            {
                ToBytes(binaryWriter);
            }

            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data | readonlyFlag,
                    ArrayUtility.SubArray(buf, 0, headerSize)));
            stubSecBufIndex = securityBufferList.Count;
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data,
                    ArrayUtility.ConcatenateArrays(stub, authVerifier.auth_pad)));
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data | readonlyFlag,
                    ArrayUtility.SubArray(
                        buf,
                        headerSize + stub.Length + authVerifier.auth_pad_length,
                        RpceUtility.AUTH_VERIFIER_SIZE))); //8 == length of auth_verifier
            tokenSecBufIndex = securityBufferList.Count;
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Token,
                    authVerifier.auth_value));
            SecurityBuffer[] securityBuffers = securityBufferList.ToArray();

            //encrypt and sign
            switch (context.AuthenticationLevel)
            {
                case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_CALL: //Same as RPC_C_AUTHN_LEVEL_PKT
                case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT:
                    //the field "checksum" is the checksum value returned
                    //by the underlying security service in response to
                    //an integrity protection call
                    context.SecurityContext.Sign(securityBuffers);
                    authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer;
                    break;

                case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:
                    //the field "checksum" is the checksum value returned
                    //by the underlying security service in response to
                    //an integrity protection call
                    context.SecurityContext.Sign(securityBuffers);
                    authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer;
                    break;

                case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
                    //This level of service provides strong integrity protection for the
                    //entire PDU, plus privacy protection for the body data only.
                    //Therefore, only the bodies of the request, response and fault PDUs
                    //are encrypted.
                    context.SecurityContext.Encrypt(securityBuffers);
                    authVerifier.auth_pad = ArrayUtility.SubArray(securityBuffers[stubSecBufIndex].Buffer, stub.Length);
                    authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer;
                    stub = ArrayUtility.SubArray(securityBuffers[stubSecBufIndex].Buffer, 0, stub.Length);
                    SetStub(stub);
                    break;

                //default do nothing.
            }

            //A client or a server that (during composing of a PDU) has allocated more space for
            //the authentication token than the security provider fills in SHOULD<36> fill in
            //the rest of the allocated space with zero octets. These zero octets are still
            //considered to belong to the authentication token part of the PDU.
            int padLength = (int)auth_length - authVerifier.auth_value.Length;
            if (padLength < 0)
            {
                throw new InvalidOperationException("Length of calculated auth_value is incorrect.");
            }
            else if (padLength > 0)
            {
                authVerifier.auth_value = ArrayUtility.ConcatenateArrays(authVerifier.auth_value, new byte[padLength]);
            }
        }
        /// <summary>
        /// Decrypt and verify auth_token.
        /// </summary>
        /// <param name="authVerifier">auth_verifier, not null.</param>
        /// <returns>true if verify success; otherwise, false.</returns>
        private bool DecryptAndVerify(ref auth_verifier_co_t authVerifier)
        {
            bool result;

            //Just get the stub, no padding.
            byte[] stub = GetStub();
            if (stub == null)
            {
                stub = new byte[0];
                SetStub(stub);
            }

            //Get SecurityBuffers.
            int stubSecBufIndex;
            SecurityBufferType readonlyFlag;
            List<SecurityBuffer> securityBufferList = new List<SecurityBuffer>();
            if (context.SupportsHeaderSign)
            {
                readonlyFlag = SecurityBufferType.ReadOnlyWithChecksum;
            }
            else
            {
                readonlyFlag = SecurityBufferType.ReadOnly;
            }
            int headerSize = GetSize();
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data | readonlyFlag,
                    ArrayUtility.SubArray(PacketBytes, 0, headerSize)));
            stubSecBufIndex = securityBufferList.Count;
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data,
                    ArrayUtility.SubArray(
                        PacketBytes,
                        headerSize,
                        stub.Length + authVerifier.auth_pad_length)));
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data | readonlyFlag,
                    ArrayUtility.SubArray(
                        PacketBytes,
                        headerSize + stub.Length + authVerifier.auth_pad_length,
                        RpceUtility.AUTH_VERIFIER_SIZE)));
            securityBufferList.Add(
                new SecurityBuffer(SecurityBufferType.Token, authVerifier.auth_value));
            SecurityBuffer[] securityBuffers = securityBufferList.ToArray();

            //decrypt and validate
            switch (context.AuthenticationLevel)
            {
                case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_CALL: //Same as RPC_C_AUTHN_LEVEL_PKT
                case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT:
                    //the field "checksum" is the checksum value returned
                    //by the underlying security service in response to
                    //an integrity protection call
                    result = context.SecurityContext.Verify(securityBuffers);
                    break;

                case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:
                    //the field "checksum" is the checksum value returned
                    //by the underlying security service in response to
                    //an integrity protection call
                    result = context.SecurityContext.Verify(securityBuffers);
                    break;

                case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
                    //This level of service provides strong integrity protection for the
                    //entire PDU, plus privacy protection for the body data only.
                    //Therefore, only the bodies of the request, response and fault PDUs
                    //are encrypted.
                    result = context.SecurityContext.Decrypt(securityBuffers);
                    authVerifier.auth_pad = ArrayUtility.SubArray(
                        securityBuffers[stubSecBufIndex].Buffer,
                        stub.Length);
                    stub = ArrayUtility.SubArray(
                        securityBuffers[stubSecBufIndex].Buffer,
                        0,
                        stub.Length);
                    SetStub(stub);
                    break;

                default:
                    //do nothing.
                    result = false;
                    break;
            }

            return result;
        }
Esempio n. 6
0
        /// <summary>
        /// Create an instance of auth_verifier_co_t.
        /// </summary>
        /// <param name="packetType">PTYPE</param>
        /// <param name="stubLength">stub length</param>
        /// <param name="securityContext">security context</param>
        /// <param name="type">auth_type</param>
        /// <param name="level">auth_level</param>
        /// <param name="contextId">auth_context_id</param>
        /// <returns>an auth_verifier_co_t instance.</returns>
        internal static auth_verifier_co_t?AuthVerifierCreateInstance(
            RpcePacketType packetType,
            int stubLength,
            SecurityContext securityContext,
            RpceAuthenticationType type,
            RpceAuthenticationLevel level,
            uint contextId)
        {
            if (type == RpceAuthenticationType.RPC_C_AUTHN_NONE ||
                level == RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_NONE)
            {
                return(null);
            }

            if (level <= RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_CONNECT)
            {
                if (packetType != RpcePacketType.Bind &&
                    packetType != RpcePacketType.BindAck &&
                    packetType != RpcePacketType.BindNak &&
                    packetType != RpcePacketType.AlterContext &&
                    packetType != RpcePacketType.AlterContextResp &&
                    packetType != RpcePacketType.Auth3)
                {
                    return(null);
                }
            }

            //The authentication verifier is never present in bind_nak and shutdown PDUs
            if (packetType == RpcePacketType.BindNak ||
                packetType == RpcePacketType.Shutdown)
            {
                return(null);
            }

            auth_verifier_co_t authVerifier = new auth_verifier_co_t();

            //The sec_trailer structure MUST be 4-byte aligned with respect
            //to the beginning of the PDU. Padding octets MUST be used to
            //align the sec_trailer structure if its natural beginning is not
            //already 4-byte aligned.
            authVerifier.auth_pad_length = (byte)(Align(stubLength, STUB_PAD_LENGTH) - stubLength);
            authVerifier.auth_pad        = new byte[authVerifier.auth_pad_length];

            authVerifier.auth_type       = (byte)type;
            authVerifier.auth_level      = (byte)level;
            authVerifier.auth_reserved   = 0;
            authVerifier.auth_context_id = contextId;

            if (securityContext != null)
            {
                if (packetType == RpcePacketType.Bind ||
                    packetType == RpcePacketType.BindAck ||
                    packetType == RpcePacketType.AlterContext ||
                    packetType == RpcePacketType.AlterContextResp ||
                    packetType == RpcePacketType.Auth3)
                {
                    authVerifier.auth_value = securityContext.Token;
                }
                else if (level == RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
                {
                    int authValueSize = Align(
                        (int)securityContext.ContextSizes.SecurityTrailerSize,
                        STUB_PAD_LENGTH);
                    authVerifier.auth_value = new byte[authValueSize];
                }
                else
                {
                    // level == RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_INTEGRITY ||
                    // level == RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT ||
                    // level == RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_CALL
                    int authValueSize = Align(
                        (int)securityContext.ContextSizes.MaxSignatureSize,
                        STUB_PAD_LENGTH);
                    authVerifier.auth_value = new byte[authValueSize];
                }
            }

            return(authVerifier);
        }
Esempio n. 7
0
        /// <summary>
        /// Encrypt and sign to get auth_token.
        /// </summary>
        /// <param name="authVerifier">auth_verifier, not null.</param>
        private void EncryptAndSign(ref auth_verifier_co_t authVerifier)
        {
            //Request, Response, Fault
            //Get stub, pad the length to a multiple of 4 bytes.
            byte[] stub = GetStub();
            if (stub == null)
            {
                stub = new byte[0];
                SetStub(stub);
            }

            //Get SecurityBuffers.
            int stubSecBufIndex;
            int tokenSecBufIndex;
            SecurityBufferType    readonlyFlag;
            List <SecurityBuffer> securityBufferList = new List <SecurityBuffer>();

            if (context.SupportsHeaderSign)
            {
                readonlyFlag = SecurityBufferType.ReadOnlyWithChecksum;
            }
            else
            {
                readonlyFlag = SecurityBufferType.ReadOnly;
            }
            int headerSize = GetSize();

            byte[] buf = new byte[
                headerSize
                + stub.Length
                + RpceUtility.AuthVerifierGetSize(authVerifier)];
            using (BinaryWriter binaryWriter = new BinaryWriter(new MemoryStream(buf)))
            {
                ToBytes(binaryWriter);
            }

            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data | readonlyFlag,
                    ArrayUtility.SubArray(buf, 0, headerSize)));
            stubSecBufIndex = securityBufferList.Count;
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data,
                    ArrayUtility.ConcatenateArrays(stub, authVerifier.auth_pad)));
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data | readonlyFlag,
                    ArrayUtility.SubArray(
                        buf,
                        headerSize + stub.Length + authVerifier.auth_pad_length,
                        RpceUtility.AUTH_VERIFIER_SIZE))); //8 == length of auth_verifier
            tokenSecBufIndex = securityBufferList.Count;
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Token,
                    authVerifier.auth_value));
            SecurityBuffer[] securityBuffers = securityBufferList.ToArray();

            //encrypt and sign
            switch (context.AuthenticationLevel)
            {
            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_CALL:     //Same as RPC_C_AUTHN_LEVEL_PKT
            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT:
                //the field "checksum" is the checksum value returned
                //by the underlying security service in response to
                //an integrity protection call
                context.SecurityContext.Sign(securityBuffers);
                authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer;
                break;

            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:
                //the field "checksum" is the checksum value returned
                //by the underlying security service in response to
                //an integrity protection call
                context.SecurityContext.Sign(securityBuffers);
                authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer;
                break;

            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
                //This level of service provides strong integrity protection for the
                //entire PDU, plus privacy protection for the body data only.
                //Therefore, only the bodies of the request, response and fault PDUs
                //are encrypted.
                context.SecurityContext.Encrypt(securityBuffers);
                authVerifier.auth_pad   = ArrayUtility.SubArray(securityBuffers[stubSecBufIndex].Buffer, stub.Length);
                authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer;
                stub = ArrayUtility.SubArray(securityBuffers[stubSecBufIndex].Buffer, 0, stub.Length);
                SetStub(stub);
                break;

                //default do nothing.
            }

            //A client or a server that (during composing of a PDU) has allocated more space for
            //the authentication token than the security provider fills in SHOULD<36> fill in
            //the rest of the allocated space with zero octets. These zero octets are still
            //considered to belong to the authentication token part of the PDU.
            int padLength = (int)auth_length - authVerifier.auth_value.Length;

            if (padLength < 0)
            {
                throw new InvalidOperationException("Length of calculated auth_value is incorrect.");
            }
            else if (padLength > 0)
            {
                authVerifier.auth_value = ArrayUtility.ConcatenateArrays(authVerifier.auth_value, new byte[padLength]);
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Decrypt and verify auth_token.
        /// </summary>
        /// <param name="authVerifier">auth_verifier, not null.</param>
        /// <returns>true if verify success; otherwise, false.</returns>
        private bool DecryptAndVerify(ref auth_verifier_co_t authVerifier)
        {
            bool result;

            //Just get the stub, no padding.
            byte[] stub = GetStub();
            if (stub == null)
            {
                stub = new byte[0];
                SetStub(stub);
            }

            //Get SecurityBuffers.
            int stubSecBufIndex;
            SecurityBufferType    readonlyFlag;
            List <SecurityBuffer> securityBufferList = new List <SecurityBuffer>();

            if (context.SupportsHeaderSign)
            {
                readonlyFlag = SecurityBufferType.ReadOnlyWithChecksum;
            }
            else
            {
                readonlyFlag = SecurityBufferType.ReadOnly;
            }
            int headerSize = GetSize();

            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data | readonlyFlag,
                    ArrayUtility.SubArray(PacketBytes, 0, headerSize)));
            stubSecBufIndex = securityBufferList.Count;
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data,
                    ArrayUtility.SubArray(
                        PacketBytes,
                        headerSize,
                        stub.Length + authVerifier.auth_pad_length)));
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data | readonlyFlag,
                    ArrayUtility.SubArray(
                        PacketBytes,
                        headerSize + stub.Length + authVerifier.auth_pad_length,
                        RpceUtility.AUTH_VERIFIER_SIZE)));
            securityBufferList.Add(
                new SecurityBuffer(SecurityBufferType.Token, authVerifier.auth_value));
            SecurityBuffer[] securityBuffers = securityBufferList.ToArray();

            //decrypt and validate
            switch (context.AuthenticationLevel)
            {
            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_CALL:     //Same as RPC_C_AUTHN_LEVEL_PKT
            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT:
                //the field "checksum" is the checksum value returned
                //by the underlying security service in response to
                //an integrity protection call
                result = context.SecurityContext.Verify(securityBuffers);
                break;

            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:
                //the field "checksum" is the checksum value returned
                //by the underlying security service in response to
                //an integrity protection call
                result = context.SecurityContext.Verify(securityBuffers);
                break;

            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
                //This level of service provides strong integrity protection for the
                //entire PDU, plus privacy protection for the body data only.
                //Therefore, only the bodies of the request, response and fault PDUs
                //are encrypted.
                result = context.SecurityContext.Decrypt(securityBuffers);
                authVerifier.auth_pad = ArrayUtility.SubArray(
                    securityBuffers[stubSecBufIndex].Buffer,
                    stub.Length);
                stub = ArrayUtility.SubArray(
                    securityBuffers[stubSecBufIndex].Buffer,
                    0,
                    stub.Length);
                SetStub(stub);
                break;

            default:
                //do nothing.
                result = false;
                break;
            }

            return(result);
        }
Esempio n. 9
0
        /// <summary>
        /// Decrypt stub and validate auth_token.
        /// </summary>
        public override bool ValidateAuthenticationToken()
        {
            FieldInfo fieldInfo = this.GetType().GetField("auth_verifier");

            if (fieldInfo == null)
            {
                // PDU has no auth_verifier field, do nothing.
                return(true);
            }

            auth_verifier_co_t?authVerifier = (auth_verifier_co_t?)fieldInfo.GetValue(this);

            if (authVerifier == null)
            {
                // PDU has no auth_verifier, do nothing.
                return(true);
            }

            if (authVerifier.Value.auth_type != (byte)context.AuthenticationType ||
                authVerifier.Value.auth_level != (byte)context.AuthenticationLevel ||
                authVerifier.Value.auth_context_id != context.AuthenticationContextId)
            {
                //SecurityProvider in context is not the right SSPI to decrypt and validate the PDU.
                return(false);
            }

            bool result = true;

            if (PTYPE == RpcePacketType.Bind ||
                PTYPE == RpcePacketType.AlterContext ||
                PTYPE == RpcePacketType.Auth3)
            {
                ServerSecurityContext serverSspi = context.SecurityContext as ServerSecurityContext;
                if (serverSspi != null)
                {
                    // Accept or Initialize should throw exception when token is incorrect.
                    serverSspi.Accept(authVerifier.Value.auth_value);
                    securityContextNeedContinueProcessing = serverSspi.NeedContinueProcessing;
                }
            }
            else if (PTYPE == RpcePacketType.BindAck ||
                     PTYPE == RpcePacketType.AlterContextResp)
            {
                ClientSecurityContext clientSspi = context.SecurityContext as ClientSecurityContext;
                if (clientSspi != null)
                {
                    //BindAck only received on client.
                    clientSspi.Initialize(authVerifier.Value.auth_value);
                    securityContextNeedContinueProcessing = clientSspi.NeedContinueProcessing;
                }
            }
            else if (context.AuthenticationLevel != RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_DEFAULT &&
                     context.AuthenticationLevel != RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_CONNECT)
            {
                auth_verifier_co_t newAuthVerifier = authVerifier.Value;
                result       = DecryptAndVerify(ref newAuthVerifier);
                authVerifier = newAuthVerifier;
            }

            return(result);
        }