public byte[] ToBytes(TransportType transportType)
 {
     Asn1BerEncodingBuffer asBerBuffer = new Asn1BerEncodingBuffer();
     this.FastReq.BerEncode(asBerBuffer, true);
     if (transportType == TransportType.TCP)
     {
         return KerberosUtility.WrapLength(asBerBuffer.Data, true);
     }
     else
     {
         return asBerBuffer.Data;
     }
 }
        /// <summary>
        /// Create an instance.
        /// </summary>
        public KpasswordRequest(KerberosTicket ticket, Authenticator authenticator, string newPwd, bool isAuthErrorRequired = false)
        {
            //Create KerberosApRequest
            long pvno = KerberosConstValue.KERBEROSV5;
            APOptions option = new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.None));
            KerberosApRequest ap_req = new KerberosApRequest(pvno, option, ticket, authenticator, KeyUsageNumber.AP_REQ_Authenticator);
            //Create KRB_PRIV
            ChangePasswdData pwd_data = new ChangePasswdData(new Asn1OctetString(newPwd), null, null);
            priv_enc_part = new EncKrbPrivPart();
            priv_enc_part.user_data = pwd_data.newpasswd;
            priv_enc_part.usec = authenticator.cusec;
            priv_enc_part.seq_number = authenticator.seq_number;
            priv_enc_part.s_address = new HostAddress(new KerbInt32((int)AddressType.NetBios), new Asn1OctetString(Encoding.ASCII.GetBytes(System.Net.Dns.GetHostName())));
            Asn1BerEncodingBuffer asnBuffPriv = new Asn1BerEncodingBuffer();
            priv_enc_part.BerEncode(asnBuffPriv, true);
            byte[] encAsnEncodedPriv = null;

            if (!isAuthErrorRequired)
            {
                encAsnEncodedPriv = KerberosUtility.Encrypt((EncryptionType)authenticator.subkey.keytype.Value,
                            authenticator.subkey.keyvalue.ByteArrayValue,
                            asnBuffPriv.Data,
                            (int)KeyUsageNumber.KRB_PRIV_EncPart);
            }
            else
            {
                encAsnEncodedPriv = KerberosUtility.Encrypt((EncryptionType)authenticator.subkey.keytype.Value,
                            authenticator.subkey.keyvalue.ByteArrayValue,
                            asnBuffPriv.Data,
                            (int)KeyUsageNumber.None);
            }

            var encrypted = new EncryptedData();
            encrypted.etype = new KerbInt32(authenticator.subkey.keytype.Value);
            encrypted.cipher = new Asn1OctetString(encAsnEncodedPriv);
            KRB_PRIV krb_priv = new KRB_PRIV(new Asn1Integer(pvno), new Asn1Integer((long)MsgType.KRB_PRIV), encrypted);
            //Calculate the msg_length and ap_req_length
            krb_priv.BerEncode(privBuffer, true);
            ap_req.Request.BerEncode(apBuffer, true);
            version = 0x0001;
            ap_req_length = (ushort)apBuffer.Data.Length;
            msg_length = (ushort)(ap_req_length + privBuffer.Data.Length + 3 * sizeof(ushort));
            //Convert Endian
            version = KerberosUtility.ConvertEndian(version);
            ap_req_length = KerberosUtility.ConvertEndian(ap_req_length);
            msg_length = KerberosUtility.ConvertEndian(msg_length);
        }
 /// <summary>
 /// Encode this class into byte array.
 /// </summary>
 /// <returns>The byte array of the class.</returns>
 public override byte[] ToBytes()
 {
     Asn1BerEncodingBuffer asBerBuffer = new Asn1BerEncodingBuffer();
     this.Request.BerEncode(asBerBuffer, true);
     KerberosUtility.OnDumpMessage("KRB5:KrbMessage",
         "Kerberos Message",
         KerberosUtility.DumpLevel.WholeMessage,
         asBerBuffer.Data);
     if (transportType == TransportType.TCP)
     {
         return KerberosUtility.WrapLength(asBerBuffer.Data, true);
     }
     else
     {
         return asBerBuffer.Data;
     }
 }
        /// <summary>
        /// Create an instance.
        /// </summary>
        public KerberosApRequest(long pvno, APOptions ap_options, KerberosTicket ticket, Authenticator authenticator, KeyUsageNumber keyUsageNumber)
        {
            Asn1BerEncodingBuffer asnBuffPlainAuthenticator = new Asn1BerEncodingBuffer();
            authenticator.BerEncode(asnBuffPlainAuthenticator, true);
            KerberosUtility.OnDumpMessage("KRB5:Authenticator",
                "Authenticator in AP-REQ structure",
                 KerberosUtility.DumpLevel.PartialMessage,
                 asnBuffPlainAuthenticator.Data);
            byte[] encAsnEncodedAuth = KerberosUtility.Encrypt((EncryptionType)ticket.SessionKey.keytype.Value,
                                    ticket.SessionKey.keyvalue.ByteArrayValue,
                                    asnBuffPlainAuthenticator.Data,
                                    (int)keyUsageNumber);
            var encrypted = new EncryptedData();
            encrypted.etype = new KerbInt32(ticket.SessionKey.keytype.Value);
            encrypted.cipher = new Asn1OctetString(encAsnEncodedAuth);

            long msg_type = (long)MsgType.KRB_AP_REQ;
            Request = new AP_REQ(new Asn1Integer(pvno), new Asn1Integer(msg_type), ap_options, ticket.Ticket, encrypted);
            Authenticator = authenticator;
        }
        /// <summary>
        /// Create and send TGS request
        /// </summary>
        /// <param name="sName">Service principal name</param>
        /// <param name="kdcOptions">KDC options</param>
        /// <param name="seqPadata">A sequence of preauthentication data</param>
        /// <param name="checksumType">Checksum type of PA-TGS-REQ</param>
        /// <param name="additionalTicket">Additional ticket</param>
        /// <param name="data">Authorization data</param>
        public void SendTgsRequest(string sName,
            KdcOptions kdcOptions,
            Asn1SequenceOf<PA_DATA> seqPadata = null,
            Ticket additionalTicket = null,
            AuthorizationData dataInAuthenticator = null,
            AuthorizationData dataInEncAuthData = null)
        {
            if (sName == null)
            {
                throw new ArgumentNullException("sName");
            }
            PrincipalName sname = new PrincipalName(
                new KerbInt32((int)PrincipalType.NT_SRV_INST),
                KerberosUtility.String2SeqKerbString(sName.Split('/')));

            KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sname, dataInEncAuthData);
            Asn1BerEncodingBuffer bodyBuffer = new Asn1BerEncodingBuffer();
            kdcReqBody.BerEncode(bodyBuffer);

            ChecksumType checksumType = KerberosUtility.GetChecksumType(Context.SelectedEType);
            PA_DATA paTgsReq = CreatePaTgsReq(checksumType, bodyBuffer.Data, dataInAuthenticator);

            Asn1SequenceOf<PA_DATA> tempPaData = null;
            if (seqPadata == null || seqPadata.Elements == null || seqPadata.Elements.Length == 0)
            {
                tempPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paTgsReq });
            }
            else
            {
                PA_DATA[] paDatas = new PA_DATA[seqPadata.Elements.Length + 1];
                Array.Copy(seqPadata.Elements, paDatas, seqPadata.Elements.Length);
                paDatas[seqPadata.Elements.Length] = paTgsReq;
                tempPaData = new Asn1SequenceOf<PA_DATA>(paDatas);
            }

            KerberosTgsRequest tgsRequest = new KerberosTgsRequest(KerberosConstValue.KERBEROSV5, kdcReqBody, tempPaData, Context.TransportType);
            this.SendPdu(tgsRequest);
            this.testSite.Log.Add(LogEntryKind.Debug, "Send TGS request.");
        }
        public PaFxFastReq CreateAsPaFxFast(
            EncryptionKey subKey,
            FastOptions fastOptions,
            ApOptions apOptions,
            Asn1SequenceOf<PA_DATA> seqPaData,
            string sName,
            KDC_REQ_BODY kdcReqBody,
            KrbFastArmorType armorType
            )
        {
            string domain = this.Context.Realm.Value;
            PrincipalName sname =
                new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString(sName, domain));

            var armorKey = KerberosUtility.MakeArmorKey(
                Context.SelectedEType,
                subKey.keyvalue.ByteArrayValue,
                Context.ArmorSessionKey.keyvalue.ByteArrayValue);
            Context.FastArmorkey = new EncryptionKey(new KerbInt32((long)Context.SelectedEType), new Asn1OctetString(armorKey));

            Asn1BerEncodingBuffer encodebuf = new Asn1BerEncodingBuffer();
            kdcReqBody.BerEncode(encodebuf);
            var checksumType = KerberosUtility.GetChecksumType(Context.SelectedEType);
            var chksum = KerberosUtility.GetChecksum(
                armorKey,
                encodebuf.Data,
                (int)KeyUsageNumber.FAST_REQ_CHECKSUM,
                checksumType);
            Checksum checkSum = new Checksum(new KerbInt32((int)checksumType), new Asn1OctetString(chksum));

            Authenticator plaintextAuthenticator = CreateAuthenticator(Context.ArmorTicket, null, subKey);

            KerberosApRequest apReq = new KerberosApRequest(Context.Pvno,
                new APOptions(KerberosUtility.ConvertInt2Flags((int)apOptions)),
                Context.ArmorTicket,
                plaintextAuthenticator,
                KeyUsageNumber.AP_REQ_Authenticator);

            KDC_REQ_BODY innerKdcReqBody = CreateKdcRequestBody(KdcOptions.CANONICALIZE | KdcOptions.FORWARDABLE | KdcOptions.RENEWABLE, sname);
            KerberosFastRequest fastReq = new KerberosFastRequest(fastOptions, seqPaData, innerKdcReqBody);
            FastArmorApRequest fastArmor = new FastArmorApRequest(apReq.Request);
            fastArmor.armorType = armorType;
            KerberosArmoredRequest armoredReq
                = new KerberosArmoredRequest(fastArmor, checkSum, (long)Context.SelectedEType, armorKey, fastReq);
            PA_FX_FAST_REQUEST paFxFastReq = new PA_FX_FAST_REQUEST();
            paFxFastReq.SetData(PA_FX_FAST_REQUEST.armored_data, armoredReq.FastArmoredReq);
            PaFxFastReq paFxfast = new PaFxFastReq(paFxFastReq);
            return paFxfast;
        }
        private KDC_REQ_BODY CreateKdcRequestBody(
            KdcOptions kdcOptions,
            PrincipalName sName,
            AuthorizationData data = null
            )
        {
            KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sName);

            if (data == null)
                return kdcReqBody;

            Asn1BerEncodingBuffer asnBuffer = new Asn1BerEncodingBuffer();
            // Fix me: NullReferenceException if data is null.
            if (data != null) data.BerEncode(asnBuffer, true);

            EncryptedData eData = new EncryptedData();
            eData.etype = new KerbInt32(0);
            byte[] encAsnEncoded = asnBuffer.Data;
            if (Context.SessionKey != null && Context.SessionKey.keytype != null
                && Context.SessionKey.keyvalue != null && Context.SessionKey.keyvalue.Value != null)
            {
                encAsnEncoded = KerberosUtility.Encrypt((EncryptionType)Context.SessionKey.keytype.Value,
                                                    Context.SessionKey.keyvalue.ByteArrayValue,
                                                    asnBuffer.Data,
                                                    (int)KeyUsageNumber.TGS_REQ_KDC_REQ_BODY_AuthorizationData);
                eData.etype = new KerbInt32(Context.SessionKey.keytype.Value);
            }
            eData.cipher = new Asn1OctetString(encAsnEncoded);
            kdcReqBody.enc_authorization_data = eData;

            return kdcReqBody;
        }
        public PaEncryptedChallenge(EncryptionType type, string timeStamp, int usec, EncryptionKey armorKey, EncryptionKey userLongTermKey)
        {
            this.TimeStamp = timeStamp;
            this.Usec = usec;

            var keyvalue = KeyGenerator.KrbFxCf2(
                (EncryptionType)armorKey.keytype.Value,
                armorKey.keyvalue.ByteArrayValue,
                userLongTermKey.keyvalue.ByteArrayValue,
                "clientchallengearmor",
                "challengelongterm");
            switch (type)
            {
                case EncryptionType.AES256_CTS_HMAC_SHA1_96:
                    {
                        var key = new EncryptionKey(new KerbInt32((long)EncryptionType.AES256_CTS_HMAC_SHA1_96), new Asn1OctetString(keyvalue));
                        this.Key = key;
                        break;
                    }
                case EncryptionType.RC4_HMAC:
                    {
                        var key = new EncryptionKey(new KerbInt32((long)EncryptionType.RC4_HMAC), new Asn1OctetString(keyvalue));
                        this.Key = key;
                        break;
                    }
                default:
                    throw new ArgumentException("Unsupported encryption type.");
            }

            // create a timestamp
            PA_ENC_TS_ENC paEncTsEnc = new PA_ENC_TS_ENC(new KerberosTime(this.TimeStamp), new Microseconds(this.Usec));
            Asn1BerEncodingBuffer currTimeStampBuffer = new Asn1BerEncodingBuffer();
            paEncTsEnc.BerEncode(currTimeStampBuffer);

            var rawData = currTimeStampBuffer.Data;
            KerberosUtility.OnDumpMessage("KRB5:PA-ENC-TS-ENC",
                "Encrypted Timestamp Pre-authentication",
                KerberosUtility.DumpLevel.PartialMessage,
                rawData);

            // encrypt the timestamp
            byte[] encTimeStamp = KerberosUtility.Encrypt((EncryptionType)this.Key.keytype.Value,
                                                      this.Key.keyvalue.ByteArrayValue,
                                                      rawData,
                                                      (int)KeyUsageNumber.ENC_CHALLENGE_CLIENT);

            EncryptedChallenge encryptedChallenge = new EncryptedChallenge(new KerbInt32((long)this.Key.keytype.Value),
                null,
                new Asn1OctetString(encTimeStamp));

            Asn1BerEncodingBuffer paEncTimestampBuffer = new Asn1BerEncodingBuffer();
            encryptedChallenge.BerEncode(paEncTimestampBuffer, true);

            Data = new PA_DATA(new KerbInt32((long)PaDataType.PA_ENCRYPTED_CHALLENGE), new Asn1OctetString(paEncTimestampBuffer.Data));
        }
        public void KrbErrorTktNotYetValid()
        {
            base.Logging();

            client = new KerberosTestClient(this.testConfig.LocalRealm.RealmName,
                this.testConfig.LocalRealm.User[1].Username,
                this.testConfig.LocalRealm.User[1].Password,
                KerberosAccountType.User,
                testConfig.LocalRealm.KDC[0].IPAddress,
                testConfig.LocalRealm.KDC[0].Port,
                testConfig.TransportType,
                testConfig.SupportedOid);

            // Kerberos Proxy Service is used
            if (this.testConfig.UseProxy)
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Initialize KKDCP Client.");
                KKDCPClient proxyClient = new KKDCPClient(proxyClientConfig);
                proxyClient.TargetDomain = this.testConfig.LocalRealm.RealmName;
                client.UseProxy = true;
                client.ProxyClient = proxyClient;
            }

            //Create and send AS request
            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            //Recieve preauthentication required error
            METHOD_DATA methodData;
            KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData);

            //Create sequence of PA data
            string timeStamp = KerberosUtility.CurrentKerberosTime.Value;
            PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp,
                0,
                client.Context.SelectedEType,
                this.client.Context.CName.Password,
                this.client.Context.CName.Salt);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data });

            //Create and send AS request
            client.SendAsRequest(options, seqOfPaData);
            KerberosAsResponse asResponse = client.ExpectAsResponse();

            //Create and send TGS request
            client.SendTgsRequest(this.testConfig.LocalRealm.FileServer[0].Smb2ServiceName, options);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            // Change ticket
            EncryptionKey tgskey = testConfig.QueryKey(
                this.testConfig.LocalRealm.FileServer[0].Smb2ServiceName,
                this.testConfig.LocalRealm.RealmName,
                this.client.Context.SelectedEType);
            // Decrypt ticket
            tgsResponse.DecryptTicket(tgskey);
            // Set ticket start time 15 minutes later than now
            string nyvTime = DateTime.Now.AddMinutes(15).ToUniversalTime().ToString("yyyyMMddHHmmss") + "Z";
            tgsResponse.TicketEncPart.starttime = new KerberosTime(nyvTime);
            Asn1BerEncodingBuffer encodeBuffer = new Asn1BerEncodingBuffer();
            tgsResponse.TicketEncPart.BerEncode(encodeBuffer, true);
            EncryptionType encryptType = (EncryptionType) tgsResponse.Response.ticket.enc_part.etype.Value;
            var key = KeyGenerator.MakeKey(encryptType, this.testConfig.LocalRealm.FileServer[0].Password, this.testConfig.LocalRealm.FileServer[0].ServiceSalt);
            // Re-encrypt ticket
            var encrypedData = KerberosUtility.Encrypt(
                encryptType,
                key,
                encodeBuffer.Data,
                (int)KeyUsageNumber.AS_REP_TicketAndTGS_REP_Ticket);
            tgsResponse.Response.ticket.enc_part = new EncryptedData(new KerbInt32((long)encryptType), null, new Asn1OctetString(encrypedData));

            AuthorizationData data = null;
            EncryptionKey subkey = KerberosUtility.GenerateKey(client.Context.SessionKey);
            byte[] token = client.CreateGssApiToken(ApOptions.MutualRequired,
                data,
                subkey,
                ChecksumFlags.GSS_C_MUTUAL_FLAG | ChecksumFlags.GSS_C_INTEG_FLAG);

            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send Smb2 request.");
            KerberosKrbError error = client.GetKrbErrorFromToken(SendAndRecieveSmb2Ap(this.testConfig.LocalRealm.FileServer[0], token));
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve Kerberos error.");
            BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_TKT_NYV, error.ErrorCode,
                "If the starttime is later than the current time by more than the allowable clock skew (10 minutes), " +
                "the KRB_AP_ERR_TKT_NYV error is returned.");
        }
        public void KrbFastFinishedTgsRep()
        {
            base.Logging();

            client = new KerberosTestClient(
                this.testConfig.LocalRealm.RealmName,
                this.testConfig.LocalRealm.ClientComputer.NetBiosName,
                this.testConfig.LocalRealm.ClientComputer.Password,
                KerberosAccountType.Device,
                testConfig.LocalRealm.KDC[0].IPAddress,
                testConfig.LocalRealm.KDC[0].Port,
                testConfig.TransportType,
                testConfig.SupportedOid,
               testConfig.LocalRealm.ClientComputer.AccountSalt);

            // Kerberos Proxy Service is used
            if (this.testConfig.UseProxy)
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Initialize KKDCP Client .");
                KKDCPClient proxyClient = new KKDCPClient(proxyClientConfig);
                proxyClient.TargetDomain = this.testConfig.LocalRealm.RealmName;
                client.UseProxy = true;
                client.ProxyClient = proxyClient;
            }

            // AS_REQ and KRB-ERROR using device principal
            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            METHOD_DATA methodData;
            KerberosKrbError krbError1 = client.ExpectPreauthRequiredError(out methodData);

            // AS_REQ and AS_REP using device principal
            string timeStamp = KerberosUtility.CurrentKerberosTime.Value;
            PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(
                timeStamp,
                0,
                client.Context.SelectedEType,
                this.client.Context.CName.Password,
                this.client.Context.CName.Salt);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data });
            client.SendAsRequest(options, seqOfPaData);
            KerberosAsResponse asResponse = client.ExpectAsResponse();
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                string.Format("The type of AS-REP encrypted part is {0}.", asResponse.EncPart.GetType().Name));

            // Switch to user principal
            client = new KerberosTestClient(
                this.testConfig.LocalRealm.RealmName,
                this.testConfig.LocalRealm.User[1].Username,
                this.testConfig.LocalRealm.User[1].Password,
                KerberosAccountType.User,
                client.Context.Ticket,
                client.Context.SessionKey,
                testConfig.LocalRealm.KDC[0].IPAddress,
                testConfig.LocalRealm.KDC[0].Port,
                testConfig.TransportType,
                testConfig.SupportedOid);

            // Kerberos Proxy Service is used
            if (this.testConfig.UseProxy)
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Initialize KKDCP Client .");
                KKDCPClient proxyClient = new KKDCPClient(proxyClientConfig);
                proxyClient.TargetDomain = this.testConfig.LocalRealm.RealmName;
                client.UseProxy = true;
                client.ProxyClient = proxyClient;
            }

            // FAST armored AS_REQ and KRB-ERROR using user principal
            //Create a "random" key.
            var subkey = KerberosUtility.MakeKey(client.Context.SelectedEType, "Password02!", "this is a salt");
            var fastOptions = new Protocols.TestTools.StackSdk.Security.KerberosV5.Preauth.FastOptions(KerberosUtility.ConvertInt2Flags((int)0));
            var apOptions = ApOptions.None;

            Asn1SequenceOf<PA_DATA> seqOfPaData2 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { new PA_DATA(new KerbInt32((long)PaDataType.PA_FX_FAST), null) });
            client.SendAsRequestWithFast(options, seqOfPaData2, null, subkey, fastOptions, apOptions);
            KerberosKrbError krbError2 = client.ExpectKrbError();
            BaseTestSite.Assert.AreEqual(krbError2.ErrorCode, KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED, "Pre-authentication required.");

            // FAST armored AS_REQ and AS_REP using user principal
            var userKey = KerberosUtility.MakeKey(
                client.Context.SelectedEType,
                client.Context.CName.Password,
                client.Context.CName.Salt);
            PaEncryptedChallenge paEncTimeStamp3 = new PaEncryptedChallenge(
                client.Context.SelectedEType,
                KerberosUtility.CurrentKerberosTime.Value,
                0,
                client.Context.FastArmorkey,
                userKey);
            Asn1SequenceOf<PA_DATA> seqOfPaData3 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp3.Data });
            client.SendAsRequestWithFast(options, seqOfPaData3, null, subkey, fastOptions, apOptions);
            KerberosAsResponse userKrbAsRep = client.ExpectAsResponse();
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                string.Format("The type of AS-REP encrypted part is {0}.", userKrbAsRep.EncPart.GetType().Name));

            // FAST armored TGS_REQ and TGS_REP using user principal
            subkey = KerberosUtility.MakeKey(client.Context.SelectedEType, "Password03!", "this is a salt");
            client.SendTgsRequestWithFast(testConfig.LocalRealm.ClientComputer.DefaultServiceName, options, null, null, subkey, fastOptions, apOptions);
            KerberosTgsResponse userKrbTgsRep = client.ExpectTgsResponse(KeyUsageNumber.TGS_REP_encrypted_part_subkey);
            BaseTestSite.Assert.IsNotNull(userKrbTgsRep.EncPart, "The encrypted part of TGS-REP is decrypted.");
            //Verify KrbFastFinished.
            KrbFastFinished fastFinishedTgs = null;
            BaseTestSite.Assert.IsNotNull(userKrbAsRep.Response.padata, "The padata of AS-REP is not null.");
            BaseTestSite.Assert.IsNotNull(userKrbAsRep.Response.padata.Elements, "The padata of AS-REP is not empty.");

            foreach (PA_DATA paData in userKrbTgsRep.Response.padata.Elements)
            {
                var parsedPaData = PaDataParser.ParseRepPaData(paData);
                if (parsedPaData is PaFxFastRep)
                {
                    var armoredRep = ((PaFxFastRep)parsedPaData).GetArmoredRep();
                    var kerbFastRep = ((PaFxFastRep)parsedPaData).GetKerberosFastRep(client.Context.FastArmorkey);
                    fastFinishedTgs = kerbFastRep.FastResponse.finished;
                    break;
                }
            }
            BaseTestSite.Assert.IsNotNull(fastFinishedTgs, "The finished field contains a KrbFastFinished structure.");
            Asn1BerEncodingBuffer buf2 = new Asn1BerEncodingBuffer();
            userKrbTgsRep.Response.ticket.BerEncode(buf2);
            Checksum ticketChecksumTgs = new Checksum(new KerbInt32((long)KerberosUtility.GetChecksumType(client.Context.SelectedEType)), new Asn1OctetString(KerberosUtility.GetChecksum(
                client.Context.FastArmorkey.keyvalue.ByteArrayValue,
                buf2.Data,
                (int)KeyUsageNumber.FAST_FINISHED,
                KerberosUtility.GetChecksumType(client.Context.SelectedEType))));
            BaseTestSite.Assert.IsTrue(
                KerberosUtility.CompareChecksum(fastFinishedTgs.ticket_checksum, ticketChecksumTgs),
                "The ticket checksum is correct.");
        }
 /// <summary>
 /// Encode this class into byte array.
 /// </summary>
 /// <returns>The byte array of the class.</returns>
 public byte[] ToBytes()
 {
     Asn1BerEncodingBuffer asBerBuffer = new Asn1BerEncodingBuffer();
     this.Message.BerEncode(asBerBuffer, true);
     return asBerBuffer.Data;
 }
