/// <summary>
 /// Decode AS Request from bytes
 /// </summary>
 /// <param name="buffer">the byte array to be decoded</param>
 /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception>
 public override void FromBytes(byte[] buffer)
 {
     if (buffer == null)
     {
         throw new ArgumentNullException("buffer");
     }
     Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(buffer);
     Request.BerDecode(decodeBuffer);
 }
        /// <summary>
        /// Decode the Krb Error from bytes
        /// </summary>
        /// <param name="buffer">The byte array to be decoded.</param>
        /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception>
        public override void FromBytes(byte[] buffer)
        {
            if (null == buffer)
            {
                throw new ArgumentNullException("buffer");
            }
            KerberosUtility.OnDumpMessage("KRB5:KrbMessage",
                "Kerberos Message",
                KerberosUtility.DumpLevel.WholeMessage,
                buffer);
            // Decode Krb Error
            Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(buffer);
            this.KrbError.BerDecode(decodeBuffer);

            ErrorCode = (KRB_ERROR_CODE)KrbError.error_code.Value;
        }
 /// <summary>
 /// Decode TGS Response from bytes
 /// </summary>
 /// <param name="buffer">byte array to be decoded</param>
 /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception>
 public override void FromBytes(byte[] buffer)
 {
     if (null == buffer)
     {
         throw new ArgumentNullException("buffer");
     }
     KerberosUtility.OnDumpMessage("KRB5:KrbMessage",
         "Kerberos Message",
         KerberosUtility.DumpLevel.WholeMessage,
         buffer);
     // Decode TGS Response
     Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(buffer);
     Response.BerDecode(decodeBuffer);
 }
        /// <summary>
        /// Decodes an LDAP v3 packet.
        /// </summary>
        /// <param name="messageBytes">The message bytes that contains the packet data.</param>
        /// <param name="context">The context that contains decode-related information.</param>
        /// <returns>Decoded LDAP v3 packet.</returns>
        internal override AdtsLdapPacket ParseAdtsLdapPacket(byte[] messageBytes, AdtsLdapContext context)
        {
            LDAPMessage message = new LDAPMessage();
            Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(messageBytes);

            message.BerDecode(decodeBuffer);

            Type innerMessageType = message.protocolOp.GetData().GetType();
            AdtsLdapPacket packet = CreatePacketFromType(innerMessageType);

            context.MessageId = (long)message.messageID.Value;
            packet.messageId = (long)message.messageID.Value;
            packet.ldapMessagev3 = message;

            return packet;
        }
        /// <summary>
        /// Decrypt the KRB-PRIV
        /// </summary>
        /// <param name="subkey">the subkey used to decrypt</param>
        public void DecryptKrbPriv(EncryptionKey subkey)
        {
            byte[] priv = KerberosUtility.Decrypt(
                      (EncryptionType)subkey.keytype.Value,
                      subkey.keyvalue.ByteArrayValue,
                      krb_priv.enc_part.cipher.ByteArrayValue,
                      (int)KeyUsageNumber.KRB_PRIV_EncPart);

            Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(priv);
            priv_enc_part.BerDecode(decodeBuffer);
        }
        /// <summary>
        /// Decode Kpassword Response from bytes
        /// </summary>
        /// <param name="buffer">the byte array to be decoded</param>
        /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception>
        public override void FromBytes(byte[] buffer)
        {
            if (null == buffer)
            {
                throw new ArgumentNullException("buffer");
            }

            //Calculate the length of the message and the length of AP response data
            byte[] msgLengthBytes = ArrayUtility.SubArray<byte>(buffer, 0, sizeof(ushort));
            Array.Reverse(msgLengthBytes);
            ushort msgLength = BitConverter.ToUInt16(msgLengthBytes, 0);

            byte[] apLengthBytes = ArrayUtility.SubArray<byte>(buffer, 2 * sizeof(ushort), sizeof(ushort));
            Array.Reverse(apLengthBytes);
            ushort apLength = BitConverter.ToUInt16(apLengthBytes, 0);

            //Decode the ap response and the krb-priv message
            byte[] apBytes = ArrayUtility.SubArray<byte>(buffer, 3 * sizeof(ushort), apLength);
            Asn1DecodingBuffer apBuffer = new Asn1DecodingBuffer(apBytes);
            this.ap_rep.Response.BerDecode(apBuffer);

            byte[] privBytes = ArrayUtility.SubArray<byte>(buffer, 3 * sizeof(ushort) + apLength);
            Asn1DecodingBuffer privBuffer = new Asn1DecodingBuffer(privBytes);
            this.krb_priv.BerDecode(privBuffer);
        }
        /// <summary>
        /// [TD Reference 3.2.5.3.4]
        /// Decode MCS Connect Response PDU with GCC Conference Create Response
        /// </summary>
        /// <param name="data">data to be parsed</param>
        /// <returns>decoded MCS Connect Response PDU with GCC Conference Create Response PDU</returns>
        public StackPacket DecodeMcsConnectResponsePDU(byte[] data)
        {
            // initialize
            int currentIndex = 0;
            Server_MCS_Connect_Response_Pdu_with_GCC_Conference_Create_Response pdu =
                new Server_MCS_Connect_Response_Pdu_with_GCC_Conference_Create_Response();

            // McsConnectResponse: TpktHeader
            pdu.tpktHeader = ParseTpktHeader(data, ref currentIndex);

            // McsConnectResponse: X224
            pdu.x224Data = ParseX224Data(data, ref currentIndex);

            // T125 Data: decode McsConnectResponse
            int t125DataLength = data.Length - currentIndex;
            if (t125DataLength <= 0)
            {
                throw new FormatException(ConstValue.ERROR_MESSAGE_DATA_INDEX_OUT_OF_RANGE);
            }
            byte[] t125Data = new byte[t125DataLength];
            Array.Copy(data, currentIndex, t125Data, 0, t125Data.Length);
            Connect_Response mcsConnectResponse = new Connect_Response();
            Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(t125Data);
            mcsConnectResponse.BerDecode(decodeBuffer);

            // McsConnectResponse:result
            pdu.mcsCrsp.result = (int)mcsConnectResponse.result.Value;
            byte[] userData = mcsConnectResponse.userData.ByteArrayValue;

            // T125 Data: decode McsConnectResponse's user data
            Asn1DecodingBuffer connectDataBuffer = new Asn1DecodingBuffer(userData);
            ConnectData connectData = new ConnectData();
            connectData.PerDecode(connectDataBuffer);

            // T125 Data: get Gcc data
            int gccDataLength = userData.Length - ConstValue.GCC_DATA_OFFSET;
            if (gccDataLength <= 0)
            {
                throw new FormatException(ConstValue.ERROR_MESSAGE_DATA_INDEX_OUT_OF_RANGE);
            }
            byte[] gccData = new byte[gccDataLength];
            Array.Copy(userData, ConstValue.GCC_DATA_OFFSET, gccData, 0, gccData.Length);

            // T125 Data: decode Gcc user data
            ConnectGCCPDU gccPdu = new ConnectGCCPDU();
            Asn1DecodingBuffer gccPduBuffer = new Asn1DecodingBuffer(gccData);
            gccPdu.PerDecode(gccPduBuffer);

            // McsConnectResponse: H221Key
            ConferenceCreateResponse conferenceResponse = (ConferenceCreateResponse)gccPdu.GetData();
            H221NonStandardIdentifier identifier =
                (H221NonStandardIdentifier)conferenceResponse.userData.Elements[0].key.GetData();
            pdu.mcsCrsp.gccPdu.H221Key = Encoding.ASCII.GetString(identifier.ByteArrayValue);

            // McsConnectResponse: ccrResult
            pdu.mcsCrsp.gccPdu.ccrResult = (int)conferenceResponse.result.Value;

            // McsConnectResponse: nodeID
            pdu.mcsCrsp.gccPdu.nodeID = (int)conferenceResponse.nodeID.Value;

            // McsConnectResponse: tag
            pdu.mcsCrsp.gccPdu.tag = (int)conferenceResponse.tag.Value;

            // T125 Data: get Gcc user data
            byte[] gccUserData = conferenceResponse.userData.Elements[0].value.ByteArrayValue;

            // Reset current index
            currentIndex = 0;
            while (currentIndex < gccUserData.Length)
            {
                // Peek data type
                int tempIndex = currentIndex;
                TS_UD_HEADER_type_Values type =
                    (TS_UD_HEADER_type_Values)ParseUInt16(gccUserData, ref tempIndex, false);

                // Parse data by type
                switch (type)
                {
                    case TS_UD_HEADER_type_Values.SC_CORE:
                        pdu.mcsCrsp.gccPdu.serverCoreData = ParseTsUdScCore(gccUserData, ref currentIndex);
                        break;

                    case TS_UD_HEADER_type_Values.SC_NET:
                        pdu.mcsCrsp.gccPdu.serverNetworkData = ParseTsUdScNet(gccUserData, ref currentIndex);
                        break;

                    case TS_UD_HEADER_type_Values.SC_SECURITY:
                        pdu.mcsCrsp.gccPdu.serverSecurityData = ParseTsUdScSec1(gccUserData, ref currentIndex);
                        break;

                    case TS_UD_HEADER_type_Values.SC_MCS_MSGCHANNEL:
                        pdu.mcsCrsp.gccPdu.serverMessageChannelData = ParseTsUdScMSGChannel(gccUserData, ref currentIndex);
                        break;

                    case TS_UD_HEADER_type_Values.SC_MULTITRANSPORT:
                        pdu.mcsCrsp.gccPdu.serverMultitransportChannelData = ParseTsUdScMultiTransport(gccUserData, ref currentIndex);
                        break;

                    default:
                        throw new FormatException(ConstValue.ERROR_MESSAGE_ENUM_UNRECOGNIZED);
                }
            }

            // Check if data length exceeded expectation
            VerifyDataLength(gccUserData.Length, currentIndex, ConstValue.ERROR_MESSAGE_DATA_LENGTH_EXCEEDED);
            return pdu;
        }
        /// <summary>
        /// Parse MCS Domain PDU
        /// (parser index is updated according to parsed length)
        /// </summary>
        /// <param name="data">data to be parsed</param>
        /// <param name="currentIndex">current parser index</param>
        /// <returns>MCS Domain PDU</returns>
        private DomainMCSPDU ParseMcsDomainPdu(byte[] data, ref int currentIndex)
        {
            // initialize decode buffer
            byte[] temp = GetBytes(data, ref currentIndex, (data.Length - currentIndex));
            Asn1DecodingBuffer buffer = new Asn1DecodingBuffer(temp);

            // decode
            DomainMCSPDU domainPdu = new DomainMCSPDU();
            domainPdu.PerDecode(buffer);
            return domainPdu;
        }
        /// <summary>
        /// Decode MCS Connect Initial PDU with GCC Conference Create Initial
        /// </summary>
        /// <param name="data">data to be parsed</param>
        /// <returns>Decoded MCS Connect Initial PDU with GCC Conference Create Initial</returns>
        public StackPacket DecodeMcsConnectInitialPDU(byte[] data)
        {
            // initialize
            int currentIndex = 0;
            Client_MCS_Connect_Initial_Pdu_with_GCC_Conference_Create_Request pdu =
                new Client_MCS_Connect_Initial_Pdu_with_GCC_Conference_Create_Request();

            // McsConnectResponse: TpktHeader
            pdu.tpktHeader = ParseTpktHeader(data, ref currentIndex);

            // McsConnectResponse: X224
            pdu.x224Data = ParseX224Data(data, ref currentIndex);

            // T125 Data: decode McsConnectResponse
            int t125DataLength = data.Length - currentIndex;
            if (t125DataLength <= 0)
            {
                throw new FormatException(ConstValue.ERROR_MESSAGE_DATA_INDEX_OUT_OF_RANGE);
            }
            byte[] t125Data = new byte[t125DataLength];
            Array.Copy(data, currentIndex, t125Data, 0, t125Data.Length);
            Connect_Initial mcsConnectInitial = new Connect_Initial();
            Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(t125Data);
            mcsConnectInitial.BerDecode(decodeBuffer);

            // McsConnectResponse:result
            pdu.mcsCi.targetParameters.maxChannelIds = (long)mcsConnectInitial.targetParameters.maxChannelIds.Value;
            pdu.mcsCi.targetParameters.maxHeight = (long)mcsConnectInitial.targetParameters.maxHeight.Value;
            pdu.mcsCi.targetParameters.maxMcsPduSize = (long)mcsConnectInitial.targetParameters.maxMCSPDUsize.Value;
            pdu.mcsCi.targetParameters.maxTokenIds = (long)mcsConnectInitial.targetParameters.maxTokenIds.Value;
            pdu.mcsCi.targetParameters.maxUserIds = (long)mcsConnectInitial.targetParameters.maxUserIds.Value;
            pdu.mcsCi.targetParameters.minThroughput = (long)mcsConnectInitial.targetParameters.minThroughput.Value;
            pdu.mcsCi.targetParameters.numPriorities = (long)mcsConnectInitial.targetParameters.numPriorities.Value;
            pdu.mcsCi.targetParameters.protocolVersion = (long)mcsConnectInitial.targetParameters.protocolVersion.Value;

            pdu.mcsCi.minimumParameters.maxChannelIds = (long)mcsConnectInitial.minimumParameters.maxChannelIds.Value;
            pdu.mcsCi.minimumParameters.maxHeight = (long)mcsConnectInitial.minimumParameters.maxHeight.Value;
            pdu.mcsCi.minimumParameters.maxMcsPduSize = (long)mcsConnectInitial.minimumParameters.maxMCSPDUsize.Value;
            pdu.mcsCi.minimumParameters.maxTokenIds = (long)mcsConnectInitial.minimumParameters.maxTokenIds.Value;
            pdu.mcsCi.minimumParameters.maxUserIds = (long)mcsConnectInitial.minimumParameters.maxUserIds.Value;
            pdu.mcsCi.minimumParameters.minThroughput = (long)mcsConnectInitial.minimumParameters.minThroughput.Value;
            pdu.mcsCi.minimumParameters.numPriorities = (long)mcsConnectInitial.minimumParameters.numPriorities.Value;
            pdu.mcsCi.minimumParameters.protocolVersion = (long)mcsConnectInitial.minimumParameters.protocolVersion.Value;

            pdu.mcsCi.maximumParameters.maxChannelIds = (long)mcsConnectInitial.maximumParameters.maxChannelIds.Value;
            pdu.mcsCi.maximumParameters.maxHeight = (long)mcsConnectInitial.maximumParameters.maxHeight.Value;
            pdu.mcsCi.maximumParameters.maxMcsPduSize = (long)mcsConnectInitial.maximumParameters.maxMCSPDUsize.Value;
            pdu.mcsCi.maximumParameters.maxTokenIds = (long)mcsConnectInitial.maximumParameters.maxTokenIds.Value;
            pdu.mcsCi.maximumParameters.maxUserIds = (long)mcsConnectInitial.maximumParameters.maxUserIds.Value;
            pdu.mcsCi.maximumParameters.minThroughput = (long)mcsConnectInitial.maximumParameters.minThroughput.Value;
            pdu.mcsCi.maximumParameters.numPriorities = (long)mcsConnectInitial.maximumParameters.numPriorities.Value;
            pdu.mcsCi.maximumParameters.protocolVersion = (long)mcsConnectInitial.maximumParameters.protocolVersion.Value;

            // T125 User Data: get McsConnectResponse's user data
            //byte[] userData = new byte[mcsConnectInitial.userData.Length];
            //Stream mscInput = mcsConnectInitial.userData.toInputStream();
            //mscInput.Read(userData, 0, userData.Length);
            byte[] userData = mcsConnectInitial.userData.ByteArrayValue;

            // T125 User Data: decode McsConnectResponse's user data
            Asn1DecodingBuffer connectDataBuffer = new Asn1DecodingBuffer(userData);
            ConnectData connectData = new ConnectData();
            connectData.PerDecode(connectDataBuffer);

            // Gcc Data: get Gcc data
            int gccDataLength = userData.Length - ConstValue.GCC_CCI_DATA_OFFSET;
            if (gccDataLength <= 0)
            {
                throw new FormatException(ConstValue.ERROR_MESSAGE_DATA_INDEX_OUT_OF_RANGE);
            }
            byte[] gccData = new byte[gccDataLength];
            Array.Copy(userData, ConstValue.GCC_CCI_DATA_OFFSET, gccData, 0, gccData.Length);

            // Gcc Data: decode Gcc data
            ConnectGCCPDU gccPdu = new ConnectGCCPDU();
            Asn1DecodingBuffer gccPduBuffer = new Asn1DecodingBuffer(gccData);
            gccPdu.PerDecode(gccPduBuffer);

            // McsConnectResponse: H221Key
            ConferenceCreateRequest conferenceRequest = (ConferenceCreateRequest)gccPdu.GetData();
            H221NonStandardIdentifier identifier =
                (H221NonStandardIdentifier)conferenceRequest.userData.Elements[0].key.GetData();
            pdu.mcsCi.gccPdu.h221Key = Encoding.ASCII.GetString(identifier.ByteArrayValue);

            // Gcc User Data: get Gcc user data
            byte[] gccUserData = conferenceRequest.userData.Elements[0].value.ByteArrayValue;

            // Reset current index
            currentIndex = 0;
            while (currentIndex < gccUserData.Length)
            {
                // Peek data type
                int tempIndex = currentIndex;
                int orgIndex = currentIndex;
                TS_UD_HEADER_type_Values type =
                    (TS_UD_HEADER_type_Values)ParseUInt16(gccUserData, ref tempIndex, false);
                ushort userDataLength = ParseUInt16(gccUserData, ref tempIndex, false);

                // Parse data by type
                switch (type)
                {
                    case TS_UD_HEADER_type_Values.CS_CORE:
                        pdu.mcsCi.gccPdu.clientCoreData = ParseTsUdCsCore(gccUserData, ref currentIndex, userDataLength);
                        break;

                    case TS_UD_HEADER_type_Values.CS_NET:
                        pdu.mcsCi.gccPdu.clientNetworkData = ParseTsUdCsNet(gccUserData, ref currentIndex);
                        break;

                    case TS_UD_HEADER_type_Values.CS_SECURITY:
                        pdu.mcsCi.gccPdu.clientSecurityData = ParseTsUdCsSec(gccUserData, ref currentIndex);
                        break;

                    case TS_UD_HEADER_type_Values.CS_CLUSTER:
                        pdu.mcsCi.gccPdu.clientClusterData = ParseTsUdCsCluster(gccUserData, ref currentIndex);
                        break;

                    case TS_UD_HEADER_type_Values.CS_MONITOR:
                        pdu.mcsCi.gccPdu.clientMonitorData = ParseTsUdCsMon(gccUserData, ref currentIndex);
                        break;

                    case TS_UD_HEADER_type_Values.CS_MCS_MSGCHANNEL:
                        pdu.mcsCi.gccPdu.clientMessageChannelData = ParseTsUdCsMcsMsgChannel(gccUserData, ref currentIndex);
                        break;

                    case TS_UD_HEADER_type_Values.CS_MULTITRANSPORT:
                        pdu.mcsCi.gccPdu.clientMultitransportChannelData = ParseTsUdCsMultiTransport(gccUserData, ref currentIndex);
                        break;

                    case TS_UD_HEADER_type_Values.CS_MONITOR_EX:
                        pdu.mcsCi.gccPdu.clientMonitorExtendedData = ParseTsUdCsMonitorEX(gccUserData, ref currentIndex);
                        break;

                    default:
                        break;
                    //throw new FormatException(ConstValue.ERROR_MESSAGE_ENUM_UNRECOGNIZED);
                }
                currentIndex = orgIndex + userDataLength;
            }

            // Check if data length exceeded expectation
            VerifyDataLength(gccUserData.Length, currentIndex, ConstValue.ERROR_MESSAGE_DATA_LENGTH_EXCEEDED);
            return pdu;
        }
        /// <summary>
        /// Expected a PreauthenticationRequired error
        /// </summary>
        /// <param name="eData">Error data of this error</param>
        /// <returns></returns>
        public KerberosKrbError ExpectPreauthRequiredError(out METHOD_DATA eData)
        {
            KerberosPdu responsePdu = this.ExpectPdu(KerberosConstValue.TIMEOUT_DEFAULT, typeof(KerberosKrbError));
            this.testSite.Assert.IsNotNull(responsePdu, "Response Pdu should not be null.");
            this.testSite.Assert.IsInstanceOfType(responsePdu, typeof(KerberosKrbError), "Response type mismatch");

            KerberosKrbError krbError = responsePdu as KerberosKrbError;
            this.testSite.Assert.AreEqual(KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED, krbError.ErrorCode, "The Error code should be KDC_ERR_PREAUTH_REQUIRED");
            this.testSite.Log.Add(LogEntryKind.Debug, "Receive preauthentication required error.");

            eData = new METHOD_DATA();
            Asn1DecodingBuffer buffer = new Asn1DecodingBuffer(krbError.KrbError.e_data.ByteArrayValue);
            eData.BerDecode(buffer);
            return krbError;
        }
 /// <summary>
 /// Decode KDCProxyMessage from bytes
 /// </summary>
 /// <param name="buffer">byte array to be decoded</param>
 /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception>
 public void FromBytes(byte[] buffer)
 {
     if (null == buffer)
     {
         throw new ArgumentNullException("buffer");
     }
     this.Message = new KDC_PROXY_MESSAGE();
     Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(buffer);
     this.Message.BerDecode(decodeBuffer);
 }
        private void UpdateContext(KerberosAsResponse response)
        {
            KerberosFastResponse kerbFastRep = null;
            if (response.Response.padata != null && response.Response.padata.Elements != null)
            {
                foreach (PA_DATA paData in response.Response.padata.Elements)
                {
                    var parsedPaData = PaDataParser.ParseRepPaData(paData);
                    if (parsedPaData is PaETypeInfo2)
                    {
                        Asn1DecodingBuffer buffer = new Asn1DecodingBuffer(paData.padata_value.ByteArrayValue);
                        ETYPE_INFO2 eTypeInfo2 = new ETYPE_INFO2();
                        eTypeInfo2.BerDecode(buffer);
                        if (eTypeInfo2.Elements != null && eTypeInfo2.Elements.Length > 0)
                        {
                            // the salt is received from KDC
                            if (eTypeInfo2.Elements[0].salt != null)
                                Context.CName.Salt = eTypeInfo2.Elements[0].salt.Value;
                            continue;
                        }
                    }
                    if (parsedPaData is PaFxFastRep)
                    {
                        var armoredRep = ((PaFxFastRep)parsedPaData).GetArmoredRep();
                        kerbFastRep = ((PaFxFastRep)parsedPaData).GetKerberosFastRep(Context.FastArmorkey);
                        var strKey = kerbFastRep.FastResponse.strengthen_key;
                        Context.ReplyKey = KerberosUtility.KrbFxCf2(
                            strKey,
                            //Fix me: should be Context.ReplyKey
                            KerberosUtility.MakeKey(Context.SelectedEType, Context.CName.Password, Context.CName.Salt),
                            "strengthenkey",
                            "replykey");
                    }
                }
            }

            if (Context.ReplyKey != null)
            {
                response.Decrypt(Context.ReplyKey.keyvalue.ByteArrayValue);
            }
            else
            {
                var encryptType = (EncryptionType)response.Response.enc_part.etype.Value;
                var key = KeyGenerator.MakeKey(encryptType, Context.CName.Password, Context.CName.Salt);
                Context.ReplyKey = new EncryptionKey(new KerbInt32((long)encryptType), new Asn1OctetString(key));
                response.Decrypt(key);
            }

            if (response.EncPart != null)
            {
                Context.SessionKey = response.EncPart.key;
            }

            if (response.Response != null)
            {
                //Response.Response.cname is not the real CName of the ticket when hide-client-names=1
                if (kerbFastRep != null && kerbFastRep.FastResponse != null && kerbFastRep.FastResponse.finished != null)
                {
                    // Windows DC is case insensitive. It may change the cname in the response, e.g. administrator -> Administrator
                    Context.CName.Name = kerbFastRep.FastResponse.finished.cname;
                    Context.Ticket = new KerberosTicket(response.Response.ticket, kerbFastRep.FastResponse.finished.cname, response.EncPart.key);
                }
                else
                {
                    // Windows DC is case insensitive. It may change the cname in the response, e.g. administrator -> Administrator
                    Context.CName.Name = response.Response.cname;
                    Context.Ticket = new KerberosTicket(response.Response.ticket, response.Response.cname, response.EncPart.key);
                }
                Context.SelectedEType = (EncryptionType)Context.Ticket.SessionKey.keytype.Value;
                if (Context.Ticket != null && Context.Ticket.Ticket.sname != null
                    && Context.Ticket.Ticket.sname.name_string != null
                    && Context.Ticket.Ticket.sname.name_string.Elements != null
                    && Context.Ticket.Ticket.sname.name_string.Elements.Length > 1)
                {
                    int count = Context.Ticket.Ticket.sname.name_string.Elements.Length;
                    Context.Realm = new Realm(Context.Ticket.Ticket.sname.name_string.Elements[count - 1].Value);
                }
            }
        }
 /// <summary>
 /// Decode AS Response from bytes
 /// </summary>
 /// <param name="buffer">the byte array to be decoded</param>
 /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception>
 public override void FromBytes(byte[] buffer)
 {
     if (null == buffer)
     {
         throw new ArgumentNullException("buffer");
     }
     KerberosUtility.OnDumpMessage("KRB5:KrbMessage",
         "Kerberos Message",
         KerberosUtility.DumpLevel.WholeMessage,
         buffer);
     // Decode AS Response
     Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(buffer);
     this.Response.BerDecode(decodeBuffer);
     // Get the current encryption type, cipher data, session key
     EncryptionType encryptType = (EncryptionType)this.Response.enc_part.etype.Value;
 }
        private void DecryptAsResponse(byte[] key)
        {
            var encryptType = (EncryptionType)Response.enc_part.etype.Value;
            int keyUsage  = (int)KeyUsageNumber.AS_REP_ENCRYPTEDPART;
            if (encryptType == EncryptionType.RC4_HMAC)
                keyUsage = (int)KeyUsageNumber.TGS_REP_encrypted_part;

            var encPartRawData = KerberosUtility.Decrypt(
                encryptType,
                key,
                Response.enc_part.cipher.ByteArrayValue,
                keyUsage);
            Asn1DecodingBuffer buf = new Asn1DecodingBuffer(encPartRawData);
            Asn1Tag tag = null;
            Asn1StandardProcedure.TagBerDecode(buf, out tag);
            //Some implementations unconditionally send an encrypted EncTGSRepPart in the field
            //regardless of whether the reply is an AS-REP or a TGS-REP.([RFC4120] Section 5.4.2)
            if (tag.TagValue == 25)  //EncAsRepPart
            {
                EncPart = new EncASRepPart();
            }
            else if (tag.TagValue == 26) //EncTgsRepPart
            {
                EncPart = new EncTGSRepPart();
            }
            else
            {
                throw new Exception("Unknown tag number");
            }
            EncPart.BerDecode(new Asn1DecodingBuffer(encPartRawData));
            KerberosUtility.OnDumpMessage("KRB5:AS-REP(enc-part)",
                "Encrypted part of AS-REP",
                KerberosUtility.DumpLevel.PartialMessage,
                encPartRawData);
        }