/// <summary>
        /// Updated context based on Kerberos pdu
        /// </summary>
        /// <param name="pdu">Kerberos pdu</param>
        public override void UpdateContext(KerberosPdu pdu)
        {
            if (pdu is KerberosAsRequest)
            {
                KerberosAsRequest request = (KerberosAsRequest)pdu;
                UpdateContext(request);
            }
            if (pdu is KerberosKrbError)
            {
                KerberosKrbError error = (KerberosKrbError)pdu;
                UpdateContext(error);
            }
            if (pdu is KerberosAsResponse)
            {
                KerberosAsResponse response = (KerberosAsResponse)pdu;
                UpdateContext(response);
            }

            if (pdu is KerberosTgsRequest)
            {
                KerberosTgsRequest request = pdu as KerberosTgsRequest;
                UpdateContext(request);
            }

            if (pdu is KerberosTgsResponse)
            {
                KerberosTgsResponse response = pdu as KerberosTgsResponse;
                UpdateContext(response);
            }

            this.expectedPduType = null;
        }
Example #2
0
        /// <summary>
        /// Expected a KDC_ERR_PREAUTH_REQUIRED error
        /// </summary>
        /// <param name="eData">Error data of this error</param>
        /// <returns></returns>
        private KerberosKrbError ExpectPreauthRequiredError(out METHOD_DATA eData)
        {
            KerberosPdu responsePdu = this.client.ExpectPdu(KerberosConstValue.TIMEOUT_DEFAULT, typeof(KerberosKrbError));

            if ((responsePdu == null) || (!(responsePdu is KerberosKrbError)))
            {
                throw new InvalidOperationException("Response type should be KerberosKrbError");
            }

            KerberosKrbError krbError = responsePdu as KerberosKrbError;

            if (!krbError.ErrorCode.Equals(KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED))
            {
                throw new InvalidOperationException("The Error code should be KDC_ERR_PREAUTH_REQUIRED");
            }

            eData = new METHOD_DATA();
            Asn1DecodingBuffer buffer = new Asn1DecodingBuffer(krbError.KrbError.e_data.ByteArrayValue);

            eData.BerDecode(buffer);
            return(krbError);
        }
        private void UpdateContext(KerberosKrbError error)
        {
            switch (error.ErrorCode)
            {
            case KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED:
            {
                var seqOfPadata = new Asn1SequenceOf <PA_DATA>();
                seqOfPadata.BerDecode(new Asn1DecodingBuffer(error.KrbError.e_data.ByteArrayValue));
                var padataCount = seqOfPadata.Elements.Length;

                for (int i = 0; i < padataCount; i++)
                {
                    var padata = PaDataParser.ParseRepPaData(seqOfPadata.Elements[i]);
                    //Fix me: PaETypeInfo is also possible
                    if (padata is PaETypeInfo2)
                    {
                        var    etypeinfo = padata as PaETypeInfo2;
                        string salt;
                        var    etype = negotiateEtype(etypeinfo.ETypeInfo2.Elements, Context.SupportedEType.Elements, out salt);
                        Context.SelectedEType = (EncryptionType)etype;
                        if (!string.IsNullOrEmpty(salt))
                        {
                            Context.CName.Salt = salt;
                        }
                        Context.ReplyKey = KerberosUtility.MakeKey(Context.SelectedEType, Context.CName.Password, Context.CName.Salt);
                    }
                    if (padata is PaFxFastRep)
                    {
                        //Fix me: Do something.
                    }
                }
                break;
            }

            default:
                break;
            }
        }