Example #12
0
        /// <summary>
        /// Encode this structure into byte array.
        /// </summary>
        /// <returns>The byte array of the structure.</returns>
        public override byte[] ToBytes()
        {
            List<byte> totalBuffer = new List<byte>();
            RdpbcgrEncoder.EncodeStructure(totalBuffer, tpktHeader);
            RdpbcgrEncoder.EncodeStructure(totalBuffer, x224Data);

            if (mcsCrsp != null)
            {
                byte[] gccData = EncodeGccRspData(mcsCrsp.gccPdu);

                #region Filling MCS Connect Response PDU
                Connect_Response connectResponse = new Connect_Response();
                connectResponse.result = new Result(mcsCrsp.result);
                connectResponse.calledConnectId = new Asn1Integer(mcsCrsp.calledConnectId);
                connectResponse.domainParameters = new DomainParameters(new Asn1Integer(mcsCrsp.domainParameters.maxChannelIds),
                                                                       new Asn1Integer(mcsCrsp.domainParameters.maxUserIds),
                                                                       new Asn1Integer(mcsCrsp.domainParameters.maxTokenIds),
                                                                       new Asn1Integer(mcsCrsp.domainParameters.numPriorities),
                                                                       new Asn1Integer(mcsCrsp.domainParameters.minThroughput),
                                                                       new Asn1Integer(mcsCrsp.domainParameters.maxHeight),
                                                                       new Asn1Integer(mcsCrsp.domainParameters.maxMcsPduSize),
                                                                       new Asn1Integer(mcsCrsp.domainParameters.protocolVersion));
                connectResponse.userData = new Asn1OctetString(gccData);
                #endregion Filling MCS Connect Response PDU

                #region Encode MCS Connect Initial PDU
                Asn1BerEncodingBuffer berEncodeBuffer = new Asn1BerEncodingBuffer();
                connectResponse.BerEncode(berEncodeBuffer);
                #endregion MCS Connect Initial PDU

                RdpbcgrEncoder.EncodeBytes(totalBuffer, berEncodeBuffer.Data);
            }

            byte[] encodedBytes = RdpbcgrUtility.ToBytes(totalBuffer);

            // ToDo: Ugly dump message code here
            // ETW Provider Dump Code
            RdpbcgrUtility.ETWProviderDump(this.GetType().Name, encodedBytes);

            return encodedBytes;
        }
