//Get the expected Kerberos PDU from byte array
        private KerberosPdu getExpectedPduFromBytes(
            byte[] receivedBytes,
            out int consumedLength,
            out int expectedLength)
        {
            // initialize lengths
            consumedLength = 0;
            expectedLength = 0;

            if (null == receivedBytes || 0 == receivedBytes.Length)
            {
                return null;
            }

            // TCP has a 4 bytes length header, while UDP has not
            byte[] pduBytes = receivedBytes;

            if ((this.Context.TransportType == TransportType.TCP))
            {
                // insufficient data, needs to receive more
                if (receivedBytes.Length < sizeof(int))
                {
                    return null;
                }

                // get pdu data length
                byte[] lengthBytes = ArrayUtility.SubArray(receivedBytes, 0, sizeof(int));
                Array.Reverse(lengthBytes);
                int pduLength = BitConverter.ToInt32(lengthBytes, 0);

                // insufficient data, needs to receive more
                expectedLength = sizeof(int) + pduLength;
                if (receivedBytes.Length < expectedLength)
                {
                    return null;
                }

                // remove length header from pdu bytes
                pduBytes = ArrayUtility.SubArray<byte>(receivedBytes, sizeof(int), pduLength);
            }
            else
            {
                // UDP has no length header
                expectedLength = pduBytes.Length;
            }

            consumedLength = expectedLength;
            KerberosPdu pdu = null;

            //Get AP data in message to judge the kpassword type
            byte[] apLengthBytes = ArrayUtility.SubArray<byte>(pduBytes, 2 * sizeof(ushort), sizeof(ushort));
            Array.Reverse(apLengthBytes);
            ushort apLength = BitConverter.ToUInt16(apLengthBytes, 0);

            //If the length is zero, then the last field contains a KRB-ERROR message instead of a KRB-PRIV message.
            if (apLength == 0)
            {
                pdu = new KerberosKrbError();
                pdu.FromBytes(ArrayUtility.SubArray<byte>(pduBytes, 3 * sizeof(ushort)));
                return pdu;
            }

            // get message type
            // (the lower 5 bits indicates its message type)
            byte[] apBytes = ArrayUtility.SubArray<byte>(pduBytes, 3 * sizeof(ushort), apLength);
            MsgType kpassMsgType = (MsgType)(apBytes[0] & 0x1f);
            if (kpassMsgType == MsgType.KRB_AP_REQ)
            {
                pdu = new KpasswordRequest();
            }
            else
            {
                pdu = new KpasswordResponse();
                pdu.FromBytes(pduBytes);
            }

            return pdu;
        }
        //Get the expected Kerberos PDU from byte array
        private KerberosPdu getExpectedPduFromBytes(
            byte[] receivedBytes,
            out int consumedLength,
            out int expectedLength)
        {
            // initialize lengths
            consumedLength = 0;
            expectedLength = 0;

            if (null == receivedBytes || 0 == receivedBytes.Length)
            {
                return(null);
            }

            // TCP has a 4 bytes length header, while UDP has not
            byte[] pduBytes = receivedBytes;

            if ((this.Context.TransportType == TransportType.TCP))
            {
                // insufficient data, needs to receive more
                if (receivedBytes.Length < sizeof(int))
                {
                    return(null);
                }

                // get pdu data length
                byte[] lengthBytes = ArrayUtility.SubArray(receivedBytes, 0, sizeof(int));
                Array.Reverse(lengthBytes);
                int pduLength = BitConverter.ToInt32(lengthBytes, 0);

                // insufficient data, needs to receive more
                expectedLength = sizeof(int) + pduLength;
                if (receivedBytes.Length < expectedLength)
                {
                    return(null);
                }

                // remove length header from pdu bytes
                pduBytes = ArrayUtility.SubArray <byte>(receivedBytes, sizeof(int), pduLength);
            }
            else
            {
                // UDP has no length header
                expectedLength = pduBytes.Length;
            }

            consumedLength = expectedLength;
            KerberosPdu pdu = null;

            //Get AP data in message to judge the kpassword type
            byte[] apLengthBytes = ArrayUtility.SubArray <byte>(pduBytes, 2 * sizeof(ushort), sizeof(ushort));
            Array.Reverse(apLengthBytes);
            ushort apLength = BitConverter.ToUInt16(apLengthBytes, 0);

            //If the length is zero, then the last field contains a KRB-ERROR message instead of a KRB-PRIV message.
            if (apLength == 0)
            {
                pdu = new KerberosKrbError();
                pdu.FromBytes(ArrayUtility.SubArray <byte>(pduBytes, 3 * sizeof(ushort)));
                return(pdu);
            }

            // get message type
            // (the lower 5 bits indicates its message type)
            byte[]  apBytes      = ArrayUtility.SubArray <byte>(pduBytes, 3 * sizeof(ushort), apLength);
            MsgType kpassMsgType = (MsgType)(apBytes[0] & 0x1f);

            if (kpassMsgType == MsgType.KRB_AP_REQ)
            {
                pdu = new KpasswordRequest();
            }
            else
            {
                pdu = new KpasswordResponse();
                pdu.FromBytes(pduBytes);
            }

            return(pdu);
        }
 public ushort GetResultCode(KpasswordResponse response)
 {
     byte[] resultCodeBytes = ArrayUtility.SubArray<byte>(response.priv_enc_part.user_data.ByteArrayValue, 0, sizeof(ushort));
     Array.Reverse(resultCodeBytes);
     return BitConverter.ToUInt16(resultCodeBytes, 0);
 }