Example #4
0
        private KerberosAsResponse ExpectAsResponse()
        {
            KerberosPdu responsePdu = this.client.ExpectPdu(KerberosConstValue.TIMEOUT_DEFAULT, typeof(KerberosAsResponse));

            if (responsePdu == null)
            {
                throw new Exception("Expected KerberosAsResponse data is null");
            }

            if (responsePdu is KerberosKrbError)
            {
                KerberosKrbError errorResponse = responsePdu as KerberosKrbError;
                throw new Exception($"Expected KerberosAsResponse failed, Error Code:{errorResponse.ErrorCode}");
            }
            else if (!(responsePdu is KerberosAsResponse))
            {
                throw new Exception($"Expected KerberosAsResponse failed, reponse type is not a valid KerberosAsResponse, Response Type:{responsePdu.GetType().ToString()}");
            }

            KerberosAsResponse response = responsePdu as KerberosAsResponse;

            response.Decrypt(this.Context.ReplyKey.keyvalue.ByteArrayValue);
            return(response);
        }
 public PaFxError(PA_DATA PaData)
 {
     paData   = PaData;
     KrbError = new KerberosKrbError();
     KrbError.FromBytes(PaData.padata_value.ByteArrayValue);
 }
        //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;
            }

            // decode according to message type
            consumedLength = expectedLength;

            // get message type
            // (the lower 5 bits indicates its kile message type)
            MsgType     kileMessageType = (MsgType)(pduBytes[0] & 0x1f);
            KerberosPdu pdu             = null;

            switch (kileMessageType)
            {
            case MsgType.KRB_AS_REQ:
                pdu = new KerberosAsRequest();
                break;

            case MsgType.KRB_AS_RESP:
                pdu = new KerberosAsResponse();
                break;

            case MsgType.KRB_TGS_REQ:
                pdu = new KerberosTgsRequest();
                break;

            case MsgType.KRB_TGS_RESP:
                pdu = new KerberosTgsResponse();
                break;

            case MsgType.KRB_ERROR:
                pdu = new KerberosKrbError();
                break;

            default:
                throw new FormatException(
                          "Unsupported Message Type: " + kileMessageType.ToString());
            }
            pdu.FromBytes(pduBytes);
            // update context
            if (this.expectedPduType == null || this.expectedPduType == pdu.GetType())
            {
                this.UpdateContext(pdu);
            }
            return(pdu);
        }
        public KerberosKrbError GetKrbErrorFromToken(byte[] token)
        {
            token = KerberosUtility.DecodeNegotiationToken(token);

            if (token[0] == KerberosConstValue.KERBEROS_TAG)
            {
                byte[] apData = KerberosUtility.VerifyGssApiTokenHeader(token, this.oidPkt);

                // Check if it has a two-byte tok_id
                if (null == apData || apData.Length <= sizeof(TOK_ID))
                {
                    throw new FormatException(
                        "Data length is shorter than a valid AP Response data length.");
                }

                // verify TOK_ID
                byte[] tokenID = ArrayUtility.SubArray<byte>(apData, 0, sizeof(TOK_ID));
                Array.Reverse(tokenID);
                TOK_ID id = (TOK_ID)BitConverter.ToUInt16(tokenID, 0);

                this.testSite.Assert.AreEqual(TOK_ID.KRB_ERROR, id, "The Token ID should be KRB_ERROR");

                // Get apBody
                token = ArrayUtility.SubArray(apData, sizeof(TOK_ID));
            }

            KerberosKrbError error = new KerberosKrbError();
            error.FromBytes(token);

            return error;
        }
 public PaFxError(PA_DATA PaData)
 {
     paData = PaData;
     KrbError = new KerberosKrbError();
     KrbError.FromBytes(PaData.padata_value.ByteArrayValue);
 }
        private void UpdateContext(KerberosKrbError error)
        {
            switch (error.ErrorCode)
            {
                case KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED:
                    {
                        var seqOfPadata = new Asn1SequenceOf<PA_DATA>();
                        seqOfPadata.BerDecode(new Asn1DecodingBuffer(error.KrbError.e_data.ByteArrayValue));
                        var padataCount = seqOfPadata.Elements.Length;

                        for (int i = 0; i < padataCount; i++)
                        {
                            var padata = PaDataParser.ParseRepPaData(seqOfPadata.Elements[i]);
                            //Fix me: PaETypeInfo is also possible
                            if (padata is PaETypeInfo2)
                            {
                                var etypeinfo = padata as PaETypeInfo2;
                                string salt;
                                var etype = negotiateEtype(etypeinfo.ETypeInfo2.Elements, Context.SupportedEType.Elements, out salt);
                                Context.SelectedEType = (EncryptionType)etype;
                                if (!string.IsNullOrEmpty(salt)) Context.CName.Salt = salt;
                                Context.ReplyKey = KerberosUtility.MakeKey(Context.SelectedEType, Context.CName.Password, Context.CName.Salt);
                            }
                            if (padata is PaFxFastRep)
                            {
                                //Fix me: Do something.
                            }

                        }
                        break;
                    }
                default:
                    break;
            }
        }
        //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;
            }

            // decode according to message type
            consumedLength = expectedLength;

            // get message type
            // (the lower 5 bits indicates its kile message type)
            MsgType kileMessageType = (MsgType)(pduBytes[0] & 0x1f);
            KerberosPdu pdu = null;

            switch (kileMessageType)
            {
                case MsgType.KRB_AS_REQ:
                    pdu = new KerberosAsRequest();
                    break;

                case MsgType.KRB_AS_RESP:
                    pdu = new KerberosAsResponse();
                    break;

                case MsgType.KRB_TGS_REQ:
                    pdu = new KerberosTgsRequest();
                    break;

                case MsgType.KRB_TGS_RESP:
                    pdu = new KerberosTgsResponse();
                    break;

                case MsgType.KRB_ERROR:
                    pdu = new KerberosKrbError();
                    break;

                default:
                    throw new FormatException(
                        "Unsupported Message Type: " + kileMessageType.ToString());
            }
            pdu.FromBytes(pduBytes);
            // update context
            if (this.expectedPduType == null || this.expectedPduType == pdu.GetType())
                this.UpdateContext(pdu);
            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;
        }