Example #13
0
        /// <summary>
        /// Encode this structure into byte array.
        /// </summary>
        /// <returns>The byte array of the structure.</returns>
        public override byte[] ToBytes()
        {
            List<byte> totalBuffer = new List<byte>();
            RdpbcgrEncoder.EncodeStructure(totalBuffer, tpktHeader);
            RdpbcgrEncoder.EncodeStructure(totalBuffer, x224Data);

            if (mcsCi != null)
            {
                byte[] gccData = EncodeGccData(mcsCi.gccPdu);

                #region Filling MCS Connect Initial PDU
                Connect_Initial connectInitial = new Connect_Initial();
                connectInitial.calledDomainSelector = new Asn1OctetString(mcsCi.calledDomainSelector);
                connectInitial.callingDomainSelector = new Asn1OctetString(mcsCi.callingDomainSelector);
                connectInitial.upwardFlag = new Asn1Boolean(mcsCi.upwardFlag);

                connectInitial.targetParameters = new DomainParameters(new Asn1Integer(mcsCi.targetParameters.maxChannelIds),
                                                                       new Asn1Integer(mcsCi.targetParameters.maxUserIds),
                                                                       new Asn1Integer(mcsCi.targetParameters.maxTokenIds),
                                                                       new Asn1Integer(mcsCi.targetParameters.numPriorities),
                                                                       new Asn1Integer(mcsCi.targetParameters.minThroughput),
                                                                       new Asn1Integer(mcsCi.targetParameters.maxHeight),
                                                                       new Asn1Integer(mcsCi.targetParameters.maxMcsPduSize),
                                                                       new Asn1Integer(mcsCi.targetParameters.protocolVersion));

                connectInitial.minimumParameters = new DomainParameters(new Asn1Integer(mcsCi.minimumParameters.maxChannelIds),
                                                                        new Asn1Integer(mcsCi.minimumParameters.maxUserIds),
                                                                        new Asn1Integer(mcsCi.minimumParameters.maxTokenIds),
                                                                        new Asn1Integer(mcsCi.minimumParameters.numPriorities),
                                                                        new Asn1Integer(mcsCi.minimumParameters.minThroughput),
                                                                        new Asn1Integer(mcsCi.minimumParameters.maxHeight),
                                                                        new Asn1Integer(mcsCi.minimumParameters.maxMcsPduSize),
                                                                        new Asn1Integer(mcsCi.minimumParameters.protocolVersion));

                connectInitial.maximumParameters = new DomainParameters(new Asn1Integer(mcsCi.maximumParameters.maxChannelIds),
                                                                        new Asn1Integer(mcsCi.maximumParameters.maxUserIds),
                                                                        new Asn1Integer(mcsCi.maximumParameters.maxTokenIds),
                                                                        new Asn1Integer(mcsCi.maximumParameters.numPriorities),
                                                                        new Asn1Integer(mcsCi.maximumParameters.minThroughput),
                                                                        new Asn1Integer(mcsCi.maximumParameters.maxHeight),
                                                                        new Asn1Integer(mcsCi.maximumParameters.maxMcsPduSize),
                                                                        new Asn1Integer(mcsCi.maximumParameters.protocolVersion));

                connectInitial.userData = new Asn1OctetString(gccData);
                #endregion Filling MCS Connect Initial PDU

                #region Encode MCS Connect Initial PDU
                Asn1BerEncodingBuffer berEncodeBuffer = new Asn1BerEncodingBuffer();
                connectInitial.BerEncode(berEncodeBuffer);
                #endregion MCS Connect Initial PDU

                if (berEncodeBuffer.Data != null)
                {
                    RdpbcgrEncoder.EncodeBytes(totalBuffer, berEncodeBuffer.Data);
                }
            }

            return RdpbcgrUtility.ToBytes(totalBuffer);
        }
        public void DetectTicketModification_Http()
        {
            base.Logging();

            client = new KerberosTestClient(this.testConfig.LocalRealm.RealmName,
                this.testConfig.LocalRealm.User[1].Username,
                this.testConfig.LocalRealm.User[1].Password,
                KerberosAccountType.User,
                testConfig.LocalRealm.KDC[0].IPAddress,
                testConfig.LocalRealm.KDC[0].Port,
                testConfig.TransportType,
                testConfig.SupportedOid);

            // Kerberos Proxy Service is used
            if (this.testConfig.UseProxy)
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Initialize KKDCP Client .");
                KKDCPClient proxyClient = new KKDCPClient(proxyClientConfig);
                proxyClient.TargetDomain = this.testConfig.LocalRealm.RealmName;
                client.UseProxy = true;
                client.ProxyClient = proxyClient;
            }

            //Create and send AS request
            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            //Recieve preauthentication required error
            METHOD_DATA methodData;
            KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData);

            //Create sequence of PA data
            string timeStamp = KerberosUtility.CurrentKerberosTime.Value;
            PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp,
                0,
                client.Context.SelectedEType,
                this.client.Context.CName.Password,
                this.client.Context.CName.Salt);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data });
            //Create and send AS request
            client.SendAsRequest(options, seqOfPaData);
            KerberosAsResponse asResponse = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");

            //Create and send TGS request
            client.SendTgsRequest(this.testConfig.LocalRealm.WebServer[0].HttpServiceName, options);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            EncryptionKey tgskey = testConfig.QueryKey(this.testConfig.LocalRealm.WebServer[0].HttpServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType);
            tgsResponse.DecryptTicket(tgskey);

            //Change ticket
            //tgsResponse.DecryptTicket(this.testConfig.LocalRealm.WebServer[0].Password, this.testConfig.LocalRealm.WebServer[0].ServiceSalt);
            //tgsResponse.TicketEncPart.cname = new PrincipalName((long)PrincipalType.NT_PRINCIPAL, KerberosUtility.String2SeqKerbString("NonExistUser", testConfig.LocalRealm.RealmName));
            Asn1BerEncodingBuffer encodeBuffer = new Asn1BerEncodingBuffer();
            tgsResponse.TicketEncPart.BerEncode(encodeBuffer, true);

            EncryptionType encryptType = (EncryptionType)tgsResponse.Response.ticket.enc_part.etype.Value;
            var key = KeyGenerator.MakeKey(encryptType, "WrongPassword", this.testConfig.LocalRealm.WebServer[0].ServiceSalt);
            var encrypedData = KerberosUtility.Encrypt(
                encryptType,
                key,
                encodeBuffer.Data,
                (int)KeyUsageNumber.AS_REP_TicketAndTGS_REP_Ticket);
            tgsResponse.Response.ticket.enc_part = new EncryptedData(new KerbInt32((long)encryptType), null, new Asn1OctetString(encrypedData));

            AuthorizationData data = null;
            EncryptionKey subkey = KerberosUtility.GenerateKey(client.Context.SessionKey);
            byte[] token = client.CreateGssApiToken(ApOptions.MutualRequired,
                data,
                subkey,
                ChecksumFlags.GSS_C_MUTUAL_FLAG | ChecksumFlags.GSS_C_INTEG_FLAG);

            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send Http request.");
            //Receive Error here
            KerberosKrbError error = client.GetKrbErrorFromToken(SendAndRecieveHttpAp(this.testConfig.LocalRealm.WebServer[0], token));
            BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_MODIFIED,
                error.ErrorCode,
                "AP should return KRB_AP_ERR_MODIFIED if authenticator changed");
        }
        /// <summary>
        /// Converts the packet to a byte array that transmits on the wire.
        /// </summary>
        /// <returns>The byte array.</returns>
        public override byte[] ToBytes()
        {
            Asn1BerEncodingBuffer berEncoder = new Asn1BerEncodingBuffer();
            LdapV2.LDAPMessage ldapv2Msg = ldapMessagev2 as LdapV2.LDAPMessage;
            if (ldapv2Msg != null)
            {
                ldapv2Msg.BerEncode(berEncoder);
                return berEncoder.Data;
            }

            LdapV3.LDAPMessage ldapv3Msg = ldapMessagev3 as LdapV3.LDAPMessage;
            if (ldapv3Msg != null)
            {
                ldapv3Msg.BerEncode(berEncoder);
                return berEncoder.Data;
            }

            throw new StackException("The LDAP v2 and v3 messages cannot be both null");
        }
        /// <summary>
        /// Create and send FAST TGS request
        /// </summary>
        /// <param name="sName">Service principal name</param>
        /// <param name="kdcOptions">KDC options</param>
        /// <param name="innerSeqPaData">A sequence of preauthentication data in FAST request</param>
        /// <param name="outerSeqPaData">A sequence of preauthentication data</param>
        /// <param name="subKey">Sub-session key for authenticator in FAST armor field</param>
        /// <param name="fastOptions">FAST options</param>
        /// <param name="apOptions">AP options in FAST armor field</param>
        /// <param name="data">Authorization data</param>
        public void SendTgsRequestWithExplicitFast(
            string sName,
            KdcOptions kdcOptions,
            Asn1SequenceOf<PA_DATA> innerSeqPaData,
            Asn1SequenceOf<PA_DATA> outerSeqPaData,
            EncryptionKey subKey,
            FastOptions fastOptions,
            ApOptions apOptions,
            AuthorizationData data = null)
        {
            Context.Subkey = subKey;
            Context.ReplyKey = subKey;
            string domain = this.Context.Realm.Value;
            PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST),
                KerberosUtility.String2SeqKerbString(sName.Split('/')));

            KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sname, data);
            Asn1BerEncodingBuffer bodyBuffer = new Asn1BerEncodingBuffer();
            kdcReqBody.BerEncode(bodyBuffer);

            //Create PA-TGS-REQ
            APOptions option = new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.None));
            ChecksumType checksumType = KerberosUtility.GetChecksumType(Context.SelectedEType);
            KerberosApRequest apRequest = CreateApRequest(
                option,
                Context.Ticket,
                subKey,
                data,
                KeyUsageNumber.TG_REQ_PA_TGS_REQ_padataOR_AP_REQ_Authenticator,
                checksumType,
                bodyBuffer.Data);

            PaTgsReq paTgsReq = new PaTgsReq(apRequest.Request);

            Asn1SequenceOf<PA_DATA> tempPaData = null;
            if (outerSeqPaData == null || outerSeqPaData.Elements == null || outerSeqPaData.Elements.Length == 0)
            {
                tempPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paTgsReq.Data });
            }
            else
            {
                tempPaData.Elements = new PA_DATA[outerSeqPaData.Elements.Length + 1];
                Array.Copy(outerSeqPaData.Elements, tempPaData.Elements, outerSeqPaData.Elements.Length);
                tempPaData.Elements[outerSeqPaData.Elements.Length] = paTgsReq.Data;
            }
            //Create explicit FAST armor
            EncryptionKey explicitSubkey = KerberosUtility.MakeKey(
                Context.SelectedEType,
                "Password04!",
                "This is a salt");
            Authenticator plaintextAuthenticator = CreateAuthenticator(Context.ArmorTicket, null, explicitSubkey);
            KerberosApRequest apReq = new KerberosApRequest(Context.Pvno,
                new APOptions(KerberosUtility.ConvertInt2Flags((int)apOptions)),
                Context.ArmorTicket,
                plaintextAuthenticator,
                KeyUsageNumber.AP_REQ_Authenticator);
            FastArmorApRequest explicitArmor = new FastArmorApRequest(apReq.Request);

            //Create armor key
            var armorKey = GetArmorKey(Context.ArmorSessionKey, subKey, explicitSubkey);
            Context.FastArmorkey = armorKey;

            //Create PA-FX-FAST
            var pafxfast = CreateTgsPaFxFast(armorKey, Context.ArmorTicket, fastOptions, apOptions, tempPaData, sName, paTgsReq.Data.padata_value.ByteArrayValue, explicitArmor);

            PA_DATA[] elements;
            if (outerSeqPaData != null && outerSeqPaData.Elements.Length > 0)
            {
                elements = new PA_DATA[outerSeqPaData.Elements.Length + 1];
                Array.Copy(outerSeqPaData.Elements, elements, outerSeqPaData.Elements.Length);
                elements[outerSeqPaData.Elements.Length] = pafxfast.Data;
                elements[outerSeqPaData.Elements.Length + 1] = paTgsReq.Data;
            }
            else
            {
                elements = new PA_DATA[] { pafxfast.Data, paTgsReq.Data };
            }
            Asn1SequenceOf<PA_DATA> seqPaData = new Asn1SequenceOf<PA_DATA>();
            KerberosTgsRequest tgsRequest = new KerberosTgsRequest(KerberosConstValue.KERBEROSV5, kdcReqBody, new Asn1SequenceOf<PA_DATA>(elements), Context.TransportType);

            this.SendPdu(tgsRequest);
            this.testSite.Log.Add(LogEntryKind.Debug, "Send FAST TGS request.");
        }
        /// <summary>
        /// Create and send FAST TGS request
        /// </summary>
        /// <param name="sName">Service principal name</param>
        /// <param name="kdcOptions">KDC options</param>
        /// <param name="innerSeqPaData">A sequence of preauthentication data in FAST request</param>
        /// <param name="outerSeqPaData">A sequence of preauthentication data</param>
        /// <param name="subKey">Sub-session key for authenticator in FAST armor field</param>
        /// <param name="fastOptions">FAST options</param>
        /// <param name="apOptions">AP options in FAST armor field</param>
        /// <param name="data">Authorization data</param>
        public void SendTgsRequestWithFastHideCName(
            string sName,
            PrincipalName cName,
            KdcOptions kdcOptions,
            Asn1SequenceOf<PA_DATA> innerSeqPaData,
            Asn1SequenceOf<PA_DATA> outerSeqPaData,
            EncryptionKey subKey,
            ApOptions apOptions,
            AuthorizationData data = null)
        {
            var fastOptions = new Protocols.TestTools.StackSdk.Security.KerberosV5.Preauth.FastOptions(
                KerberosUtility.ConvertInt2Flags((int)FastOptionFlags.Hide_Client_Names));
            Context.Subkey = subKey;
            Context.ReplyKey = subKey;
            string domain = this.Context.Realm.Value;
            PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST),
                KerberosUtility.String2SeqKerbString(sName.Split('/')));

            KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sname, data);
            kdcReqBody.cname = cName;
            Asn1BerEncodingBuffer bodyBuffer = new Asn1BerEncodingBuffer();
            kdcReqBody.BerEncode(bodyBuffer);

            APOptions option = new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.None));
            ChecksumType checksumType = KerberosUtility.GetChecksumType(Context.SelectedEType);
            KerberosApRequest apRequest = CreateApRequest(
                option,
                Context.Ticket,
                subKey,
                data,
                KeyUsageNumber.TG_REQ_PA_TGS_REQ_padataOR_AP_REQ_Authenticator,
                checksumType,
                bodyBuffer.Data);

            PaTgsReq paTgsReq = new PaTgsReq(apRequest.Request);

            Asn1SequenceOf<PA_DATA> tempPaData = null;
            if (outerSeqPaData == null || outerSeqPaData.Elements == null || outerSeqPaData.Elements.Length == 0)
            {
                tempPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paTgsReq.Data });
            }
            else
            {
                tempPaData.Elements = new PA_DATA[outerSeqPaData.Elements.Length + 1];
                Array.Copy(outerSeqPaData.Elements, tempPaData.Elements, outerSeqPaData.Elements.Length);
                tempPaData.Elements[outerSeqPaData.Elements.Length] = paTgsReq.Data;
            }
            var armorKey = GetArmorKey(Context.SessionKey, subKey);
            var pafxfast = CreateTgsPaFxFast(armorKey, Context.Ticket, fastOptions, apOptions, tempPaData, sName, paTgsReq.Data.padata_value.ByteArrayValue);
            Context.FastArmorkey = armorKey;
            PA_DATA[] elements;
            if (outerSeqPaData != null && outerSeqPaData.Elements.Length > 0)
            {
                elements = new PA_DATA[outerSeqPaData.Elements.Length + 1];
                Array.Copy(outerSeqPaData.Elements, elements, outerSeqPaData.Elements.Length);
                elements[outerSeqPaData.Elements.Length] = pafxfast.Data;
                elements[outerSeqPaData.Elements.Length + 1] = paTgsReq.Data;
            }
            else
            {
                elements = new PA_DATA[] { pafxfast.Data, paTgsReq.Data };
            }
            Asn1SequenceOf<PA_DATA> seqPaData = new Asn1SequenceOf<PA_DATA>();
            KerberosTgsRequest tgsRequest = new KerberosTgsRequest(KerberosConstValue.KERBEROSV5, kdcReqBody, new Asn1SequenceOf<PA_DATA>(elements), Context.TransportType);

            this.SendPdu(tgsRequest);
            this.testSite.Log.Add(LogEntryKind.Debug, "Send FAST TGS request.");
        }
        private EncryptedData EncryptTicket(EncTicketPart encTicketPart, EncryptionKey serviceKey)
        {
            Asn1BerEncodingBuffer encodeBuffer = new Asn1BerEncodingBuffer();
            encTicketPart.BerEncode(encodeBuffer, true);
            byte[] encData = KerberosUtility.Encrypt(
                (EncryptionType)serviceKey.keytype.Value,
                serviceKey.keyvalue.ByteArrayValue,
                encodeBuffer.Data,
                (int)KeyUsageNumber.AS_REP_TicketAndTGS_REP_Ticket);

            return new EncryptedData(
                    new KerbInt32(serviceKey.keytype.Value),
                    null,
                    new Asn1OctetString(encData));
        }
 /// <summary>
 /// Encode this class into byte array.
 /// </summary>
 /// <returns>The byte array of the class.</returns>
 public override byte[] ToBytes()
 {
     Asn1BerEncodingBuffer asBerBuffer = new Asn1BerEncodingBuffer();
     this.Request.BerEncode(asBerBuffer, true);
     return asBerBuffer.Data;
 }
        private void Smb2KerberosAuthentication(CaseVariant variant)
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Initialize Kerberos Functional Client");
            KerberosFunctionalClient kerberosClient = new KerberosFunctionalClient(
                TestConfig.DomainName,
                TestConfig.UserName,
                TestConfig.UserPassword,
                KerberosAccountType.User,
                KDCIP,
                KDCPort,
                TransportType.TCP,
                OidPkt,
                BaseTestSite);

            #region Service Ticket
            EncryptionKey serviceKey;
            EncTicketPart encTicketPart = RetrieveAndDecryptServiceTicket(kerberosClient, out serviceKey);

            Ticket serviceTicket = kerberosClient.Context.Ticket.Ticket;

            Realm crealm = serviceTicket.realm;
            BaseTestSite.Assert.AreEqual(TestConfig.DomainName.ToLower(),
                encTicketPart.crealm.Value.ToLower(),
                "Realm name in service ticket encrypted part should match as expected, case insensitive");
            BaseTestSite.Assert.AreEqual(TestConfig.UserName.ToLower(),
                KerberosUtility.PrincipalName2String(encTicketPart.cname).ToLower(),
                "User name in service ticket encrypted part should match as expected, case insensitive.");

            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Add a type-unknown AuthorizationData to the ticket");
                AuthorizationDataElement unknownElement = GenerateUnKnownAuthorizationDataElement();
                AppendNewAuthDataElement(encTicketPart.authorization_data, unknownElement);
            }

            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT_OPTIONAL))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Add a type-unknown AuthorizationData which is inside AD_IF_RELEVANT to the ticket");
                AuthorizationDataElement unknownElement = GenerateUnKnownAuthorizationDataElement();
                AD_IF_RELEVANT ifRelavantElement =
                    new AD_IF_RELEVANT(new[] { unknownElement });
                var dataBuffer = new Asn1BerEncodingBuffer();
                ifRelavantElement.BerEncode(dataBuffer);
                AuthorizationDataElement unknownElementOptional =
                    new AuthorizationDataElement(new KerbInt32((long)AuthorizationData_elementType.AD_IF_RELEVANT), new Asn1OctetString(dataBuffer.Data));
                AppendNewAuthDataElement(encTicketPart.authorization_data, unknownElementOptional);
            }

            if (variant.HasFlag(CaseVariant.TICKET_NOT_VALID))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the Ticket start time to tomorrow");
                DateTime tomorrow = DateTime.Now.AddDays(1);
                string kerbTimeString = tomorrow.ToUniversalTime().ToString("yyyyMMddhhmmssZ");
                encTicketPart.starttime = new KerberosTime(kerbTimeString, true);
            }
            if (variant.HasFlag(CaseVariant.TICKET_EXPIRED))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the Ticket end time to yesterday");
                DateTime yesterday = DateTime.Now.AddDays(-1);
                string kerbTimeString = yesterday.ToUniversalTime().ToString("yyyyMMddhhmmssZ");
                encTicketPart.endtime = new KerberosTime(kerbTimeString, true);
            }

            if (variant.HasFlag(CaseVariant.TICKET_WRONG_ENC_KEY))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Modify the Ticket, making it encrypted with wrong key");
                serviceKey = KerberosUtility.GenerateKey(serviceKey);
            }

            EncryptedData data = EncryptTicket(encTicketPart, serviceKey);
            serviceTicket.enc_part = data;

            if (variant.HasFlag(CaseVariant.TICKET_WRONG_REALM))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the Realm in the Ticket to an unknown realm");
                serviceTicket.realm = new Realm("kerb.com");
            }
            if (variant.HasFlag(CaseVariant.TICKET_WRONG_SNAME))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the SNAME in the Ticket to an unknown service name");
                serviceTicket.sname = new PrincipalName(new KerbInt32((long)PrincipalType.NT_SRV_INST),
                    KerberosUtility.String2SeqKerbString("UnknownService", TestConfig.DomainName));
            }
            if (variant.HasFlag(CaseVariant.TICKET_WRONG_KVNO))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep,
                    "Change the KVNO in the Ticket to an invalid Key Version Number (Int32.MaxValue)");
                const int invalidKvno = System.Int32.MaxValue;
                serviceTicket.enc_part.kvno = new KerbInt32(invalidKvno);
            }
            #endregion

            #region Authenticator
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create Authenticator");
            EncryptionKey subkey = KerberosUtility.GenerateKey(kerberosClient.Context.SessionKey);
            PrincipalName cname;
            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_CNAME_NOT_MATCH))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Use wrong cname in the Authenticator");
                cname = new PrincipalName(new KerbInt32((long)PrincipalType.NT_PRINCIPAL),
                    KerberosUtility.String2SeqKerbString(TestConfig.NonAdminUserName, TestConfig.DomainName));
            }
            else
            {
                cname = kerberosClient.Context.CName.Name;
            }

            Authenticator authenticator = CreateAuthenticator(cname, crealm, subkey);
            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_CREALM_NOT_MATCH))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Use wrong crealm in the Authenticator");
                authenticator.crealm = new Realm("kerb.com");
            }

            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_EXCEED_TIME_SKEW))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the ctime in the Authenticator to one hour later");
                DateTime oneHourLater = DateTime.Now.AddHours(1);
                string kerbTimeString = oneHourLater.ToUniversalTime().ToString("yyyyMMddhhmmssZ");
                authenticator.ctime = new KerberosTime(kerbTimeString, true);
            }

            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Add a type-unknown AuthorizationData to the Authenticator");
                AuthorizationDataElement unknownElement = GenerateUnKnownAuthorizationDataElement();
                authenticator.authorization_data = new AuthorizationData(new[] { unknownElement });
            }

            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR_OPTIONAL))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep,
                    "Add a type-unknown AuthorizationData which is inside AD_IF_RELEVANT to the Authenticator");
                AuthorizationDataElement unknownElement = GenerateUnKnownAuthorizationDataElement();
                AD_IF_RELEVANT ifRelavantElement =
                    new AD_IF_RELEVANT(new[] { unknownElement });
                var dataBuffer = new Asn1BerEncodingBuffer();
                ifRelavantElement.BerEncode(dataBuffer);
                AuthorizationDataElement unknownElementOptional =
                    new AuthorizationDataElement(new KerbInt32((long)AuthorizationData_elementType.AD_IF_RELEVANT), new Asn1OctetString(dataBuffer.Data));
                authenticator.authorization_data = new AuthorizationData(new[] { unknownElementOptional });
            }

            #endregion

            #region AP Request
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create AP Request");
            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_WRONG_ENC_KEY))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Use wrong key to encrypt the Authenticator");
                kerberosClient.Context.Ticket.SessionKey = KerberosUtility.GenerateKey(kerberosClient.Context.Ticket.SessionKey);
            }
            KerberosApRequest request = new KerberosApRequest(
                kerberosClient.Context.Pvno,
                new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.MutualRequired)),
                kerberosClient.Context.Ticket,
                authenticator,
                KeyUsageNumber.AP_REQ_Authenticator
            );
            #endregion

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create GSS Token");
            byte[] token = KerberosUtility.AddGssApiTokenHeader(request, OidPkt, GssToken);

            Smb2FunctionalClientForKerbAuth smb2Client = new Smb2FunctionalClientForKerbAuth(TestConfig.Timeout, TestConfig, BaseTestSite);
            smb2Client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);

            #region Check the result

            byte[] repToken;
            uint status = DoSessionSetupWithGssToken(smb2Client, token, out repToken);

            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_CNAME_NOT_MATCH) || variant.HasFlag(CaseVariant.AUTHENTICATOR_CREALM_NOT_MATCH))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                    "Session Setup should fail because the cname or crealm in the authenticator does not match the same field in the Ticket");
                if (TestConfig.IsWindowsPlatform)
                {
                    KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken);
                    BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_BADMATCH, krbError.ErrorCode,
                        "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_BADMATCH);
                }
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_WRONG_ENC_KEY) || variant.HasFlag(CaseVariant.TICKET_WRONG_ENC_KEY))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                    "Session Setup should fail because Ticket or Authenticator cannot be correctly decrypted");
                if (TestConfig.IsWindowsPlatform)
                {
                    KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken);
                    BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_MODIFIED, krbError.ErrorCode,
                        "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_MODIFIED);
                }
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_EXCEED_TIME_SKEW))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                    "Session Setup should fail because the server time and the client time " +
                    "in the Authenticator differ by (1 hour) more than the allowable clock skew");
                if (TestConfig.IsWindowsPlatform)
                {
                    KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken);
                    BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_SKEW, krbError.ErrorCode,
                        "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_SKEW);
                }
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.TICKET_WRONG_KVNO) ||
                variant.HasFlag(CaseVariant.TICKET_WRONG_REALM) ||
                variant.HasFlag(CaseVariant.TICKET_WRONG_SNAME))
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "If decryption fails, server would try other keys");
            }
            if (variant.HasFlag(CaseVariant.TICKET_NOT_VALID))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                    "Session Setup should fail because the starttime (tomorrow) in the Ticket " +
                    "is later than the current time by more than the allowable clock skew");
                if (TestConfig.IsWindowsPlatform)
                {
                    KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken);
                    BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_TKT_NYV, krbError.ErrorCode,
                        "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_TKT_NYV);
                }
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.TICKET_EXPIRED))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                    "Session Setup should fail because the current time is later than the endtime (yesterday)" +
                    " in the Ticket by more than the allowable clock skew");
                if (TestConfig.IsWindowsPlatform)
                {
                    KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken);
                    BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_TKT_EXPIRED, krbError.ErrorCode,
                        "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_TKT_EXPIRED);
                }
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                    "Session Setup should fail because of the unknown AutherizationData in the ticket");
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR))
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment,
                    "Unknown AuthorizationData in the Authenticator should not fail the request");
            }
            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT_OPTIONAL) ||
                variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR_OPTIONAL))
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Unknown AuthorizationData in AD_IF_RELEVANT is optional. " +
                                                           "Server should not fail the request.");
            }

            KerberosApResponse apRep = kerberosClient.GetApResponseFromToken(repToken, GssToken);
            // Get subkey from AP response, which used for signing in smb2
            apRep.Decrypt(kerberosClient.Context.Ticket.SessionKey.keyvalue.ByteArrayValue);
            smb2Client.SetSessionSigningAndEncryption(true, false, apRep.ApEncPart.subkey.keyvalue.ByteArrayValue);

            string path = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            AccessFile(smb2Client, path);
            #endregion

            smb2Client.LogOff();
            smb2Client.Disconnect();
        }
        /// <summary>
        /// Encode the Krb Error to bytes
        /// </summary>
        /// <param name="buffer">The byte array to be decoded.</param>
        public override byte[] ToBytes()
        {
            Asn1BerEncodingBuffer errorBerBuffer = new Asn1BerEncodingBuffer();
            this.KrbError.BerEncode(errorBerBuffer, true);

            if (transportType == TransportType.TCP)
            {
                return KerberosUtility.WrapLength(errorBerBuffer.Data, true);
            }
            else
            {
                return errorBerBuffer.Data;
            }
        }
        public PaEncTimeStamp(string timeStamp, int usec, EncryptionType eType, string password, string salt)
        {
            this.TimeStamp = timeStamp;
            this.Usec = usec;
            byte[] key = KeyGenerator.MakeKey(eType, password, salt);
            this.Key = new EncryptionKey(new KerbInt32((long)eType), new Asn1OctetString(key));

            // create a timestamp
            PA_ENC_TS_ENC paEncTsEnc = new PA_ENC_TS_ENC(new KerberosTime(this.TimeStamp), new Microseconds(this.Usec));
            Asn1BerEncodingBuffer currTimeStampBuffer = new Asn1BerEncodingBuffer();
            paEncTsEnc.BerEncode(currTimeStampBuffer);
            var rawData = currTimeStampBuffer.Data;

            KerberosUtility.OnDumpMessage("KRB5:PA-ENC-TS-ENC",
                "Encrypted Timestamp Pre-authentication",
                KerberosUtility.DumpLevel.PartialMessage,
                rawData);
            // encrypt the timestamp
            byte[] encTimeStamp = KerberosUtility.Encrypt((EncryptionType)this.Key.keytype.Value,
                                                      this.Key.keyvalue.ByteArrayValue,
                                                      rawData,
                                                      (int)KeyUsageNumber.PA_ENC_TIMESTAMP);

            // create an encrypted timestamp
            PA_ENC_TIMESTAMP paEncTimeStamp =
                new PA_ENC_TIMESTAMP(new KerbInt32(this.Key.keytype.Value), null, new Asn1OctetString(encTimeStamp));
            Asn1BerEncodingBuffer paEncTimestampBuffer = new Asn1BerEncodingBuffer();
            paEncTimeStamp.BerEncode(paEncTimestampBuffer, true);

            Data = new PA_DATA(new KerbInt32((long)PaDataType.PA_ENC_TIMESTAMP), new Asn1OctetString(paEncTimestampBuffer.Data));
        }