public CLAIMS_SET? GetADUserClaims_SingleRealm(string realm, string user, string userPwd, string server, string servicePwd, string serviceSpn)
        {
            base.Logging();

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

            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            METHOD_DATA methodData;
            KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData);

            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with PaEncTimeStamp, PaPacRequest and paPacOptions.");
            string timeStamp = KerberosUtility.CurrentKerberosTime.Value;
            PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp,
                0,
                client.Context.SelectedEType,
                client.Context.CName.Password,
                this.client.Context.CName.Salt);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequest(options, seqOfPaData);
            KerberosAsResponse asResponse = client.ExpectAsResponse();

            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send FAST armored TGS request: {0}.", this.testConfig.LocalRealm.FileServer[0].Smb2ServiceName);
            Asn1SequenceOf<PA_DATA> seqOfPaData2 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paPacRequest.Data, paPacOptions.Data });
            client.SendTgsRequest(this.testConfig.LocalRealm.FileServer[0].Smb2ServiceName, options, seqOfPaData2);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();
            EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.FileServer[0].Smb2ServiceName, client.Context.Realm.ToString(), client.Context.SelectedEType);
            tgsResponse.DecryptTicket(key);
            BaseTestSite.Assert.IsNotNull(tgsResponse.EncPart, "The encrypted part of TGS-REP is decrypted.");

            if (this.testConfig.IsKileImplemented)
            {
                BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data.");
                AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements);
                BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac.");

                foreach (PacInfoBuffer buf in adWin2kPac.Pac.PacInfoBuffers)
                {
                    if (buf.GetType() == typeof(ClientClaimsInfo))
                    {
                        return ((ClientClaimsInfo)buf).NativeClaimSet;
                    }
                }
            }
            return null;
        }
        public void KrbErrorBadIntegrity()
        {
            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();

            // Modify ciphertext of TGT
            byte originalFirstByte = (byte)client.Context.Ticket.Ticket.enc_part.cipher.ByteArrayValue.GetValue(0);
            client.Context.Ticket.Ticket.enc_part.cipher.ByteArrayValue.SetValue((byte)(originalFirstByte + 1), 0);

            //Create and send TGS request
            client.SendTgsRequest(this.testConfig.LocalRealm.FileServer[0].Smb2ServiceName, options);
            krbError = client.ExpectKrbError();
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve Kerberos error.");
            BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_BAD_INTEGRITY, krbError.ErrorCode,
                "If decrypting the authenticator using the session key shows that it has been modified, " +
                "the KRB_AP_ERR_BAD_INTEGRITY error is returned");
        }
        public void AdFxFastArmorInAuthenticator()
        {
            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));

            AdFxFastArmor adFxFastArmor = new AdFxFastArmor();
            AuthorizationData authData = new AuthorizationData(new AuthorizationDataElement[] { adFxFastArmor.AuthDataElement });
            client.SendTgsRequest(testConfig.LocalRealm.ClientComputer.DefaultServiceName, options, null, null, authData);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Receive TGS Error, KDC MUST reject the request.");
            KerberosKrbError krbError = client.ExpectKrbError();
        }
        public void KerbAuth_Replay()
        {
            #region Get Service Ticket
            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);

            //Create and send AS request
            const KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            kerberosClient.SendAsRequest(options, null);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects Kerberos Error from KDC");
            //Receive preauthentication required error
            METHOD_DATA methodData;
            KerberosKrbError krbError = kerberosClient.ExpectPreauthRequiredError(out methodData);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client sends AS request with PA-DATA set");
            //Create sequence of PA data
            string timeStamp = KerberosUtility.CurrentKerberosTime.Value;
            PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp,
                0,
                kerberosClient.Context.SelectedEType,
                kerberosClient.Context.CName.Password,
                kerberosClient.Context.CName.Salt);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new[] { paEncTimeStamp.Data, paPacRequest.Data });
            //Create and send AS request
            kerberosClient.SendAsRequest(options, seqOfPaData);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects AS response from KDC");
            KerberosAsResponse asResponse = kerberosClient.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");

            //Create and send TGS request
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client sends TGS request to KDC");
            kerberosClient.SendTgsRequest(servicePrincipalName, options);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects TGS response from KDC");
            KerberosTgsResponse tgsResponse = kerberosClient.ExpectTgsResponse();

            BaseTestSite.Assert.AreEqual(servicePrincipalName,
                KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname),
                "Service principal name in service ticket should match expected.");
            #endregion

            #region Create AP request
            Ticket serviceTicket = kerberosClient.Context.Ticket.Ticket;
            Realm crealm = serviceTicket.realm;
            EncryptionKey subkey = KerberosUtility.GenerateKey(kerberosClient.Context.SessionKey);
            PrincipalName cname = kerberosClient.Context.CName.Name;
            Authenticator authenticator = CreateAuthenticator(cname, crealm, subkey);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create AP Request");
            KerberosApRequest request = new KerberosApRequest(
                kerberosClient.Context.Pvno,
                new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.MutualRequired)),
                kerberosClient.Context.Ticket,
                authenticator,
                KeyUsageNumber.AP_REQ_Authenticator
            );
            #endregion

            #region Create GSS token and send session setup request
            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);
            byte[] repToken;
            uint status = DoSessionSetupWithGssToken(smb2Client, token, out repToken);

            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);
            #endregion

            #region Second client
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Replay the request from another client");
            Smb2FunctionalClientForKerbAuth smb2Client2 = new Smb2FunctionalClientForKerbAuth(TestConfig.Timeout, TestConfig, BaseTestSite);
            smb2Client2.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            status = DoSessionSetupWithGssToken(smb2Client2, token, out repToken);

            BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                "Session Setup should fail because it uses a Replay of KRB_AP_REQ");

            if (TestConfig.IsWindowsPlatform)
            {
                krbError = kerberosClient.GetKrbErrorFromToken(repToken);
                BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_REPEAT, krbError.ErrorCode,
                    "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_REPEAT);
            }
            smb2Client2.Disconnect();
            #endregion

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

            smb2Client.LogOff();
            smb2Client.Disconnect();
        }
        public void DomainLocalGroupMembershipWithDisableResourceSIDCompressionSet()
        {
            base.Logging();

            //Create kerberos test client and connect
            client = new KerberosTestClient(
                this.testConfig.LocalRealm.RealmName,
                this.testConfig.LocalRealm.User[13].Username,
                this.testConfig.LocalRealm.User[13].Password,
                KerberosAccountType.User,
                testConfig.LocalRealm.KDC[0].IPAddress,
                testConfig.LocalRealm.KDC[0].Port,
                testConfig.TransportType,
                testConfig.SupportedOid);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Construct Kerberos client for testing."); //Create and send AS request

            // 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;
            }

            Adapter.PacHelper.commonUserFields commonUserFields = new Adapter.PacHelper.commonUserFields();
            if (this.testConfig.LocalRealm.KDC[0].IsWindows)
            {
                //Don't use the same user account for ldap querys, it will change the current user account attributes
                NetworkCredential cred = new NetworkCredential(this.testConfig.LocalRealm.Admin.Username, this.testConfig.LocalRealm.Admin.Password, this.testConfig.LocalRealm.RealmName);
                commonUserFields = Adapter.PacHelper.GetCommonUserFields(this.testConfig.LocalRealm.RealmName, this.testConfig.LocalRealm.User[13].Username, cred);
            }

            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with no PA data.");
            //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, this.client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.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.LocalResources[1].DefaultServiceName, options, seqOfPaData);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
                tgsResponse.Response.ticket.realm.Value.ToLower(),
                "The realm in ticket should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.LocalResources[1].DefaultServiceName,
               KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname),
               "The Service principal name in ticket should match expected.");

            tgsResponse.DecryptTicket(this.testConfig.LocalRealm.LocalResources[1].Password, this.testConfig.LocalRealm.LocalResources[1].ServiceSalt);
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
               tgsResponse.TicketEncPart.crealm.Value.ToLower(),
               "The realm in ticket encrypted part should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[13].Username.ToLower(),
                KerberosUtility.PrincipalName2String(tgsResponse.TicketEncPart.cname).ToLower(),
                "The client principal name in ticket encrypted part should match expected.");
            //Verify PAC
            if (this.testConfig.IsKileImplemented && this.testConfig.LocalRealm.KDC[0].IsWindows)
            {
                BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data.");
                AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements);
                BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac.");
                KerbValidationInfo kerbValidationInfo = null;
                foreach (var buf in adWin2kPac.Pac.PacInfoBuffers)
                {
                    if (buf is KerbValidationInfo)
                    {
                        kerbValidationInfo = buf as KerbValidationInfo;
                        break;
                    }
                }
                BaseTestSite.Assert.IsNotNull(kerbValidationInfo, "KerbValidationInfo is generated.");

                //sidcount =2 because, one for AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY SID and one for CLAIMS_VALID SID
                uint resourceGroupCount = this.testConfig.LocalRealm.ResourceGroups.GroupCount;
                uint expectedSidCount = 2 + resourceGroupCount;
                BaseTestSite.Assert.AreEqual(expectedSidCount, kerbValidationInfo.NativeKerbValidationInfo.SidCount, "The SidCount includes the number of one AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY, one CLAIMS_VALID and the number of localResourceGroup SIDs.");

                //BaseTestSite.Assert.IsNull(kerbValidationInfo.NativeKerbValidationInfo.ExtraSids, ".");

                KERB_SID_AND_ATTRIBUTES[] expectedDefaultExtraSids = new KERB_SID_AND_ATTRIBUTES[2];
                //The CLAIMS_VALID SID is "S-1-5-21-0-0-0-497"
                _RPC_SID CLAIMS_VALID = new _RPC_SID();
                CLAIMS_VALID.Revision = 0x01;
                CLAIMS_VALID.IdentifierAuthority = new _RPC_SID_IDENTIFIER_AUTHORITY();
                CLAIMS_VALID.IdentifierAuthority.Value = new byte[] { 0, 0, 0, 0, 0, 5 };
                CLAIMS_VALID.SubAuthorityCount = 5;
                CLAIMS_VALID.SubAuthority = new uint[] { 21, 0, 0, 0, 497 };
                expectedDefaultExtraSids[0] = new KERB_SID_AND_ATTRIBUTES();
                expectedDefaultExtraSids[0].Attributes = Attributes_Values.Mandatory | Attributes_Values.EnabledByDefault | Attributes_Values.Enabled;
                expectedDefaultExtraSids[0].SID = new _RPC_SID[1];
                expectedDefaultExtraSids[0].SID[0] = CLAIMS_VALID;

                //The AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY SID is "S-1-18-1"
                _RPC_SID AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY = new _RPC_SID();
                AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.Revision = 0x01;
                AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.IdentifierAuthority = new _RPC_SID_IDENTIFIER_AUTHORITY();
                AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.IdentifierAuthority.Value = new byte[] { 0, 0, 0, 0, 0, 18 };
                AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.SubAuthorityCount = 1;
                AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.SubAuthority = new uint[] { 1 };
                expectedDefaultExtraSids[1] = new KERB_SID_AND_ATTRIBUTES();
                expectedDefaultExtraSids[1].Attributes = Attributes_Values.Mandatory | Attributes_Values.EnabledByDefault | Attributes_Values.Enabled;
                expectedDefaultExtraSids[1].SID = new _RPC_SID[1];
                expectedDefaultExtraSids[1].SID[0] = AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY;

                Adapter.Group[] resourceGroups = this.testConfig.LocalRealm.ResourceGroups.Groups;
                NetworkCredential cred = new NetworkCredential(this.testConfig.LocalRealm.Admin.Username, this.testConfig.LocalRealm.Admin.Password, this.testConfig.LocalRealm.RealmName);
                KERB_SID_AND_ATTRIBUTES[] expectedResourceGroupExtraSids = Adapter.PacHelper.GetResourceGroupExtraSids(this.testConfig.LocalRealm.RealmName, cred, resourceGroupCount, resourceGroups);
                var expectedExtraSids = expectedDefaultExtraSids.Concat(expectedResourceGroupExtraSids).ToArray();

                var res = expectedSidCount;

                for (int i = 0; i < expectedSidCount; i++)
                {

                    for (int j = 0; j < expectedSidCount; j++)
                    {
                        if(Adapter.PacHelper.ExtraSidsAreEqual(expectedExtraSids[i], kerbValidationInfo.NativeKerbValidationInfo.ExtraSids[j]))
                        {
                            res--;
                        }
                    }
                }
                BaseTestSite.Assert.AreEqual((uint)0, res, "The ExtraSids field contains the pointer to a list which is the list copied from the PAC in the TGT plus a list constructed from the domain local groups...");
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Generate a GCC AP token for the given account and SPN.
        /// </summary>
        /// <param name="kdcIpAddr">KDC IP address</param>
        /// <param name="account">Account Name.</param>
        /// <param name="pwd">Password of the account.</param>
        /// <param name="domain">Domain name.</param>
        /// <param name="spn">SPN</param>
        /// <param name="aType">Account type</param>
        /// <returns>Token</returns>
        public static byte[] GenerateGssApToken(string kdcIpAddr, string account, string pwd, string domain, string spn, KerberosAccountType aType)
        {
            KerberosTestClient client = new KerberosTestClient(
                domain,
                account,
                pwd,
                KerberosAccountType.User,
                kdcIpAddr,
                88,
                Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.TransportType.TCP,
                (KerberosConstValue.OidPkt)Enum.Parse(typeof(KerberosConstValue.OidPkt), "MSKerberosToken"));

            //Create and send AS request
            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE | KdcOptions.OK_AS_DELEGATE;

            client.SendAsRequest(options, null);

            //Recieve preauthentication required error
            Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.METHOD_DATA methodData;
            KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData);

            //Create sequence of PA data
            string timeStamp = KerberosUtility.CurrentKerberosTime.Value;

            Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.PaEncTimeStamp paEncTimeStamp = new Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.PaEncTimeStamp(timeStamp, 0, client.Context.SelectedEType, client.Context.CName.Password, client.Context.CName.Salt);
            Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.PaPacRequest   paPacRequest   = new Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.PaPacRequest(true);
            Microsoft.Protocols.TestTools.StackSdk.Asn1.Asn1SequenceOf <PA_DATA>       seqOfPaData    = new Microsoft.Protocols.TestTools.StackSdk.Asn1.Asn1SequenceOf <PA_DATA>(new Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.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(spn, options);
            KerberosTgsResponse refTgsResponse = client.ExpectTgsResponse();


            // client.ChangeRealm(childDomain, childDcIp, 88, Microsoft.Protocols.TestTools.StackSdk.Security.Kerberos.TransportType.TCP);
            // client.SendTgsRequest(spn, options);
            // KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.AuthorizationData data   = null;
            Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.EncryptionKey     subkey = Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.KerberosUtility.GenerateKey(client.Context.SessionKey);
            byte[] token = client.CreateGssApiToken(Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.ApOptions.None,
                                                    data,
                                                    subkey,
                                                    Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.ChecksumFlags.None,
                                                    KerberosConstValue.GSSToken.GSSAPI
                                                    );

            return(token);
        }
Esempio n. 7
0
        /// <summary>
        /// Kerberos Client Initialize without server token
        /// </summary>
        private void ClientInitialize()
        {
            this.ApRequestAuthenticator = null;
            // Create and send AS request for pre-authentication
            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;

            KerberosTicket ticket = this.GetTGTCachedToken(this.credential, this.serverName);

            if (ticket == null)
            {
                this.SendAsRequest(options, null);

                // Expect recieve preauthentication required error
                METHOD_DATA methodData;
                this.ExpectPreauthRequiredError(out methodData);

                // Create sequence of PA data
                string         timeStamp      = KerberosUtility.CurrentKerberosTime.Value;
                PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp,
                                                                   0,
                                                                   this.Context.SelectedEType,
                                                                   this.Context.CName.Password,
                                                                   this.Context.CName.Salt);
                PaPacRequest             paPacRequest   = new PaPacRequest(true);
                PaPacOptions             paPacOptions   = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
                Asn1SequenceOf <PA_DATA> seqOfPaData_AS = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data });
                // Create and send AS request for TGT
                KerberosAsRequest asRequest = this.SendAsRequest(options, seqOfPaData_AS);

                // Expect TGT(AS) Response from KDC
                KerberosAsResponse asResponse = this.ExpectAsResponse();

                // Create and send TGS request
                Asn1SequenceOf <PA_DATA> seqOfPaData_TGS = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paPacRequest.Data, paPacOptions.Data });
                this.SendTgsRequest(this.serverName, options, seqOfPaData_TGS);

                // Expect TGS Response from KDC
                KerberosTgsResponse tgsResponse = this.ExpectTgsResponse();
                this.UpdateTGTCachedToken(this.Context.Ticket);
            }
            else
            {
                // Restore SessionKey and Ticket from cache
                this.Context.SessionKey    = ticket.SessionKey;
                this.Context.ApSessionKey  = ticket.SessionKey;
                this.Context.Ticket        = ticket;
                this.Context.SelectedEType = (EncryptionType)Context.Ticket.Ticket.enc_part.etype.Value;
            }

            // cache this.Context.Ticket;
            ApOptions apOption;

            GetFlagsByContextAttribute(out apOption);

            AuthorizationData data   = null;
            EncryptionKey     subkey = KerberosUtility.GenerateKey(this.client.Context.ContextKey);

            this.token = this.CreateGssApiToken(apOption,
                                                data,
                                                subkey,
                                                this.Context.ChecksumFlag,
                                                KerberosConstValue.GSSToken.GSSAPI);

            bool isMutualAuth = (contextAttribute & ClientSecurityContextAttribute.MutualAuth)
                                == ClientSecurityContextAttribute.MutualAuth;
            bool isDceStyle = (contextAttribute & ClientSecurityContextAttribute.DceStyle)
                              == ClientSecurityContextAttribute.DceStyle;

            if (isMutualAuth || isDceStyle)
            {
                this.needContinueProcessing = true;
            }
            else
            {
                this.needContinueProcessing = false;
            }
        }
        public void PacMarkedAdIfRelevant()
        {
            base.Logging();

            //Create kerberos test client and connect
            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;
            }

            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, this.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.ClientComputer.DefaultServiceName, options);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            //Verify PAC
            if (this.testConfig.IsKileImplemented)
            {
                EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType);
                tgsResponse.DecryptTicket(key);

                //tgsResponse.DecryptTicket(this.testConfig.LocalRealm.ClientComputer.Password, this.testConfig.LocalRealm.ClientComputer.ServiceSalt);
                BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data.");

                AdWin2KPac adWin2kPac = null;
                foreach (var element in tgsResponse.TicketEncPart.authorization_data.Elements)
                {
                    var authData = AuthDataElementParser.ParseAuthDataElement(element);
                    if (authData is AdIfRelevent)
                    {
                        AdIfRelevent adIfRelevent = authData as AdIfRelevent;
                        foreach (var subElement in adIfRelevent.Elements)
                        {
                            if (subElement is AdWin2KPac)
                            {
                                adWin2kPac = subElement as AdWin2KPac;
                                goto pacFound;
                            }
                        }
                    }
                }
            pacFound:
                BaseTestSite.Assert.IsNotNull(adWin2kPac, "AdWin2KPAC is marked as Ad-If-Relevent.");
            }
        }
        public void FastKrb_Error()
        {
            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
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with no PA data.");
            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve preauthentication required error.");
            METHOD_DATA methodData;
            KerberosKrbError krbError1 = client.ExpectPreauthRequiredError(out methodData);

            // AS_REQ and AS_REP using device principal
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with PaEncTimeStamp.");
            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);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve AS response.");
            KerberosAsResponse asResponse = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");
            BaseTestSite.Assert.IsNotNull(asResponse.EncPart, "The encrypted part of AS response is decrypted.");
            BaseTestSite.Assert.IsNotNull(asResponse.EncPart.key, "AS response should contain a session key.");
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                string.Format("The type of AS-REP encrypted part is {0}.", asResponse.EncPart.GetType().Name));

            // Switch to user principal
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Switch to user principal.");
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                string.Format("Construct Kerberos client using user account: {0}.",
                this.testConfig.LocalRealm.User[1].Username));
            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);

            // FAST armored AS_REQ and KRB-ERROR using user principal
            //Create a "random" key.
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send FAST armored AS request with no pre-authentication padata.");
            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
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with PaEncryptedChallenge.");
            var userKey = KerberosUtility.MakeKey(
                client.Context.SelectedEType,
                client.Context.CName.Password,
                client.Context.CName.Salt);

            var invalidKey = KerberosUtility.MakeKey(client.Context.SelectedEType, "Invalid", "this is a salt");
            PaEncryptedChallenge paEncTimeStamp3 = new PaEncryptedChallenge(
                client.Context.SelectedEType,
                KerberosUtility.CurrentKerberosTime.ToString(),
                0,
                invalidKey,
                userKey);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            Asn1SequenceOf<PA_DATA> outerSeqPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paPacRequest.Data });
            Asn1SequenceOf<PA_DATA> seqOfPaData3 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp3.Data });
            client.SendAsRequestWithFast(options, seqOfPaData3, outerSeqPaData, subkey, fastOptions, apOptions);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve AS response.");
            KerberosKrbError error = client.ExpectKrbError();

            BaseTestSite.Assert.IsNotNull(error.KrbError.e_data, "E_data is not null");
            Asn1SequenceOf<PA_DATA> seqOfPadata = new Asn1SequenceOf<PA_DATA>();
            seqOfPadata.BerDecode(new Asn1DecodingBuffer(error.KrbError.e_data.ByteArrayValue));
            var padataCount = seqOfPadata.Elements.Length;
            PaFxFastRep paFxFastRep = null;
            for (int i = 0; i < padataCount; i++)
            {
                var padata = PaDataParser.ParseRepPaData(seqOfPadata.Elements[i]);
                //Fix me: PaETypeInfo is also possible
                if (padata is PaFxFastRep)
                {
                    paFxFastRep = padata as PaFxFastRep;
                }
            }
            BaseTestSite.Assert.IsNotNull(paFxFastRep , "KDC must reply a PA-FX-Fast response.");
            PaFxError paFxError = null;
            var armoredRep = paFxFastRep.GetKerberosFastRep(client.Context.FastArmorkey);
            foreach (var padata in armoredRep.PaData)
            {
                if (padata is PaFxError)
                {
                    paFxError = padata as PaFxError;
                    break;
                }
            }
            BaseTestSite.Assert.IsNotNull(paFxError , "KDC must include a PA-FX-ERROR padata.");
            BaseTestSite.Assert.IsNull(paFxError.KrbError.KrbError.e_data, "E_data is null.");
        }
        public void RC4_CrossRealm_PAC_DEVICE_CLAIMS_INFO()
        {
            base.Logging();

            // Clear trust realm encryption type
            IClientControlAdapter adapter = BaseTestSite.GetAdapter<IClientControlAdapter>();
            adapter.ClearTrustRealmEncType();

            try
            {
                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);

                EncryptionType[] rc4HmacType = new EncryptionType[]
                {
                    EncryptionType.RC4_HMAC
                };

                // Define device principal client supported encryption type
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Set device principal client supported encryption type as RC4_HMAC.");
                client.SetSupportedEType(rc4HmacType);

                // 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;
                }

                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);
                BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

                //Create sequence of PA data
                string timeStamp = KerberosUtility.CurrentKerberosTime.Value;
                PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, this.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.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

                //Create and send TGS request

                client.SendTgsRequest(this.testConfig.TrustedRealm.KDC[0].DefaultServiceName, options);
                KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();
                BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

                KerberosTicket referralComputerTicket = client.Context.Ticket;
                EncryptionKey referralComputerSessionKey = client.Context.Ticket.SessionKey;

                //start
                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);

                // Define device principal client supported encryption type
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Set device principal client supported encryption type as RC4_HMAC.");
                client.SetSupportedEType(rc4HmacType);

                // 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
                options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
                client.SendAsRequest(options, null);
                KerberosKrbError krbError1 = client.ExpectPreauthRequiredError(out methodData);
                BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

                // AS_REQ and AS_REP using device principal
                timeStamp = KerberosUtility.CurrentKerberosTime.Value;
                paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt);
                seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data });
                client.SendAsRequest(options, seqOfPaData);
                asResponse = client.ExpectAsResponse();
                BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

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

                // Define user principal client supported encryption type
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Set user principal client supported encryption type as RC4_HMAC.");
                client.SetSupportedEType(rc4HmacType);

                // 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;
                string timeStamp2 = KerberosUtility.CurrentKerberosTime.Value;
                PaFxFastReq paFxFastReq = new PaFxFastReq(null);
                Asn1SequenceOf<PA_DATA> seqOfPaData2 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { (paFxFastReq.Data) });

                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.");
                BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

                // 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 });
                paPacRequest = new PaPacRequest(true);
                PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
                Asn1SequenceOf<PA_DATA> outerSeqPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paPacRequest.Data, paPacOptions.Data });
                client.SendAsRequestWithFast(options, seqOfPaData3, outerSeqPaData, subkey, fastOptions, apOptions);
                KerberosAsResponse userKrbAsRep = client.ExpectAsResponse();
                BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

                if (testConfig.IsClaimSupported)
                {
                    PaSupportedEncTypes paSupportedEncTypes = null;
                    foreach (var padata in userKrbAsRep.EncPart.pa_datas.Elements)
                    {
                        var parsedPadata = PaDataParser.ParseRepPaData(padata);
                        if (parsedPadata is PaSupportedEncTypes)
                            paSupportedEncTypes = parsedPadata as PaSupportedEncTypes;
                    }

                    BaseTestSite.Assert.IsNotNull(paSupportedEncTypes, "The encrypted padata of AS-REP contains PA_SUPPORTED_ENCTYPES.");
                    BaseTestSite.Assert.IsTrue(
                        paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.Claims_Supported),
                        "Claims is supported.");
                    BaseTestSite.Assert.IsTrue(
                        paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.FAST_Supported),
                        "FAST is supported.");
                }
                // FAST armored TGS_REQ and TGS_REP using user principal
                subkey = KerberosUtility.MakeKey(client.Context.SelectedEType, "Password03!", "this is a salt");

                client.Context.ArmorSessionKey = client.Context.Ticket.SessionKey;
                client.Context.ArmorTicket = client.Context.Ticket;

                if (this.testConfig.TrustType == Adapter.TrustType.Forest)
                {
                    client.SendTgsRequestWithExplicitFast(testConfig.TrustedRealm.FileServer[0].Smb2ServiceName,
                        options,
                        null,
                        null,
                        subkey,
                        fastOptions,
                        apOptions);
                }
                else if (this.testConfig.TrustType == Adapter.TrustType.Realm)
                {
                    client.SendTgsRequestWithExplicitFast(testConfig.TrustedRealm.KDC[0].DefaultServiceName,
                        options,
                        null,
                        null,
                        subkey,
                        fastOptions,
                        apOptions);
                }
                KerberosTgsResponse userKrbTgsRep = client.ExpectTgsResponse(KeyUsageNumber.TGS_REP_encrypted_part_subkey);
                BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

                client.ChangeRealm(this.testConfig.TrustedRealm.RealmName,
                this.testConfig.TrustedRealm.KDC[0].IPAddress,
                this.testConfig.TrustedRealm.KDC[0].Port,
                this.testConfig.TransportType);

                //Create and send referral TGS request
                client.Context.ArmorTicket = referralComputerTicket;
                client.Context.ArmorSessionKey = referralComputerTicket.SessionKey;
                client.SendTgsRequestWithExplicitFast(this.testConfig.TrustedRealm.FileServer[0].Smb2ServiceName, options, null, null, subkey, fastOptions, apOptions);
                KerberosTgsResponse refTgsResponse = client.ExpectTgsResponse(KeyUsageNumber.TGS_REP_encrypted_part_subkey);
                BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

                EncryptionKey key = testConfig.QueryKey(this.testConfig.TrustedRealm.FileServer[0].Smb2ServiceName, client.Context.Realm.ToString(), client.Context.SelectedEType);
                refTgsResponse.DecryptTicket(key);

                //Verify PAC
                if (testConfig.IsKileImplemented && testConfig.IsClaimSupported)
                {
                    BaseTestSite.Assert.IsNotNull(refTgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data.");
                    AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(refTgsResponse.TicketEncPart.authorization_data.Elements);
                    BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac.");

                    DeviceClaimsInfo deviceClaimsInfo = null;
                    foreach (var buf in adWin2kPac.Pac.PacInfoBuffers)
                    {
                        if (buf is DeviceClaimsInfo)
                        {
                            deviceClaimsInfo = buf as DeviceClaimsInfo;
                            break;
                        }
                    }
                    BaseTestSite.Assert.IsNotNull(deviceClaimsInfo, "PAC_DEVICE_CLAIM_INFO should be generated.");
                }
            }
            finally
            {
                adapter.SetTrustRealmEncTypeAsAes();
            }
        }
        public void APDS_KERBEROS_PAC_VALIDATION()
        {
            base.Logging();

            BaseTestSite.Log.Add(LogEntryKind.Comment, "Construct Kerberos client for testing.");
            client = new KerberosTestClient(
                this.testConfig.LocalRealm.RealmName,
                this.testConfig.LocalRealm.Admin.Username,
                this.testConfig.LocalRealm.Admin.Password,
                KerberosAccountType.User,
                testConfig.LocalRealm.KDC[0].IPAddress,
                testConfig.LocalRealm.KDC[0].Port,
                testConfig.TransportType,
                testConfig.SupportedOid);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with no PA data.");
            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, this.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});
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with PA data.");
            client.SendAsRequest(options, seqOfPaData);
            KerberosAsResponse asResponse = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send TGS request.");
            client.SendTgsRequest(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName, options);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();
            EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType);
            tgsResponse.DecryptTicket(key);

            if (this.testConfig.IsKileImplemented)
            {
                //Get Server and KDC Signatures
                PacServerSignature pacServerSignature = null;
                PacKdcSignature pacKdcSignature = null;
                BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data.");
                AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements);
                BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac.");
                foreach (var buf in adWin2kPac.Pac.PacInfoBuffers)
                {
                    if (buf is PacServerSignature)
                    {
                        pacServerSignature = buf as PacServerSignature;
                    }
                    if (buf is PacKdcSignature)
                    {
                        pacKdcSignature = buf as PacKdcSignature;
                    }
                }

                BaseTestSite.Log.Add(LogEntryKind.Comment, "Establish Secure Channel.");
                NrpcClient nrpcClient = NrpcClient.CreateNrpcClient(this.testConfig.LocalRealm.RealmName);
                ushort[] endPointList = NrpcUtility.QueryNrpcTcpEndpoint(testConfig.LocalRealm.KDC[0].FQDN);
                ushort endPoint = endPointList[0];
                MachineAccountCredential machineCredential = new MachineAccountCredential(
                    this.testConfig.LocalRealm.RealmName,
                    testConfig.LocalRealm.ClientComputer.FQDN.Split('.')[0],
                    testConfig.LocalRealm.ClientComputer.Password);

                nrpcClient.Context.NegotiateFlags = NrpcNegotiateFlags.SupportsAESAndSHA2
                    | NrpcNegotiateFlags.SupportsConcurrentRpcCalls
                    | NrpcNegotiateFlags.SupportsCrossForestTrusts
                    | NrpcNegotiateFlags.SupportsGenericPassThroughAuthentication
                    | NrpcNegotiateFlags.SupportsNetrLogonGetDomainInfo
                    | NrpcNegotiateFlags.SupportsNetrLogonSendToSam
                    | NrpcNegotiateFlags.SupportsNetrServerPasswordSet2
                    | NrpcNegotiateFlags.SupportsRC4
                    | NrpcNegotiateFlags.SupportsRefusePasswordChange
                    | NrpcNegotiateFlags.SupportsRodcPassThroughToDifferentDomains
                    | NrpcNegotiateFlags.SupportsSecureRpc
                    | NrpcNegotiateFlags.SupportsStrongKeys
                    | NrpcNegotiateFlags.SupportsTransitiveTrusts;

                NrpcClientSecurityContext securityContext = new NrpcClientSecurityContext(
                    this.testConfig.LocalRealm.RealmName,
                    testConfig.LocalRealm.KDC[0].FQDN.Split('.')[0],
                    machineCredential,
                    true,
                    nrpcClient.Context.NegotiateFlags);

                nrpcClient.BindOverTcp(testConfig.LocalRealm.KDC[0].FQDN, endPoint, securityContext, TimeSpan.FromMilliseconds(600000));

                _NETLOGON_LOGON_INFO_CLASS logonLevel = _NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation;
                _NETLOGON_VALIDATION_INFO_CLASS validationLevel = _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2;
                _NETLOGON_VALIDATION? validationInfomation;
                byte? authoritative;
                NrpcNetrLogonSamLogonExtraFlags? extraFlags = NrpcNetrLogonSamLogonExtraFlags.None;

                BaseTestSite.Log.Add(LogEntryKind.Comment, "Create valid KERB_VERIFY_PAC_REQUEST.");
                KERB_VERIFY_PAC_REQUEST kerberosReq = ApdsUtility.CreateKerbVerifyPacRequest(pacServerSignature.NativePacSignatureData, pacKdcSignature.NativePacSignatureData);
                //Create Kerberos Validation Logon Info
                _NETLOGON_LEVEL netlogonLevel = ApdsUtility.CreatePacLogonInfo(
                    NrpcParameterControlFlags.AllowLogonWithComputerAccount,
                    this.testConfig.LocalRealm.RealmName,
                    this.testConfig.LocalRealm.Admin.Username,
                    testConfig.LocalRealm.KDC[0].FQDN.Split('.')[0],
                    kerberosReq);
                _NETLOGON_LEVEL encryptedLogonLevel = nrpcClient.EncryptNetlogonLevel(
                    (_NETLOGON_LOGON_INFO_CLASS)logonLevel,
                    netlogonLevel);
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Call NetrLogonSamLogonEx for Kerberos pac validation.");
                NtStatus result = nrpcClient.NetrLogonSamLogonEx(
                    nrpcClient.Handle,
                    testConfig.LocalRealm.KDC[0].FQDN.Split('.')[0],
                    testConfig.LocalRealm.ClientComputer.FQDN.Split('.')[0],
                    logonLevel,
                    encryptedLogonLevel,
                    validationLevel,
                    out validationInfomation,
                    out authoritative,
                    ref extraFlags);
                BaseTestSite.Assert.AreEqual(NtStatus.STATUS_SUCCESS, result, "[MS-APDS]3.2.5.2 If the checksum is verified, the DC MUST return STATUS_SUCCESS.");
                BaseTestSite.Assert.IsNull(validationInfomation.Value.ValidationGeneric2[0].ValidationData, "[MS-APDS]3.2.5.2 There is no return message.");

                BaseTestSite.Log.Add(LogEntryKind.Comment, "Create invalid KERB_VERIFY_PAC_REQUEST.");
                kerberosReq = ApdsUtility.CreateKerbVerifyPacRequest(pacKdcSignature.NativePacSignatureData, pacKdcSignature.NativePacSignatureData);
                //Create Kerberos Validation Logon Info
                netlogonLevel = ApdsUtility.CreatePacLogonInfo(
                    NrpcParameterControlFlags.AllowLogonWithComputerAccount,
                    this.testConfig.LocalRealm.RealmName,
                    this.testConfig.LocalRealm.Admin.Username,
                    testConfig.LocalRealm.KDC[0].FQDN.Split('.')[0],
                    kerberosReq);
                encryptedLogonLevel = nrpcClient.EncryptNetlogonLevel(
                    (_NETLOGON_LOGON_INFO_CLASS)logonLevel,
                    netlogonLevel);
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Call NetrLogonSamLogonEx for Kerberos pac validation.");
                result = nrpcClient.NetrLogonSamLogonEx(
                    nrpcClient.Handle,
                    testConfig.LocalRealm.KDC[0].FQDN.Split('.')[0],
                    testConfig.LocalRealm.ClientComputer.FQDN.Split('.')[0],
                    logonLevel,
                    encryptedLogonLevel,
                    validationLevel,
                    out validationInfomation,
                    out authoritative,
                    ref extraFlags);
                BaseTestSite.Assert.AreEqual(NtStatus.STATUS_LOGON_FAILURE, result, "[MS-APDS]3.2.5.2 If the checksum verification fails, the DC MUST return an error code, STATUS_LOGON_FAILURE (section 2.2) as the return value to the Netlogon Generic Pass-through method.");
            }
        }
        public void Protected_Users_Interactive_Logon_User_A2AF_Succeed()
        {
            base.Logging();

            //Section 3.3.5.6: Authentication Policies are not supported by Windows 2000, Windows Server 2003, Windows Server 2008, Windows Server 2008 R2, or Windows Server 2012 KDCs.
            if (int.Parse(this.testConfig.LocalRealm.DomainControllerFunctionality) < 6)
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Section 3.3.5.6: Authentication Policies are not supported by Windows 2000, Windows Server 2003, Windows Server 2008, Windows Server 2008 R2, or Windows Server 2012 KDCs.");
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Will exit the case immediately.");
                return;
            }

            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);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequest(options, seqOfPaData);
            KerberosAsResponse asResponse = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");
            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[16].Username,
                this.testConfig.LocalRealm.User[16].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[] { paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequestWithFast(options, seqOfPaData2, null, subkey, fastOptions, apOptions);
            KerberosKrbError krbError2 = client.ExpectKrbError();
            BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED, krbError2.ErrorCode, "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, paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequestWithFast(options, seqOfPaData3, null, subkey, fastOptions, apOptions);
            KerberosAsResponse userKrbAsRep = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(userKrbAsRep.Response.ticket, "AS response should contain a TGT.");
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                string.Format("The type of AS-REP encrypted part is {0}.", userKrbAsRep.EncPart.GetType().Name));

            //verify flags in as reponse
            int flags = KerberosUtility.ConvertFlags2Int(asResponse.EncPart.flags.ByteArrayValue);
            BaseTestSite.Assert.AreEqual((EncTicketFlags)0,
                EncTicketFlags.FORWARDABLE & EncTicketFlags.PROXIABLE & (EncTicketFlags)flags,
                "Section  3.3.5.1: " +
                "If DelegationNotAllowed is set to TRUE on the principal, " +
                "(or if domainControllerFunctionality returns a value >= 6 ([MS-ADTS] section 3.1.1.3.2.25) and the principal is a member of PROTECTED_USERS ([MS-DTYP] section 2.4.2.4)), " +
                "the KILE KDC MUST NOT set the PROXIABLE or FORWARDABLE ticket flags ([RFC4120] sections 2.5 and 2.6)."
                );

            //Get user linked authentication policy attribute
            string attributeDN = this.sutController.getAccountAttributeDN(
                this.testConfig.LocalRealm.RealmName.ToLower().Substring(0, this.testConfig.LocalRealm.RealmName.Length - 4),
                this.testConfig.LocalRealm.User[16].Username,
                "Users",
                "msDS-AssignedAuthNPolicy",
                this.testConfig.LocalRealm.Admin.Username,
                this.testConfig.LocalRealm.Admin.Password
                );

            //Get authentication policy TGT lifetime

            // if policy not config the TGT life time, use the default value 4 hours for protected users.
            // if not a protected user, use the default value 10 hours by DC group policy defined.
            double? policyTGTLifetime4User = 4 * 36000000000;

            if (attributeDN != null)
            {
                char seperator = ',';
                string userLinkedPolicyName = attributeDN.Substring(3, attributeDN.IndexOf(seperator) - 3);

                //Get Authentication Policy User's TGT lifetime
                policyTGTLifetime4User = this.sutController.getAuthPolicyTGTLifeTime(
                    this.testConfig.LocalRealm.RealmName.ToLower().Substring(0, this.testConfig.LocalRealm.RealmName.Length - 4),
                    userLinkedPolicyName,
                    "msds-UserTGTLifetime",
                    this.testConfig.LocalRealm.Admin.Username,
                    this.testConfig.LocalRealm.Admin.Password
                    );

                if (policyTGTLifetime4User == null)
                {
                    // if policy not config the TGT life time, use the default value 4 hours for protected users.
                    // if not a protected user, use the default value 10 hours by DC group policy defined.
                    policyTGTLifetime4User = 4 * 36000000000;
                }

            }

            // if policy not config the TGT life time, use the default value 4 hours for protected users.
            // if not a protected user, use the default value 10 hours by DC group policy defined.
            double? policyTGTLifetime4Computer = 4 * 36000000000;

            attributeDN = this.sutController.getAccountAttributeDN(
                this.testConfig.LocalRealm.RealmName.ToLower().Substring(0, this.testConfig.LocalRealm.RealmName.Length - 4),
                this.testConfig.LocalRealm.ClientComputer.NetBiosName.Substring(0, this.testConfig.LocalRealm.ClientComputer.NetBiosName.Length - 1),
                "Computers",
                "msDS-AssignedAuthNPolicy",
                this.testConfig.LocalRealm.Admin.Username,
                this.testConfig.LocalRealm.Admin.Password
            );

            if (attributeDN != null)
            {
                char seperator = ',';
                string userLinkedPolicyName = attributeDN.Substring(3, attributeDN.IndexOf(seperator) - 3);

                //Get Authentication Policy Computer's TGT lifetime
                policyTGTLifetime4Computer = this.sutController.getAuthPolicyTGTLifeTime(
                    this.testConfig.LocalRealm.RealmName.ToLower().Substring(0, this.testConfig.LocalRealm.RealmName.Length - 4),
                    userLinkedPolicyName,
                    "msds-ComputerTGTLifetime",
                    this.testConfig.LocalRealm.Admin.Username,
                    this.testConfig.LocalRealm.Admin.Password
                    );
                if (policyTGTLifetime4Computer == null)
                {
                    policyTGTLifetime4Computer = 4 * 36000000000;
                }

            }

            //Get TGTlifetime from ticket received
            DateTime startTime = DateTime.ParseExact(
                asResponse.EncPart.starttime.ToString(),
                "yyyyMMddHHmmssZ",
                System.Globalization.CultureInfo.InvariantCulture
                );
            DateTime endTime = DateTime.ParseExact(
                asResponse.EncPart.endtime.ToString(),
                "yyyyMMddHHmmssZ",
                System.Globalization.CultureInfo.InvariantCulture
                );
            DateTime renewTime = DateTime.ParseExact(
                asResponse.EncPart.renew_till.ToString(),
                "yyyyMMddHHmmssZ",
                System.Globalization.CultureInfo.InvariantCulture
                );
            //get timespan
            TimeSpan maxTGTlife = endTime - startTime;
            TimeSpan maxRenewTime = renewTime - startTime;

            double? maxTGTlifeTimeSpan = maxTGTlife.Ticks;
            double? maxRenewTimeSpan = maxRenewTime.Ticks;

            //verify MaxRenewAge and MaxTicketAge for the TGT
            BaseTestSite.Assert.AreEqual(
                policyTGTLifetime4Computer, // as response is encrypted by computer's key
                maxTGTlifeTimeSpan,
                "Section 3.3.5.6 MaxTicketAge (section 3.3.1) for the TGT is 4 hours unless specified by policy. " +
                "If TGTLifetime is not 0: MaxTicketAge for the TGT is TGTLifetime."
                );

            BaseTestSite.Assert.AreEqual(
                policyTGTLifetime4Computer,
                maxRenewTimeSpan,
                "Section 3.3.5.6 MaxRenewAge (section 3.3.1) for the TGT is 4 hours unless specified by policy. " +
                "If TGTLifetime is not 0: MaxRenewAge for the TGT is TGTLifetime."
                );

            // verify the PA-DATA of AS_REP: asResponse.EncPart.pa_datas as PA_SUPPORTED_ENCTYPES
            bool isExistPaSupportedEncTypes = false;
            bool isExistPadataValue = false;

            var padataCount = userKrbAsRep.EncPart.pa_datas.Elements.Length;
            for (int i = 0; i < padataCount; i++)
            {
                var padata = PaDataParser.ParseRepPaData(userKrbAsRep.EncPart.pa_datas.Elements[i]);
                if ((PaDataType)padata.Data.padata_type.Value == PaDataType.PA_SUPPORTED_ENCTYPES)
                {
                    isExistPaSupportedEncTypes = true;
                    for (int j = 0; j < padata.Data.padata_value.Value.Length; j++)
                    {
                        if (padata.Data.padata_value.Value[j]==0x1F)
                        {
                            isExistPadataValue = true;
                        }
                    }
                }
            }
            BaseTestSite.Assert.IsTrue(isExistPaSupportedEncTypes, "If domainControllerFunctionality returns a value >= 3:" +
                 "the KDC SHOULD, in the encrypted pre-auth data part ([Referrals-11], Appendix A) of the AS-REP message, " +
                 "include PA-DATA with the padata-type set to PA-SUPPORTED-ENCTYPES (165).");

            BaseTestSite.Assert.IsTrue(isExistPadataValue, "If domainControllerFunctionality returns a value >= 3: " +
                "the KDC SHOULD, in the encrypted pre-auth data part ([Referrals-11], Appendix A) of the AS-REP message, " +
                "include PA-DATA with the padata-type set to PA-SUPPORTED-ENCTYPES (165), and the padata-value set to 0x1F (section 2.2.6).");
            if (testConfig.IsClaimSupported)
            {
                PaSupportedEncTypes paSupportedEncTypes = null;
               // userKrbAsRep.EncPart.pa_datas.GetType

                foreach (var padata in userKrbAsRep.EncPart.pa_datas.Elements)
                {
                    var parsedPadata = PaDataParser.ParseRepPaData(padata);
                    if (parsedPadata is PaSupportedEncTypes)
                        paSupportedEncTypes = parsedPadata as PaSupportedEncTypes;
                }

                BaseTestSite.Assert.IsNotNull(paSupportedEncTypes, "The encrypted padata of AS-REP contains PA_SUPPORTED_ENCTYPES.");
                BaseTestSite.Assert.IsTrue(
                    paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.Claims_Supported),
                    "Claims is supported.");
                BaseTestSite.Assert.IsTrue(
                    paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.FAST_Supported),
                    "FAST is supported.");
            }

            // FAST armored TGS_REQ and TGS_REP using user principal
            subkey = KerberosUtility.MakeKey(client.Context.SelectedEType, "Password03!", "this is a salt");
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send FAST armored TGS request.");
            client.SendTgsRequestWithFast(testConfig.LocalRealm.ClientComputer.DefaultServiceName, options, null, null, subkey, fastOptions, apOptions);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve TGS response.");
            KerberosTgsResponse userKrbTgsRep = client.ExpectTgsResponse(KeyUsageNumber.TGS_REP_encrypted_part_subkey);

            BaseTestSite.Assert.IsNotNull(userKrbTgsRep.Response, "The Response pare of TGS-REP is not null.");
            BaseTestSite.Assert.IsNotNull(userKrbTgsRep.Response.padata, "The Padata of TGS-REP is not null.");

            EncryptionKey strengthenKey = null;
            foreach (PA_DATA paData in userKrbTgsRep.Response.padata.Elements)
            {
                var parsedPaData = PaDataParser.ParseRepPaData(paData);
                if (parsedPaData is PaFxFastRep)
                {
                    var armoredRep = ((PaFxFastRep)parsedPaData).GetArmoredRep();
                    var kerbRep = ((PaFxFastRep)parsedPaData).GetKerberosFastRep(client.Context.FastArmorkey);
                    strengthenKey = kerbRep.FastResponse.strengthen_key;
                }
            }
            BaseTestSite.Assert.IsNotNull(strengthenKey, "Strengthen key field must be set in TGS-REP.");

            BaseTestSite.Assert.IsNotNull(userKrbTgsRep.EncPart, "The encrypted part of TGS-REP is decrypted.");
        }
        public void Protected_Users_Network_Logon_Computer_A2A2_Fail()
        {
            base.Logging();

            //Section 3.3.5.6: Authentication Policies are not supported by Windows 2000, Windows Server 2003, Windows Server 2008, Windows Server 2008 R2, or Windows Server 2012 KDCs.
            if (int.Parse(this.testConfig.LocalRealm.DomainControllerFunctionality) < 6)
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Section 3.3.5.6: Authentication Policies are not supported by Windows 2000, Windows Server 2003, Windows Server 2008, Windows Server 2008 R2, or Windows Server 2012 KDCs.");
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Will exit the case immediately.");
                return;
            }

            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);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequest(options, seqOfPaData);
            KerberosAsResponse asResponse = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");
            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[17].Username,
                this.testConfig.LocalRealm.User[17].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[] { paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequestWithFast(options, seqOfPaData2, null, subkey, fastOptions, apOptions);
            KerberosKrbError krbError = client.ExpectKrbError();
            BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED, krbError.ErrorCode, "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, paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequestWithFast(options, seqOfPaData3, null, subkey, fastOptions, apOptions);

            //receive as response
            KerberosAsResponse userKrbAsRep = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(userKrbAsRep.Response.ticket, "AS response should contain a TGT.");
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                string.Format("The type of AS-REP encrypted part is {0}.", userKrbAsRep.EncPart.GetType().Name));

            // verify the PA-DATA of AS_REP: asResponse.EncPart.pa_datas as PA_SUPPORTED_ENCTYPES
            bool isExistPaSupportedEncTypes = false;
            bool isExistPadataValue = false;

            var padataCount = userKrbAsRep.EncPart.pa_datas.Elements.Length;
            for (int i = 0; i < padataCount; i++)
            {
                var padata = PaDataParser.ParseRepPaData(userKrbAsRep.EncPart.pa_datas.Elements[i]);
                if ((PaDataType)padata.Data.padata_type.Value == PaDataType.PA_SUPPORTED_ENCTYPES)
                {
                    isExistPaSupportedEncTypes = true;
                    for (int j = 0; j < padata.Data.padata_value.Value.Length; j++)
                    {
                        if (padata.Data.padata_value.Value[j] == 0x1F)
                        {
                            isExistPadataValue = true;
                        }
                    }
                }
            }
            BaseTestSite.Assert.IsTrue(isExistPaSupportedEncTypes, "If domainControllerFunctionality returns a value >= 3:" +
                "the KDC SHOULD, in the encrypted pre-auth data part ([Referrals-11], Appendix A) of the AS-REP message, " +
                "include PA-DATA with the padata-type set to PA-SUPPORTED-ENCTYPES (165).");

            BaseTestSite.Assert.IsTrue(isExistPadataValue, "If domainControllerFunctionality returns a value >= 3: " +
                "the KDC SHOULD, in the encrypted pre-auth data part ([Referrals-11], Appendix A) of the AS-REP message, " +
                "include PA-DATA with the padata-type set to PA-SUPPORTED-ENCTYPES (165), and the padata-value set to 0x1F (section 2.2.6).");
            if (testConfig.IsClaimSupported)
            {
                PaSupportedEncTypes paSupportedEncTypes = null;
                // userKrbAsRep.EncPart.pa_datas.GetType

                foreach (var padata in userKrbAsRep.EncPart.pa_datas.Elements)
                {
                    var parsedPadata = PaDataParser.ParseRepPaData(padata);
                    if (parsedPadata is PaSupportedEncTypes)
                        paSupportedEncTypes = parsedPadata as PaSupportedEncTypes;
                }

                BaseTestSite.Assert.IsNotNull(paSupportedEncTypes, "The encrypted padata of AS-REP contains PA_SUPPORTED_ENCTYPES.");
                BaseTestSite.Assert.IsTrue(
                    paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.Claims_Supported),
                    "Claims is supported.");
                BaseTestSite.Assert.IsTrue(
                    paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.FAST_Supported),
                    "FAST is supported.");
            }

            // FAST armored TGS_REQ and TGS_REP using user principal
            subkey = KerberosUtility.MakeKey(client.Context.SelectedEType, "Password03!", "this is a salt");
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send FAST armored TGS request.");
            client.SendTgsRequestWithFast(testConfig.LocalRealm.FileServer[0].Smb2ServiceName, options, null, null, subkey, fastOptions, apOptions);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve TGS response.");
            krbError = client.ExpectKrbError();

            // Access check with Computer's A2A2 failed, KDC will return the KDC_ERR_POLICY error.
            BaseTestSite.Assert.AreEqual(
                KRB_ERROR_CODE.KDC_ERR_POLICY,
                krbError.ErrorCode,
                "Section 3.3.5.7 TGS Exchange: " +
                "If AllowedToAuthenticateFrom is not NULL, the PAC of the armor TGT MUST be used to perform an access check for the ACTRL_DS_CONTROL_ACCESS right with additional rights GUID against the AllowedToAuthenticateFrom." +
                "If the access check fails, the KDC MUST return KDC_ERR_POLICY."
                );
        }
        public void Protected_Users_Interactive_Logon_User_A2AF_Fail()
        {
            base.Logging();

            //Section 3.3.5.6: Authentication Policies are not supported by Windows 2000, Windows Server 2003, Windows Server 2008, Windows Server 2008 R2, or Windows Server 2012 KDCs.
            if (int.Parse(this.testConfig.LocalRealm.DomainControllerFunctionality) < 6)
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Section 3.3.5.6: Authentication Policies are not supported by Windows 2000, Windows Server 2003, Windows Server 2008, Windows Server 2008 R2, or Windows Server 2012 KDCs.");
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Will exit the case immediately.");
                return;
            }

            //TODO: Consider to udpate Client computer's department attribute and then interactive log on to client computer

            client = new KerberosTestClient(
                this.testConfig.LocalRealm.RealmName,
                this.testConfig.LocalRealm.FileServer[0].NetBiosName,
                this.testConfig.LocalRealm.FileServer[0].Password,
                KerberosAccountType.Device,
                testConfig.LocalRealm.KDC[0].IPAddress,
                testConfig.LocalRealm.KDC[0].Port,
                testConfig.TransportType,
                testConfig.SupportedOid,
               testConfig.LocalRealm.FileServer[0].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);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequest(options, seqOfPaData);
            KerberosAsResponse asResponse = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");
            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[16].Username,
                this.testConfig.LocalRealm.User[16].Password,
                KerberosAccountType.User,
                client.Context.Ticket,
                client.Context.SessionKey,
                testConfig.LocalRealm.KDC[0].IPAddress,
                testConfig.LocalRealm.KDC[0].Port,
                testConfig.TransportType,
                testConfig.SupportedOid);

            // 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[] { paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequestWithFast(options, seqOfPaData2, null, subkey, fastOptions, apOptions);
            KerberosKrbError krbError2 = client.ExpectKrbError();

            // Access check with User's A2AF failed, KDC will return the KDC_ERR_POLICY error.
            BaseTestSite.Assert.AreEqual(
                KRB_ERROR_CODE.KDC_ERR_POLICY,
                krbError2.ErrorCode,
                "Section 3.3.5.6 As Exchange " +
                "If AllowedToAuthenticateFrom is not NULL, the PAC of the armor TGT MUST be used to perform an access check for the ACTRL_DS_CONTROL_ACCESS right with additional rights GUID against the AllowedToAuthenticateFrom. " +
                "If the access check fails, the KDC MUST return KDC_ERR_POLICY."
                );
        }
        public void Protected_Users_DES_PreAuthentication_Fail()
        {
            base.Logging();
            //Section 3.3.5.6: PROTECTED_USERS is not supported by Windows 2000, Windows Server 2003, Windows Server 2008, Windows Server 2008 R2, or Windows Server 2012 KDCs.
            if (int.Parse(this.testConfig.LocalRealm.DomainControllerFunctionality) < 6)
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Section 3.3.5.6: PROTECTED_USERS is not supported in Windows 2000, Windows Server 2003, Windows Server 2008, Windows Server 2008 R2, or Windows Server 2012 KDCs.");
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Will exit the case immediately.");
                return;
            }

            //Create kerberos test client and connect
            client = new KerberosTestClient(this.testConfig.LocalRealm.RealmName,
                this.testConfig.LocalRealm.User[15].Username,
                this.testConfig.LocalRealm.User[15].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;
            }

            //Send AS request
            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);

            KerberosKrbError krbError;

            //Recieve preauthentication required error
            METHOD_DATA methodData;
             krbError = client.ExpectPreauthRequiredError(out methodData);

            //Create sequence of PA data
            string timeStamp = KerberosUtility.CurrentKerberosTime.Value;

               //pre-authentication use DES
            PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp,
                0,
                EncryptionType.DES_CBC_MD5,
                this.client.Context.CName.Password,
                this.client.Context.CName.Salt);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data });

            //Create and send AS request with DES as pre-authentication
            client.SendAsRequest(options, seqOfPaData);

            //PROTECTED_USERS is not supported in Windows 2000, Windows Server 2003, Windows Server 2008, Windows Server 2008 R2, or Windows Server 2012 KDCs.

            //Receive KDC_ERR_ETYPE_NOTSUPP error from KDC
            krbError = client.ExpectKrbError();
            BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KDC_ERR_ETYPE_NOTSUPP, krbError.ErrorCode, "Section 3.3.5.6 AS Exchange:" +
                "If domainControllerFunctionality returns a value >= 6 ([MS-ADTS] section 3.1.1.3.2.25), the KDC MUST check whether the account is a member of PROTECTED_USERS ([MS-DTYP] section 2.4.2.4). " +
                "If it is a member of PROTECTED_USERS, then:<50>" +
                "If pre-authentication used DES or RC4, the KDC MUST return KDC_ERR_ETYPE_NOTSUPP.");
        }
        public void Protected_Users_Network_Logon_Computer_A2A2_Succeed()
        {
            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);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequest(options, seqOfPaData);
            KerberosAsResponse asResponse = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");
            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[16].Username,
                this.testConfig.LocalRealm.User[16].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[] { paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequestWithFast(options, seqOfPaData2, null, subkey, fastOptions, apOptions);
            KerberosKrbError krbError2 = client.ExpectKrbError();
            BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED, krbError2.ErrorCode, "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, paPacRequest.Data, paPacOptions.Data});
            client.SendAsRequestWithFast(options, seqOfPaData3, null, subkey, fastOptions, apOptions);
            KerberosAsResponse userKrbAsRep = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(userKrbAsRep.Response.ticket, "AS response should contain a TGT.");
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                string.Format("The type of AS-REP encrypted part is {0}.", userKrbAsRep.EncPart.GetType().Name));

            // verify the PA-DATA of AS_REP: asResponse.EncPart.pa_datas as PA_SUPPORTED_ENCTYPES
            bool isExistPaSupportedEncTypes = false;
            bool isExistPadataValue = false;

            var padataCount = userKrbAsRep.EncPart.pa_datas.Elements.Length;
            for (int i = 0; i < padataCount; i++)
            {
                var padata = PaDataParser.ParseRepPaData(userKrbAsRep.EncPart.pa_datas.Elements[i]);
                if ((PaDataType)padata.Data.padata_type.Value == PaDataType.PA_SUPPORTED_ENCTYPES)
                {
                    isExistPaSupportedEncTypes = true;
                    for (int j = 0; j < padata.Data.padata_value.Value.Length; j++)
                    {
                        if (padata.Data.padata_value.Value[j] == 0x1F)
                        {
                            isExistPadataValue = true;
                        }
                    }
                }
            }
            BaseTestSite.Assert.IsTrue(isExistPaSupportedEncTypes, "If domainControllerFunctionality returns a value >= 3:" +
                "the KDC SHOULD, in the encrypted pre-auth data part ([Referrals-11], Appendix A) of the AS-REP message, " +
                "include PA-DATA with the padata-type set to PA-SUPPORTED-ENCTYPES (165).");

            BaseTestSite.Assert.IsTrue(isExistPadataValue, "If domainControllerFunctionality returns a value >= 3: " +
                "the KDC SHOULD, in the encrypted pre-auth data part ([Referrals-11], Appendix A) of the AS-REP message, " +
                "include PA-DATA with the padata-type set to PA-SUPPORTED-ENCTYPES (165), and the padata-value set to 0x1F (section 2.2.6).");

            if (testConfig.IsClaimSupported)
            {
                PaSupportedEncTypes paSupportedEncTypes = null;
                // userKrbAsRep.EncPart.pa_datas.GetType

                foreach (var padata in userKrbAsRep.EncPart.pa_datas.Elements)
                {
                    var parsedPadata = PaDataParser.ParseRepPaData(padata);
                    if (parsedPadata is PaSupportedEncTypes)
                        paSupportedEncTypes = parsedPadata as PaSupportedEncTypes;
                }

                BaseTestSite.Assert.IsNotNull(paSupportedEncTypes, "The encrypted padata of AS-REP contains PA_SUPPORTED_ENCTYPES.");
                BaseTestSite.Assert.IsTrue(
                    paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.Claims_Supported),
                    "Claims is supported.");
                BaseTestSite.Assert.IsTrue(
                    paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.FAST_Supported),
                    "FAST is supported.");
            }

            // FAST armored TGS_REQ and TGS_REP using user principal
            subkey = KerberosUtility.MakeKey(client.Context.SelectedEType, "Password03!", "this is a salt");
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send FAST armored TGS request.");
            client.SendTgsRequestWithFast(testConfig.LocalRealm.FileServer[0].Smb2ServiceName, options, null, null, subkey, fastOptions, apOptions);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve TGS response.");
            KerberosTgsResponse userKrbTgsRep = client.ExpectTgsResponse(KeyUsageNumber.TGS_REP_encrypted_part_subkey);

            BaseTestSite.Assert.IsNotNull(userKrbTgsRep.Response, "The Response pare of TGS-REP is not null.");
            BaseTestSite.Assert.IsNotNull(userKrbTgsRep.Response.padata, "The Padata of TGS-REP is not null.");

            EncryptionKey strengthenKey = null;
            foreach (PA_DATA paData in userKrbTgsRep.Response.padata.Elements)
            {
                var parsedPaData = PaDataParser.ParseRepPaData(paData);
                if (parsedPaData is PaFxFastRep)
                {
                    var armoredRep = ((PaFxFastRep)parsedPaData).GetArmoredRep();
                    var kerbRep = ((PaFxFastRep)parsedPaData).GetKerberosFastRep(client.Context.FastArmorkey);
                    strengthenKey = kerbRep.FastResponse.strengthen_key;
                }
            }
            BaseTestSite.Assert.IsNotNull(strengthenKey, "Strengthen key field must be set in TGS-REP.");
            BaseTestSite.Assert.IsNotNull(userKrbTgsRep.EncPart, "The encrypted part of TGS-REP is decrypted.");
        }
        public void DomainLocalGroupMembershipWithDisableResourceSIDCompressionUnset()
        {
            base.Logging();

            //Create kerberos test client and connect
            client = new KerberosTestClient(
                this.testConfig.LocalRealm.RealmName,
                this.testConfig.LocalRealm.User[13].Username,
                this.testConfig.LocalRealm.User[13].Password,
                KerberosAccountType.User,
                testConfig.LocalRealm.KDC[0].IPAddress,
                testConfig.LocalRealm.KDC[0].Port,
                testConfig.TransportType,
                testConfig.SupportedOid);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Construct Kerberos client for testing."); //Create and send AS request

            // 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;
            }

            Adapter.PacHelper.commonUserFields commonUserFields = new Adapter.PacHelper.commonUserFields();
            if (this.testConfig.LocalRealm.KDC[0].IsWindows)
            {
                //Don't use the same user account for ldap querys, it will change the current user account attributes
                NetworkCredential cred = new NetworkCredential(this.testConfig.LocalRealm.Admin.Username, this.testConfig.LocalRealm.Admin.Password, this.testConfig.LocalRealm.RealmName);
                commonUserFields = Adapter.PacHelper.GetCommonUserFields(this.testConfig.LocalRealm.RealmName, this.testConfig.LocalRealm.User[13].Username, cred);
            }

            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with no PA data.");
            //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, this.client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.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.LocalResources[0].DefaultServiceName, options, seqOfPaData);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
                tgsResponse.Response.ticket.realm.Value.ToLower(),
                "The realm in ticket should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.LocalResources[0].DefaultServiceName,
               KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname),
               "The Service principal name in ticket should match expected.");

            //EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.LocalResources[0].DefaultServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType);
            //tgsResponse.DecryptTicket(key);

            tgsResponse.DecryptTicket(this.testConfig.LocalRealm.LocalResources[0].Password, this.testConfig.LocalRealm.LocalResources[0].ServiceSalt);
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
               tgsResponse.TicketEncPart.crealm.Value.ToLower(),
               "The realm in ticket encrypted part should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[13].Username,
                KerberosUtility.PrincipalName2String(tgsResponse.TicketEncPart.cname),
                "The client principal name in ticket encrypted part should match expected.");
            //Verify PAC
            if (this.testConfig.IsKileImplemented && this.testConfig.LocalRealm.KDC[0].IsWindows)
            {
                BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data.");
                AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements);
                BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac.");
                KerbValidationInfo kerbValidationInfo = null;
                foreach (var buf in adWin2kPac.Pac.PacInfoBuffers)
                {
                    if (buf is KerbValidationInfo)
                    {
                        kerbValidationInfo = buf as KerbValidationInfo;
                        break;
                    }
                }
                BaseTestSite.Assert.IsNotNull(kerbValidationInfo, "KerbValidationInfo is generated.");

                BaseTestSite.Assert.AreEqual(1, kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupDomainSid.Length, "The number of ResourceGroupDomainSid should be 1 as is configured.");
                foreach (_RPC_SID element in kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupDomainSid)
                {
                    byte[] expectedIdentifierAuthority = new byte[6] { 0, 0, 0, 0, 0, 5 };
                    BaseTestSite.Assert.AreEqual(expectedIdentifierAuthority.Length, element.IdentifierAuthority.Value.Length, "IdentifierAuthority 000005 stands for S-1-5");

                    BaseTestSite.Assert.IsTrue(element.IdentifierAuthority.Value.SequenceEqual(expectedIdentifierAuthority), "IdentifierAuthority elements should match expected.");
                    uint[] expectedSubAuthority = commonUserFields.domainSid;
                    BaseTestSite.Assert.AreEqual(expectedSubAuthority.Length, element.SubAuthorityCount, "SubAuthorityCount should match expected.");
                    BaseTestSite.Assert.IsTrue(element.SubAuthority.SequenceEqual(expectedSubAuthority), "SubAuthorityCount elements should match expected.");
                }

                uint resourceGroupCount = this.testConfig.LocalRealm.ResourceGroups.GroupCount;
                BaseTestSite.Assert.AreEqual((uint)resourceGroupCount, kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupCount, "The ResourceGroupCount field contains the number of groups in the ResourceGroupIds field.");

                Adapter.Group[] resourceGroups = this.testConfig.LocalRealm.ResourceGroups.Groups;
                NetworkCredential cred = new NetworkCredential(this.testConfig.LocalRealm.Admin.Username, this.testConfig.LocalRealm.Admin.Password, this.testConfig.LocalRealm.RealmName);
                uint[] expectedResourceGroupIds = Adapter.PacHelper.GetResourceGroupIds(this.testConfig.LocalRealm.RealmName, cred, resourceGroupCount, resourceGroups);
                for (int i = 0; i < resourceGroupCount; i++)
                {
                    BaseTestSite.Assert.AreEqual(Attributes_Values.Mandatory | Attributes_Values.EnabledByDefault
                        | Attributes_Values.Enabled | Attributes_Values.Resource,
                        kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupIds[i].Attributes,
                        "The Attributes have the A, B, C and E bits set to 1, and all other bits set to zero.");

                }
                BaseTestSite.Assert.IsTrue(kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupIds.Select(id => id.RelativeId).OrderBy(id => id).SequenceEqual(expectedResourceGroupIds.OrderBy(id => id)), "RelativeId contains the RID of the value pmsgOut.ppDsNames.Sid.");
            }
        }
        public void RC4_UsingFAST_Smb2()
        {
            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);

            EncryptionType[] rc4HmacType = new EncryptionType[]
            {
                EncryptionType.RC4_HMAC
            };

            // Define device principal client supported encryption type
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Set device principal client supported encryption type as RC4_HMAC.");
            client.SetSupportedEType(rc4HmacType);

            // 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);
            BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

            // 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.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

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

            // Define user principal client supported encryption type
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Set user principal client supported encryption type as RC4_HMAC.");
            client.SetSupportedEType(rc4HmacType);

            // 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;
            string timeStamp2 = KerberosUtility.CurrentKerberosTime.Value;
            PaFxFastReq paFxReq = new PaFxFastReq(null);
            Asn1SequenceOf<PA_DATA> seqOfPaData2 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { (paFxReq.Data) });

            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);

            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData3 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp3.Data, paPacRequest.Data, paPacOptions.Data });

            client.SendAsRequestWithFast(options, seqOfPaData3, null, subkey, fastOptions, apOptions);
            KerberosAsResponse userKrbAsRep = client.ExpectAsResponse();
            BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

            // 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.FileServer[0].Smb2ServiceName, options, null, null, subkey, fastOptions, apOptions);
            KerberosTgsResponse userKrbTgsRep = client.ExpectTgsResponse(KeyUsageNumber.TGS_REP_encrypted_part_subkey);
            BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

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

            KerberosApResponse apRep = client.GetApResponseFromToken(SendAndRecieveSmb2Ap(this.testConfig.LocalRealm.FileServer[0], token));
        }
        public void KdcSignature()
        {
            base.Logging();

            //Create kerberos test client and connect
            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;
            }

            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with no PA data.");
            //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, this.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.ClientComputer.DefaultServiceName, options);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
                tgsResponse.Response.ticket.realm.Value.ToLower(),
                "The realm in ticket should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName,
               KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname),
               "The Service principal name in ticket should match expected.");

            EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType);
            tgsResponse.DecryptTicket(key);

            //tgsResponse.DecryptTicket(this.testConfig.LocalRealm.ClientComputer.Password, this.testConfig.LocalRealm.ClientComputer.ServiceSalt);
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
               tgsResponse.TicketEncPart.crealm.Value.ToLower(),
               "The realm in ticket encrypted part should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].Username.ToLower(),
                KerberosUtility.PrincipalName2String(tgsResponse.TicketEncPart.cname).ToLower(),
                "The client principal name in ticket encrypted part should match expected.");
            //Verify PAC

            if (this.testConfig.IsKileImplemented)
            {
                BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data.");
                AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements);
                BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac.");
                PacKdcSignature kdcSignature = null;
                foreach (var buf in adWin2kPac.Pac.PacInfoBuffers)
                {
                    if (buf is PacKdcSignature)
                    {
                        kdcSignature = buf as PacKdcSignature;
                        break;
                    }
                }
                BaseTestSite.Assert.IsNotNull(kdcSignature, "KDC Signature is generated.");

                //cannot make a kdc key
                //kdcSignature untestable
            }
        }
        public void RC4_InteractiveLogonUseExplicitFast()
        {
            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);

            EncryptionType[] rc4HmacType = new EncryptionType[]
            {
                EncryptionType.RC4_HMAC
            };

            // Define device principal client supported encryption type
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Set device principal client supported encryption type as RC4_HMAC.");
            client.SetSupportedEType(rc4HmacType);

            // 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
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with no PA data.");
            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve preauthentication required error.");
            METHOD_DATA methodData;
            KerberosKrbError krbError1 = client.ExpectPreauthRequiredError(out methodData);
            BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");

            // AS_REQ and AS_REP using device principal
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with PaEncTimeStamp.");
            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);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve AS response.");
            KerberosAsResponse asResponse = client.ExpectAsResponse();
            BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");
            BaseTestSite.Assert.IsNotNull(asResponse.EncPart, "The encrypted part of AS response is decrypted.");
            BaseTestSite.Assert.IsNotNull(asResponse.EncPart.key, "AS response should contain a session key.");
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                string.Format("The type of AS-REP encrypted part is {0}.", asResponse.EncPart.GetType().Name));

            // Switch to user principal
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Switch to user principal.");
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                string.Format("Construct kerberos client using user account: {0}.",
                this.testConfig.LocalRealm.User[1].Username));
            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);

            // Define user principal client supported encryption type
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Set user principal client supported encryption type as RC4_HMAC.");
            client.SetSupportedEType(rc4HmacType);

            // 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.
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send FAST armored AS request with no pre-authentication padata.");
            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(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");
            BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED, krbError2.ErrorCode, "Pre-authentication required.");

            // FAST armored AS_REQ and AS_REP using user principal
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with PaEncryptedChallenge.");
            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);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve AS response.");
            KerberosAsResponse userKrbAsRep = client.ExpectAsResponse();
            BaseTestSite.Assert.AreEqual(EncryptionType.RC4_HMAC, client.Context.SelectedEType, "Client selected encryption type should be RC4_HMAC.");
            BaseTestSite.Assert.IsNotNull(userKrbAsRep.Response.ticket, "AS response should contain a TGT.");
            BaseTestSite.Assert.IsNotNull(userKrbAsRep.EncPart, "The encrypted part of AS response is decrypted.");
            BaseTestSite.Assert.IsNotNull(userKrbAsRep.EncPart.key, "AS response should contain a session key.");
            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");
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send explicit FAST armored TGS request.");
            client.SendTgsRequestWithExplicitFast(testConfig.LocalRealm.ClientComputer.DefaultServiceName, options, null, null, subkey, fastOptions, apOptions);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve TGS response.");
            KerberosTgsResponse userKrbTgsRep = client.ExpectTgsResponse(KeyUsageNumber.TGS_REP_encrypted_part_subkey);
            BaseTestSite.Assert.IsNotNull(userKrbTgsRep.EncPart, "The encrypted part of TGS-REP is decrypted.");

            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
                userKrbTgsRep.Response.ticket.realm.Value.ToLower(),
                "The realm in ticket should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName,
               KerberosUtility.PrincipalName2String(userKrbTgsRep.Response.ticket.sname),
               "The Service principal name in ticket should match expected.");

            EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType);
            userKrbTgsRep.DecryptTicket(key);

            //userKrbTgsRep.DecryptTicket(this.testConfig.LocalRealm.ClientComputer.Password, this.testConfig.LocalRealm.ClientComputer.ServiceSalt);
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
               userKrbTgsRep.TicketEncPart.crealm.Value.ToLower(),
               "The realm in ticket encrypted part should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].Username.ToLower(),
                KerberosUtility.PrincipalName2String(userKrbTgsRep.TicketEncPart.cname).ToLower(),
                "The client principal name in ticket encrypted part should match expected.");
        }
        public void KERB_VALIDATION_INFO()
        {
            base.Logging();

            //Create kerberos test client and connect
            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);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Construct Kerberos client for testing."); //Create and send AS request

            // 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;
            }

            Adapter.PacHelper.commonUserFields commonUserFields = new Adapter.PacHelper.commonUserFields();
            if (this.testConfig.LocalRealm.KDC[0].IsWindows)
            {
                //Don't use the same user account for ldap querys, it will change the current user account attributes
                NetworkCredential cred = new NetworkCredential(this.testConfig.LocalRealm.User[2].Username, this.testConfig.LocalRealm.User[2].Password, this.testConfig.LocalRealm.RealmName);
                commonUserFields = Adapter.PacHelper.GetCommonUserFields(this.testConfig.LocalRealm.RealmName, this.testConfig.LocalRealm.User[1].Username, cred);
            }

            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with no PA data.");
            //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, this.client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.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.ClientComputer.DefaultServiceName, options);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
                tgsResponse.Response.ticket.realm.Value.ToLower(),
                "The realm in ticket should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName,
               KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname),
               "The Service principal name in ticket should match expected.");

            EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType);
            tgsResponse.DecryptTicket(key);

            //tgsResponse.DecryptTicket(this.testConfig.LocalRealm.ClientComputer.Password, this.testConfig.LocalRealm.ClientComputer.ServiceSalt);

            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
               tgsResponse.TicketEncPart.crealm.Value.ToLower(),
               "The realm in ticket encrypted part should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].Username.ToLower(),
                KerberosUtility.PrincipalName2String(tgsResponse.TicketEncPart.cname).ToLower(),
                "The client principal name in ticket encrypted part should match expected.");
            //Verify PAC
            if (this.testConfig.IsKileImplemented)
            {
                BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data.");
                AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements);
                BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac.");
                KerbValidationInfo kerbValidationInfo = null;
                foreach (var buf in adWin2kPac.Pac.PacInfoBuffers)
                {
                    if (buf is KerbValidationInfo)
                    {
                        kerbValidationInfo = buf as KerbValidationInfo;
                        break;
                    }
                }
                BaseTestSite.Assert.IsNotNull(kerbValidationInfo, "KerbValidationInfo is generated.");

                if (this.testConfig.LocalRealm.KDC[0].IsWindows)
                {
                    var flogonTime = (long)kerbValidationInfo.NativeKerbValidationInfo.LogonTime.dwHighDateTime << 32 | (long)kerbValidationInfo.NativeKerbValidationInfo.LogonTime.dwLowDateTime;
                    if (flogonTime != 0x7FFFFFFFFFFFFFFF)
                    {
                        System.DateTime logonTime = System.DateTime.FromFileTime(flogonTime);
                    }
                    BaseTestSite.Assert.AreEqual(commonUserFields.LogonTime, flogonTime, "LogonTime in KERB_VALIDATION_INFO structure should be equal to that in AD.");

                    long fPasswordLastSet = (long)kerbValidationInfo.NativeKerbValidationInfo.PasswordLastSet.dwHighDateTime << 32 | (long)kerbValidationInfo.NativeKerbValidationInfo.PasswordLastSet.dwLowDateTime;
                    if (fPasswordLastSet != 0x7FFFFFFFFFFFFFFF)
                    {
                        System.DateTime passwordLastSet = System.DateTime.FromFileTime(fPasswordLastSet);
                    }
                    BaseTestSite.Assert.AreEqual(commonUserFields.PasswordLastSet,
                        fPasswordLastSet,
                        "PasswordLastSet in KERB_VALIDATION_INFO structure should be equal to that in AD.");

                    var effectiveName = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.EffectiveName.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].Username.ToLower(), effectiveName.ToLower(), "The EffectiveName field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.UserName field of the SamrQueryInformationUser2 response message.");

                    string fullName = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.FullName.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].Username.ToLower(), fullName.ToLower(), "The FullName field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.FullName field of the SamrQueryInformationUser2 response message.");

                    string logonScript = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.LogonScript.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.ScriptPath, logonScript, "The LogonScript field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.ScriptPath field of the SamrQueryInformationUser2 response message.");

                    string profilePath = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.ProfilePath.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.ProfilePath, profilePath, "The ProfilePath field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.ProfilePath field of the SamrQueryInformationUser2 response message.");

                    string homeDirectory = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.HomeDirectory.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.HomeDirectory, homeDirectory, "The HomeDirectory field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.HomeDirectory field of the SamrQueryInformationUser2 response message.");

                    string homeDirectoryDrive = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.HomeDirectoryDrive.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.HomeDrive, homeDirectoryDrive, "The HomeDirectoryDrive field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.HomeDirectoryDrive field of the SamrQueryInformationUser2 response message.");

                    ushort logonCount = kerbValidationInfo.NativeKerbValidationInfo.LogonCount;
                    BaseTestSite.Assert.AreEqual(commonUserFields.LogonCount, logonCount, "The LogonCount field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.LogonCount field of the SamrQueryInformationUser2 response message.");

                    ushort badPasswordCount = kerbValidationInfo.NativeKerbValidationInfo.BadPasswordCount;
                    BaseTestSite.Assert.AreEqual(commonUserFields.BadPwdCount, badPasswordCount, "The BadPasswordCount field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.BadPasswordCount field of the SamrQueryInformationUser2 response message.");

                    uint userId = kerbValidationInfo.NativeKerbValidationInfo.UserId;
                    BaseTestSite.Assert.AreEqual(commonUserFields.userId, userId, "The UserID field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.UserId field of the SamrQueryInformationUser2 response message.");

                    uint primaryGroupId = kerbValidationInfo.NativeKerbValidationInfo.PrimaryGroupId;
                    BaseTestSite.Assert.AreEqual(commonUserFields.primaryGroupId, primaryGroupId, "The PrimaryGroupId field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.PrimaryGroupId field of the SamrQueryInformationUser2 response message.");

                    var userAccountControl = kerbValidationInfo.NativeKerbValidationInfo.UserAccountControl;
                    //not the same with what is in the Active Directory
                    //BaseTestSite.Assert.AreEqual(commonUserFields.userAccountControl, userAccountControl, "The BadPasswordCount field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.BadPasswordCount field of the SamrQueryInformationUser2 response message.");

                    //read only, need SUT adapter
                    uint groupCount = kerbValidationInfo.NativeKerbValidationInfo.GroupCount;
                    BaseTestSite.Assert.AreEqual(commonUserFields.groupCount, groupCount, "The GroupCount field SHOULD be set to the Groups.MembershipCount field of the SamrGetGroupsForUser response message.");

                    //read only, need SUT adapter
                    Microsoft.Protocols.TestTools.StackSdk.Security.Pac._GROUP_MEMBERSHIP[] groupIds = kerbValidationInfo.NativeKerbValidationInfo.GroupIds;
                    BaseTestSite.Assert.AreEqual(commonUserFields.groupIds.Length, groupIds.Length, "The GroupIds field SHOULD be set to the Groups.Group field of the SamrGetGroupsForUser response message.");
                    BaseTestSite.Assert.IsTrue(groupIds.Select(id => id.RelativeId).OrderBy(id => id).SequenceEqual(commonUserFields.groupIds.OrderBy(id => id)), "The GroupIds field SHOULD be set to the Groups.Group field of the SamrGetGroupsForUser response message.");

                    UserFlags_Values userFlags = kerbValidationInfo.NativeKerbValidationInfo.UserFlags;
                    BaseTestSite.Assert.AreEqual(UserFlags_Values.ExtraSids, UserFlags_Values.ExtraSids & userFlags, "The D bit SHOULD be set in the UserFlags field if the ExtraSids field is populated and contains additional SIDs and all other bits MUST be set to zero.");

                    byte[] userSessionKey = kerbValidationInfo.NativeKerbValidationInfo.UserSessionKey;
                    byte[] allZero = userSessionKey;
                    Array.Clear(allZero, 0, allZero.Length);
                    BaseTestSite.Assert.AreEqual(allZero, userSessionKey, "The UserSessionKey field MUST be set to zero.");

                    string logonServer = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.LogonServer.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.KDC[0].NetBiosName.Remove(this.testConfig.LocalRealm.KDC[0].NetBiosName.IndexOf("$")), logonServer, "The LogonServer SHOULD be set to NetbiosServerName.");

                    string logonDomainName = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.LogonDomainName.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.Remove(this.testConfig.LocalRealm.RealmName.IndexOf(".")).ToLower(), logonDomainName.ToLower(), "The LogonDomainName SHOULD be set to NetbiosDomainName.");

                    BaseTestSite.Assert.AreEqual(1, kerbValidationInfo.NativeKerbValidationInfo.LogonDomainId.Length, "The number of LogonDomainId should always be 1.");
                    foreach (_RPC_SID element in kerbValidationInfo.NativeKerbValidationInfo.LogonDomainId)
                    {
                        byte[] expectedIdentifierAuthority = new byte[6] { 0, 0, 0, 0, 0, 5 };
                        BaseTestSite.Assert.AreEqual(expectedIdentifierAuthority.Length, element.IdentifierAuthority.Value.Length, "IdentifierAuthority 000005 stands for S-1-5");
                        for (int i = 0; i < expectedIdentifierAuthority.Length; i++)
                        {
                            BaseTestSite.Assert.AreEqual(expectedIdentifierAuthority[i], element.IdentifierAuthority.Value[i], "IdentifierAuthority element {0} should match expected.", i);
                        }
                        uint[] expectedSubAuthority = commonUserFields.domainSid;
                        BaseTestSite.Assert.AreEqual(expectedSubAuthority.Length, element.SubAuthorityCount, "SubAuthorityCount should match expected.");
                        for (int i = 0; i < expectedSubAuthority.Length; i++)
                        {
                            BaseTestSite.Assert.AreEqual(commonUserFields.domainSid[i], element.SubAuthority[i], "SubAuthorityCount element {0} should match expected.");
                        }
                    }

                    KERB_VALIDATION_INFO_Reserved1_Values[] reserved1 = kerbValidationInfo.NativeKerbValidationInfo.Reserved1;
                    BaseTestSite.Assert.AreEqual(2, reserved1.Length, "The Reserved1 field MUST be set to a two-element array of unsigned 32-bit integers.");
                    foreach (KERB_VALIDATION_INFO_Reserved1_Values element in reserved1)
                    {
                        BaseTestSite.Assert.AreEqual(KERB_VALIDATION_INFO_Reserved1_Values.V1, element, "Each element of the array MUST be zero.");
                    }

                    KERB_VALIDATION_INFO_Reserved3_Values[] reserved3 = kerbValidationInfo.NativeKerbValidationInfo.Reserved3;
                    BaseTestSite.Assert.AreEqual(7, reserved3.Length, "The Reserved1 field MUST be set to a seven-element array of unsigned 32-bit integers.");
                    foreach (KERB_VALIDATION_INFO_Reserved3_Values element in reserved3)
                    {
                        BaseTestSite.Assert.AreEqual(KERB_VALIDATION_INFO_Reserved3_Values.V1, element, "Each element of the array MUST be zero.");
                    }

                    //sidcount =2 because, one for AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY SID and one for CLAIMS_VALID SID
                    uint expectedSidCount = 2;
                    BaseTestSite.Assert.AreEqual(expectedSidCount, kerbValidationInfo.NativeKerbValidationInfo.SidCount, "The SidCount includes the number of one AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY, one CLAIMS_VALID.");

                    KERB_SID_AND_ATTRIBUTES[] expectedDefaultExtraSids = new KERB_SID_AND_ATTRIBUTES[expectedSidCount];
                    //The CLAIMS_VALID SID is "S-1-5-21-0-0-0-497"
                    _RPC_SID CLAIMS_VALID = new _RPC_SID();
                    CLAIMS_VALID.Revision = 0x01;
                    CLAIMS_VALID.IdentifierAuthority = new _RPC_SID_IDENTIFIER_AUTHORITY();
                    CLAIMS_VALID.IdentifierAuthority.Value = new byte[] { 0, 0, 0, 0, 0, 5 };
                    CLAIMS_VALID.SubAuthorityCount = 5;
                    CLAIMS_VALID.SubAuthority = new uint[] { 21, 0, 0, 0, 497 };
                    expectedDefaultExtraSids[0] = new KERB_SID_AND_ATTRIBUTES();
                    expectedDefaultExtraSids[0].Attributes = Attributes_Values.Mandatory | Attributes_Values.EnabledByDefault | Attributes_Values.Enabled;
                    expectedDefaultExtraSids[0].SID = new _RPC_SID[1];
                    expectedDefaultExtraSids[0].SID[0] = CLAIMS_VALID;

                    //The AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY SID is "S-1-18-1"
                    _RPC_SID AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY = new _RPC_SID();
                    AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.Revision = 0x01;
                    AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.IdentifierAuthority = new _RPC_SID_IDENTIFIER_AUTHORITY();
                    AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.IdentifierAuthority.Value = new byte[] { 0, 0, 0, 0, 0, 18 };
                    AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.SubAuthorityCount = 1;
                    AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.SubAuthority = new uint[] { 1 };
                    expectedDefaultExtraSids[1] = new KERB_SID_AND_ATTRIBUTES();
                    expectedDefaultExtraSids[1].Attributes = Attributes_Values.Mandatory | Attributes_Values.EnabledByDefault | Attributes_Values.Enabled;
                    expectedDefaultExtraSids[1].SID = new _RPC_SID[1];
                    expectedDefaultExtraSids[1].SID[0] = AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY;

                    var expectedExtraSids = expectedDefaultExtraSids;

                    uint res = expectedSidCount;
                    for (int i = 0; i < expectedSidCount; i++)
                    {
                        for (int j = 0; j < expectedSidCount; j++)
                        {
                            if (Adapter.PacHelper.ExtraSidsAreEqual(expectedExtraSids[i], kerbValidationInfo.NativeKerbValidationInfo.ExtraSids[j]))
                            {
                                res--;
                            }
                        }
                    }
                    BaseTestSite.Assert.AreEqual((uint)0, res, "The ExtraSids field contains the pointer to a list which is the list copied from the PAC in the TGT plus a list constructed from the domain local groups, notice domain local groups is equal to 0 in this test case.");

                    BaseTestSite.Assert.IsNull(kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupDomainSid, "The ResourceGroupDomainSid field MUST be set to zero.");

                    BaseTestSite.Assert.AreEqual((uint)0, kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupCount, "The ResourceGroupCount field MUST be set to zero.");

                    BaseTestSite.Assert.IsNull(kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupIds, "The ResourceGroupIds field MUST be set to zero.");
                }
                else
                {
                    string effectiveName = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.EffectiveName.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].Username.ToLower(), effectiveName.ToLower(), "The EffectiveName field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.UserName field of the SamrQueryInformationUser2 response message.");

                    string fullName = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.FullName.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].Username.ToLower(), fullName.ToLower(), "The FullName field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.FullName field of the SamrQueryInformationUser2 response message.");

                    string logonScript = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.LogonScript.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.ScriptPath, logonScript, "The LogonScript field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.ScriptPath field of the SamrQueryInformationUser2 response message.");

                    string profilePath = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.ProfilePath.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.ProfilePath, profilePath, "The ProfilePath field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.ProfilePath field of the SamrQueryInformationUser2 response message.");

                    string homeDirectory = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.HomeDirectory.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.HomeDirectory, homeDirectory, "The HomeDirectory field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.HomeDirectory field of the SamrQueryInformationUser2 response message.");

                    string homeDirectoryDrive = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.HomeDirectoryDrive.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.HomeDrive, homeDirectoryDrive, "The HomeDirectoryDrive field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.HomeDirectoryDrive field of the SamrQueryInformationUser2 response message.");

                    uint userId = kerbValidationInfo.NativeKerbValidationInfo.UserId;
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.UserID, userId, "The UserID field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.UserId field of the SamrQueryInformationUser2 response message.");

                    uint primaryGroupId = kerbValidationInfo.NativeKerbValidationInfo.PrimaryGroupId;
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.PrimaryGroupId, primaryGroupId, "The PrimaryGroupId field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.PrimaryGroupId field of the SamrQueryInformationUser2 response message.");

                    uint userAccountControl = kerbValidationInfo.NativeKerbValidationInfo.UserAccountControl;
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.UserAccountControl, userAccountControl, "The BadPasswordCount field SHOULD be set to the Buffer.SAMPR_USER_ALL_INFORMATION.BadPasswordCount field of the SamrQueryInformationUser2 response message.");

                    uint groupCount = kerbValidationInfo.NativeKerbValidationInfo.GroupCount;
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].DomainAccountInfo.GroupCount, groupCount, "The GroupCount field SHOULD be set to the Groups.MembershipCount field of the SamrGetGroupsForUser response message.");

                    UserFlags_Values userFlags = kerbValidationInfo.NativeKerbValidationInfo.UserFlags;
                    BaseTestSite.Assert.AreEqual(UserFlags_Values.ExtraSids, UserFlags_Values.ExtraSids & userFlags, "The D bit SHOULD be set in the UserFlags field if the ExtraSids field is populated and contains additional SIDs and all other bits MUST be set to zero.");

                    byte[] userSessionKey = kerbValidationInfo.NativeKerbValidationInfo.UserSessionKey;
                    byte[] allZero = userSessionKey;
                    Array.Clear(allZero, 0, allZero.Length);
                    BaseTestSite.Assert.AreEqual(allZero, userSessionKey, "The UserSessionKey field MUST be set to zero.");

                    string logonServer = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.LogonServer.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.KDC[0].NetBiosName.Remove(this.testConfig.LocalRealm.KDC[0].NetBiosName.IndexOf("$")), logonServer, "The LogonServer SHOULD be set to NetbiosServerName.");

                    string logonDomainName = Adapter.PacHelper.ConvertUnicode2String(kerbValidationInfo.NativeKerbValidationInfo.LogonDomainName.Buffer);
                    BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.Remove(this.testConfig.LocalRealm.RealmName.IndexOf(".")).ToLower(), logonDomainName.ToLower(), "The LogonDomainName SHOULD be set to NetbiosDomainName.");

                    KERB_VALIDATION_INFO_Reserved1_Values[] reserved1 = kerbValidationInfo.NativeKerbValidationInfo.Reserved1;
                    BaseTestSite.Assert.AreEqual(2, reserved1.Length, "The Reserved1 field MUST be set to a two-element array of unsigned 32-bit integers.");
                    foreach (KERB_VALIDATION_INFO_Reserved1_Values element in reserved1)
                    {
                        BaseTestSite.Assert.AreEqual(KERB_VALIDATION_INFO_Reserved1_Values.V1, element, "Each element of the array MUST be zero.");
                    }

                    KERB_VALIDATION_INFO_Reserved3_Values[] reserved3 = kerbValidationInfo.NativeKerbValidationInfo.Reserved3;
                    BaseTestSite.Assert.AreEqual(7, reserved3.Length, "The Reserved1 field MUST be set to a seven-element array of unsigned 32-bit integers.");
                    foreach (KERB_VALIDATION_INFO_Reserved3_Values element in reserved3)
                    {
                        BaseTestSite.Assert.AreEqual(KERB_VALIDATION_INFO_Reserved3_Values.V1, element, "Each element of the array MUST be zero.");
                    }

                    //sidcount =2 because, one for AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY SID and one for CLAIMS_VALID SID
                    uint expectedSidCount = 2;
                    BaseTestSite.Assert.AreEqual(expectedSidCount, kerbValidationInfo.NativeKerbValidationInfo.SidCount, "The SidCount includes the number of one AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY, one CLAIMS_VALID.");

                    KERB_SID_AND_ATTRIBUTES[] expectedDefaultExtraSids = new KERB_SID_AND_ATTRIBUTES[expectedSidCount];
                    //The CLAIMS_VALID SID is "S-1-5-21-0-0-0-497"
                    _RPC_SID CLAIMS_VALID = new _RPC_SID();
                    CLAIMS_VALID.Revision = 0x01;
                    CLAIMS_VALID.IdentifierAuthority = new _RPC_SID_IDENTIFIER_AUTHORITY();
                    CLAIMS_VALID.IdentifierAuthority.Value = new byte[] { 0, 0, 0, 0, 0, 5 };
                    CLAIMS_VALID.SubAuthorityCount = 5;
                    CLAIMS_VALID.SubAuthority = new uint[] { 21, 0, 0, 0, 497 };
                    expectedDefaultExtraSids[0] = new KERB_SID_AND_ATTRIBUTES();
                    expectedDefaultExtraSids[0].Attributes = Attributes_Values.Mandatory | Attributes_Values.EnabledByDefault | Attributes_Values.Enabled;
                    expectedDefaultExtraSids[0].SID = new _RPC_SID[1];
                    expectedDefaultExtraSids[0].SID[0] = CLAIMS_VALID;

                    //The AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY SID is "S-1-18-1"
                    _RPC_SID AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY = new _RPC_SID();
                    AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.Revision = 0x01;
                    AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.IdentifierAuthority = new _RPC_SID_IDENTIFIER_AUTHORITY();
                    AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.IdentifierAuthority.Value = new byte[] { 0, 0, 0, 0, 0, 18 };
                    AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.SubAuthorityCount = 1;
                    AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY.SubAuthority = new uint[] { 1 };
                    expectedDefaultExtraSids[1] = new KERB_SID_AND_ATTRIBUTES();
                    expectedDefaultExtraSids[1].Attributes = Attributes_Values.Mandatory | Attributes_Values.EnabledByDefault | Attributes_Values.Enabled;
                    expectedDefaultExtraSids[1].SID = new _RPC_SID[1];
                    expectedDefaultExtraSids[1].SID[0] = AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY;

                    var expectedExtraSids = expectedDefaultExtraSids;

                    uint res = expectedSidCount;
                    for (int i = 0; i < expectedSidCount; i++)
                    {
                        for (int j = 0; j < expectedSidCount; j++)
                        {
                            if (Adapter.PacHelper.ExtraSidsAreEqual(expectedExtraSids[i], kerbValidationInfo.NativeKerbValidationInfo.ExtraSids[j]))
                            {
                                res--;
                            }
                        }
                    }
                    BaseTestSite.Assert.AreEqual((uint)0, res, "The ExtraSids field contains the pointer to a list which is the list copied from the PAC in the TGT plus a list constructed from the domain local groups, notice domain local groups is equal to 0 in this test case.");

                    BaseTestSite.Assert.IsNull(kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupDomainSid, "The ResourceGroupDomainSid field MUST be set to zero.");

                    BaseTestSite.Assert.AreEqual((uint)kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupIds.Length, kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupCount, "The ResourceGroupCount field MUST be set to zero.");

                    BaseTestSite.Assert.IsNull(kerbValidationInfo.NativeKerbValidationInfo.ResourceGroupIds, "The ResourceGroupIds field MUST be set to zero.");
                }
            }
        }
        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.");
        }
        public void AdFxFastUsedInAuthenticator()
        {
            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.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");
            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.Assert.IsNotNull(userKrbAsRep.Response.ticket, "AS response should contain a TGT.");
            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");
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send unarmored TGS request with AD-fx-fast-used.");
            AdFxFastUsed adFxFastUsed = new AdFxFastUsed();
            AuthorizationData authData = new AuthorizationData(new AuthorizationDataElement[] { adFxFastUsed.AuthDataElement });
            client.SendTgsRequest(testConfig.LocalRealm.ClientComputer.DefaultServiceName, options, null, null, authData);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Receive TGS Error, KDC MUST reject the request.");
            KerberosKrbError krbError = client.ExpectKrbError();
        }
        public void UnsupportedFastArmorType()
        {
            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);

            // 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();

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

            // 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;
            string timeStamp2 = KerberosUtility.CurrentKerberosTime.Value;
            PaFxFastReq paFxReq = new PaFxFastReq(null);
            Asn1SequenceOf<PA_DATA> seqOfPaData2 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { (paFxReq.Data) });

            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 });
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> outerSeqPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paPacRequest.Data, paPacOptions.Data });
            client.SendAsRequestWithFast(options, seqOfPaData3, outerSeqPaData, subkey, fastOptions, apOptions, 0);
            KerberosKrbError krbError3 = client.ExpectKrbError();
            BaseTestSite.Assert.AreEqual(krbError3.ErrorCode,
                KRB_ERROR_CODE.KDC_ERR_PREAUTH_FAILED,
                "Pre-authentication failed.");
        }
        public void PAC_CLIENT_INFO()
        {
            base.Logging();

            //Create kerberos test client and connect
            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;
            }

            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with no PA data.");
            //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, this.client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.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.ClientComputer.DefaultServiceName, options);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
                tgsResponse.Response.ticket.realm.Value.ToLower(),
                "The realm in ticket should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName,
               KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname),
               "The Service principal name in ticket should match expected.");

            EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType);
            tgsResponse.DecryptTicket(key);

            //tgsResponse.DecryptTicket(this.testConfig.LocalRealm.ClientComputer.Password, this.testConfig.LocalRealm.ClientComputer.ServiceSalt);
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
               tgsResponse.TicketEncPart.crealm.Value.ToLower(),
               "The realm in ticket encrypted part should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].Username.ToLower(),
                KerberosUtility.PrincipalName2String(tgsResponse.TicketEncPart.cname).ToLower(),
                "The client principal name in ticket encrypted part should match expected.");
            //Verify PAC
            if (this.testConfig.IsKileImplemented)
            {
                BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data.");

                AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements);
                BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac.");
                PacClientInfo pacClientInfo = null;
                foreach (var buf in adWin2kPac.Pac.PacInfoBuffers)
                {
                    if (buf is PacClientInfo)
                    {
                        pacClientInfo = buf as PacClientInfo;
                        break;
                    }
                }
                BaseTestSite.Assert.IsNotNull(pacClientInfo, "PAC_CLIENT_INFO is generated.");
                var authTimeInPac = DtypUtility.ToDateTime(pacClientInfo.NativePacClientInfo.ClientId).ToString("yyyyMMddHHmmss") + "Z";
                var c = asResponse.EncPart.authtime;
                BaseTestSite.Assert.AreEqual(
                    asResponse.EncPart.authtime.ToString(),
                    authTimeInPac,
                    "ClientId field is a FILETIME structure in little-endian format that contains the Kerberos initial TGT auth time.");
                string clientName = new string(pacClientInfo.NativePacClientInfo.Name);
                BaseTestSite.Assert.AreEqual(
                    pacClientInfo.NativePacClientInfo.Name.Length * sizeof(char),
                    pacClientInfo.NativePacClientInfo.NameLength,
                    "The NameLength field is an unsigned 16-bit integer in little-endian format that specifies the length, in bytes, of the Name field.");
                BaseTestSite.Assert.AreEqual(
                    this.testConfig.LocalRealm.User[1].Username.ToLower(),
                    clientName.ToLower(),
                    "The Name field is an array of 16-bit Unicode characters in little-endian format that contains the client's account name.");
            }
        }
        private EncTicketPart RetrieveAndDecryptServiceTicket(KerberosFunctionalClient kerberosClient, out EncryptionKey serviceKey)
        {
            //Create and send AS request
            const KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            kerberosClient.SendAsRequest(options, null);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects Kerberos Error from KDC");
            //Receive preauthentication required error
            METHOD_DATA methodData;
            KerberosKrbError krbError = kerberosClient.ExpectPreauthRequiredError(out methodData);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client sends AS request with PA-DATA set");
            //Create sequence of PA data
            string timeStamp = KerberosUtility.CurrentKerberosTime.Value;
            PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp,
                0,
                kerberosClient.Context.SelectedEType,
                kerberosClient.Context.CName.Password,
                kerberosClient.Context.CName.Salt);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new[] { paEncTimeStamp.Data, paPacRequest.Data });
            //Create and send AS request
            kerberosClient.SendAsRequest(options, seqOfPaData);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects AS response from KDC");
            KerberosAsResponse asResponse = kerberosClient.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");

            //Create and send TGS request
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client sends TGS request to KDC");
            kerberosClient.SendTgsRequest(servicePrincipalName, options);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects TGS response from KDC");
            KerberosTgsResponse tgsResponse = kerberosClient.ExpectTgsResponse();

            BaseTestSite.Assert.AreEqual(servicePrincipalName,
                KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname),
                "Service principal name in service ticket should match expected.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Decrypt SMB2 Service Ticket");
            serviceKey = keyManager.QueryKey(servicePrincipalName, TestConfig.DomainName, kerberosClient.Context.SelectedEType);
            tgsResponse.DecryptTicket(serviceKey);

            return tgsResponse.TicketEncPart;
        }
        public void StrengthenKey()
        {
            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
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with no PA data.");
            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve preauthentication required error.");
            METHOD_DATA methodData;
            KerberosKrbError krbError1 = client.ExpectPreauthRequiredError(out methodData);

            // AS_REQ and AS_REP using device principal
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with PaEncTimeStamp.");
            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);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve AS response.");
            KerberosAsResponse asResponse = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");
            BaseTestSite.Assert.IsNotNull(asResponse.EncPart, "The encrypted part of AS response is decrypted.");
            BaseTestSite.Assert.IsNotNull(asResponse.EncPart.key, "AS response should contain a session key.");
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                string.Format("The type of AS-REP encrypted part is {0}.", asResponse.EncPart.GetType().Name));

            // Switch to user principal
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Switch to user principal.");
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                string.Format("Construct Kerberos client using user account: {0}.",
                this.testConfig.LocalRealm.User[1].Username));
            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.
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send FAST armored AS request with no pre-authentication padata.");
            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
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with PaEncryptedChallenge.");
            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);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            Asn1SequenceOf<PA_DATA> outerSeqPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paPacRequest.Data });
            Asn1SequenceOf<PA_DATA> seqOfPaData3 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp3.Data });
            client.SendAsRequestWithFast(options, seqOfPaData3, outerSeqPaData, subkey, fastOptions, apOptions);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve AS response.");
            KerberosAsResponse userKrbAsRep = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(userKrbAsRep.Response.ticket, "AS response should contain a TGT.");
            BaseTestSite.Assert.IsNotNull(userKrbAsRep.EncPart, "The encrypted part of AS response is decrypted.");
            BaseTestSite.Assert.IsNotNull(userKrbAsRep.EncPart.key, "AS response should contain a session key.");
            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");
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send FAST armored TGS request.");
            client.SendTgsRequestWithFast(testConfig.LocalRealm.ClientComputer.DefaultServiceName, options, null, null, subkey, fastOptions, apOptions);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Recieve TGS response.");
            KerberosTgsResponse userKrbTgsRep = client.ExpectTgsResponse(KeyUsageNumber.TGS_REP_encrypted_part_subkey);

            BaseTestSite.Assert.IsNotNull(userKrbTgsRep.Response, "The Response pare of TGS-REP is not null.");
            BaseTestSite.Assert.IsNotNull(userKrbTgsRep.Response.padata, "The Padata of TGS-REP is not null.");

            EncryptionKey strengthenKey = null;
            foreach (PA_DATA paData in userKrbTgsRep.Response.padata.Elements)
            {
                var parsedPaData = PaDataParser.ParseRepPaData(paData);
                if (parsedPaData is PaFxFastRep)
                {
                    var armoredRep = ((PaFxFastRep)parsedPaData).GetArmoredRep();
                    var kerbRep = ((PaFxFastRep)parsedPaData).GetKerberosFastRep(client.Context.FastArmorkey);
                    strengthenKey = kerbRep.FastResponse.strengthen_key;
                }
            }
            BaseTestSite.Assert.IsNotNull(strengthenKey, "Strengthen key field must be set in TGS-REP.");

            BaseTestSite.Assert.IsNotNull(userKrbTgsRep.EncPart, "The encrypted part of TGS-REP is decrypted.");
        }
        public void PAC_DEVICE_INFO()
        {
            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();

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

            // 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;
            PaFxFastReq paFxFastReq = new PaFxFastReq(null);
            Asn1SequenceOf<PA_DATA> seqOfPaData2 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { (paFxFastReq.Data) });

            client.SendAsRequestWithFast(options, seqOfPaData2, null, subkey, fastOptions, apOptions);
            KerberosKrbError krbError2 = client.ExpectKrbError();
            BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED, krbError2.ErrorCode, "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);

            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc);
            Asn1SequenceOf<PA_DATA> seqOfPaData3 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp3.Data, paPacRequest.Data, paPacOptions.Data });

            client.SendAsRequestWithFast(options, seqOfPaData3, null, subkey, fastOptions, apOptions);
            KerberosAsResponse userKrbAsRep = client.ExpectAsResponse();
            if (testConfig.IsClaimSupported)
            {
                PaSupportedEncTypes paSupportedEncTypes = null;
                BaseTestSite.Assert.IsNotNull(userKrbAsRep.EncPart.pa_datas, "The encrypted padata of AS-REP is not null.");
                foreach (var padata in userKrbAsRep.EncPart.pa_datas.Elements)
                {
                    var parsedPadata = PaDataParser.ParseRepPaData(padata);
                    if (parsedPadata is PaSupportedEncTypes)
                        paSupportedEncTypes = parsedPadata as PaSupportedEncTypes;
                }

                BaseTestSite.Assert.IsNotNull(paSupportedEncTypes, "The encrypted padata of AS-REP contains PA_SUPPORTED_ENCTYPES.");
                BaseTestSite.Assert.IsTrue(
                    paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.Claims_Supported),
                    "Claims is supported.");
                BaseTestSite.Assert.IsTrue(
                    paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.FAST_Supported),
                    "FAST is supported.");
            }
            // FAST armored TGS_REQ and TGS_REP using user principal
            subkey = KerberosUtility.MakeKey(client.Context.SelectedEType, "Password03!", "this is a salt");

            client.Context.ArmorSessionKey = client.Context.Ticket.SessionKey;
            client.Context.ArmorTicket = client.Context.Ticket;

            client.SendTgsRequestWithExplicitFast(testConfig.LocalRealm.FileServer[0].Smb2ServiceName, options, null, null, subkey, fastOptions, apOptions);
            KerberosTgsResponse userKrbTgsRep = client.
                ExpectTgsResponse(KeyUsageNumber.TGS_REP_encrypted_part_subkey);
            if (testConfig.IsClaimSupported)
            {
                PaSupportedEncTypes paSupportedEncTypes = null;
                BaseTestSite.Assert.IsNotNull(asResponse.EncPart, "The encrypted part of AS-REP is decrypted.");
                BaseTestSite.Assert.IsNotNull(asResponse.EncPart.pa_datas, "The encrypted padata is not null.");
                foreach (var padata in userKrbTgsRep.EncPart.pa_datas.Elements)
                {
                    var parsedPadata = PaDataParser.ParseRepPaData(padata);
                    if (parsedPadata is PaSupportedEncTypes)
                        paSupportedEncTypes = parsedPadata as PaSupportedEncTypes;
                }
                BaseTestSite.Assert.IsNotNull(paSupportedEncTypes, "The encrypted padata of AS-REP contains PA_SUPPORTED_ENCTYPES.");
                BaseTestSite.Assert.IsTrue(
                    paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.CompoundIdentity_Supported),
                    "Compound identity is supported.");

                EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.FileServer[0].Smb2ServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType);
                userKrbTgsRep.DecryptTicket(key);

                //userKrbTgsRep.DecryptTicket(testConfig.LocalRealm.FileServer[0].Password, testConfig.LocalRealm.FileServer[0].ServiceSalt);

                //Verify PAC
                BaseTestSite.Assert.IsNotNull(userKrbTgsRep.TicketEncPart.authorization_data, "The ticket contains Authorization data.");
                AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(userKrbTgsRep.TicketEncPart.authorization_data.Elements);
                BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac.");

                PacDeviceInfo pacDeviceInfo = null;
                foreach (var buf in adWin2kPac.Pac.PacInfoBuffers)
                {
                    if (buf is PacDeviceInfo)
                    {
                        pacDeviceInfo = buf as PacDeviceInfo;
                        break;
                    }
                }
                BaseTestSite.Assert.IsNotNull(pacDeviceInfo, "PAC_DEVICE_INFO is generated.");
            }
        }
        public void ChangePasswordError()
        {
            base.Logging();

            if (!this.testConfig.UseProxy)
            {
                BaseTestSite.Assert.Inconclusive("This case is only applicable when Kerberos Proxy Service is in use.");
            }

            #region KRB5_KPASSWD_SOFTERROR
            //Create kerberos test client and connect
            client = new KerberosTestClient(this.testConfig.LocalRealm.RealmName,
                this.testConfig.LocalRealm.User[22].Username,
                this.testConfig.LocalRealm.User[22].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;
            }

            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends AS_REQ without Pre-Authentication data for password change");
            client.SendAsRequestForPwdChange(options, null);
            //Recieve preauthentication required error
            METHOD_DATA methodData;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "KDC returns KRB_ERROR: KDC_ERR_PREAUTH_REQUIRED");
            KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData);

            //Create sequence of PA data
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends AS_REQ with PA-ENC-TIMESTAMP and PA-PAC-REQUEST for password change");
            string timeStamp = KerberosUtility.CurrentKerberosTime.Value;
            PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp,
                0,
                this.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.SendAsRequestForPwdChange(options, seqOfPaData);
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "KDC returns AS_REP");
            KerberosAsResponse asResponse = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");

            //Create kpassword test client and connect
            KpasswdTestClient kpassClient = new KpasswdTestClient(
                testConfig.LocalRealm.KDC[0].IPAddress,
                KerberosConstValue.KPASSWORD_PORT,
                testConfig.TransportType,
                client.Context.Ticket);

            // 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;
                kpassClient.UseProxy = true;
                kpassClient.ProxyClient = proxyClient;
            }

            //Specify a new password which doesn't meet the complexity requirements
            string newPwd = "123";
            //Create and send Kpassword request
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends KpasswordRequest");
            kpassClient.SendKpasswordRequest(newPwd);
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "KDC returns KpasswordResponse");
            KpasswordResponse kpassResponse = kpassClient.ExpectKpasswordResponse();

            //Verify the result code
            BaseTestSite.Assert.AreEqual(KpasswdError.KRB5_KPASSWD_SOFTERROR, (KpasswdError)kpassClient.GetResultCode(kpassResponse),
                "The result code should be KRB5_KPASSWD_SOFTERROR when the new password doesn't meet the complexity requirements.");
            #endregion KRB5_KPASSWD_SOFTERROR

            #region KRB5_KPASSWD_MALFORMED
            newPwd = this.testConfig.LocalRealm.User[22].Password;
            //Create and send Kpassword request
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends KpasswordRequest");
            kpassClient.SendMalformedKpasswordRequest(newPwd);
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "KDC returns KpasswordResponse");
            kpassResponse = kpassClient.ExpectKpasswordResponse();

            //Verify the result code
            BaseTestSite.Assert.AreEqual(KpasswdError.KRB5_KPASSWD_MALFORMED, (KpasswdError)kpassClient.GetResultCode(kpassResponse),
                "The result code should be KRB5_KPASSWD_MALFORMED when the request is malformed.");
            #endregion KRB5_KPASSWD_MALFORMED

            #region KRB5_KPASSWD_AUTHERROR
            //Create and send Kpassword request
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends KpasswordRequest");
            kpassClient.SendAuthErrorKpasswordRequest(newPwd);
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "KDC returns KpasswordResponse");
            kpassResponse = kpassClient.ExpectKpasswordResponse();

            //Verify the result code
            BaseTestSite.Assert.AreEqual(KpasswdError.KRB5_KPASSWD_AUTHERROR, (KpasswdError)kpassClient.GetResultCode(kpassResponse),
                "The result code should be KRB5_KPASSWD_AUTHERROR when the request fails due to an error in authentication processing.");
            #endregion KRB5_KPASSWD_AUTHERROR

            #region KRB5_KPASSWD_ACCESSDENIED
            //Create kerberos test client and connect
            //Use the user who can't change the password
            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;
            }

            options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends AS_REQ without Pre-Authentication data for password change");
            client.SendAsRequestForPwdChange(options, null);
            //Recieve preauthentication required error
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "KDC returns KRB_ERROR: KDC_ERR_PREAUTH_REQUIRED");
            krbError = client.ExpectPreauthRequiredError(out methodData);

            //Create sequence of PA data
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends AS_REQ with PA-ENC-TIMESTAMP and PA-PAC-REQUEST for password change");
            timeStamp = KerberosUtility.CurrentKerberosTime.Value;
            paEncTimeStamp = new PaEncTimeStamp(timeStamp,
                0,
                this.client.Context.SelectedEType,
                this.client.Context.CName.Password,
                this.client.Context.CName.Salt);

            paPacRequest = new PaPacRequest(true);
            seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data });
            //Create and send AS request
            client.SendAsRequestForPwdChange(options, seqOfPaData);
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "KDC returns AS_REP");
            asResponse = client.ExpectAsResponse();
            BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT.");

            //Create kpassword test client and connect
            kpassClient = new KpasswdTestClient(
                testConfig.LocalRealm.KDC[0].IPAddress,
                KerberosConstValue.KPASSWORD_PORT,
                testConfig.TransportType,
                client.Context.Ticket);

            // 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;
                kpassClient.UseProxy = true;
                kpassClient.ProxyClient = proxyClient;
            }

            newPwd = this.testConfig.LocalRealm.User[1].Password;
            //Create and send Kpassword request
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends KpasswordRequest");
            kpassClient.SendKpasswordRequest(newPwd);
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "KDC returns KpasswordResponse");
            kpassResponse = kpassClient.ExpectKpasswordResponse();

            //Verify the result code
            BaseTestSite.Assert.AreEqual(KpasswdError.KRB5_KPASSWD_ACCESSDENIED, (KpasswdError)kpassClient.GetResultCode(kpassResponse),
                "The result code should be KRB5_KPASSWD_ACCESSDENIED when the user has no access to change the password.");
            #endregion KRB5_KPASSWD_ACCESSDENIED
        }
        public void ServerSignature()
        {
            base.Logging();

            //Create kerberos test client and connect
            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;
            }

            KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE;
            client.SendAsRequest(options, null);
            BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with no PA data.");
            //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, this.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.ClientComputer.DefaultServiceName, options);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
                tgsResponse.Response.ticket.realm.Value.ToLower(),
                "The realm in ticket should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName,
               KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname),
               "The Service principal name in ticket should match expected.");

            EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType);
            tgsResponse.DecryptTicket(key);

            //tgsResponse.DecryptTicket(this.testConfig.LocalRealm.ClientComputer.Password, this.testConfig.LocalRealm.ClientComputer.ServiceSalt);
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
               tgsResponse.TicketEncPart.crealm.Value.ToLower(),
               "The realm in ticket encrypted part should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].Username.ToLower(),
                KerberosUtility.PrincipalName2String(tgsResponse.TicketEncPart.cname).ToLower(),
                "The client principal name in ticket encrypted part should match expected.");
            //Verify PAC
            if (this.testConfig.IsKileImplemented)
            {
                BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data.");
                AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements);
                BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac.");
                PacServerSignature serverSignature = null;
                foreach (var buf in adWin2kPac.Pac.PacInfoBuffers)
                {
                    if (buf is PacServerSignature)
                    {
                        serverSignature = buf as PacServerSignature;
                        break;
                    }
                }
                BaseTestSite.Assert.IsNotNull(serverSignature, "Server Signature is generated.");

                var serverKey = KeyGenerator.MakeKey(
                    (EncryptionType)tgsResponse.Response.ticket.enc_part.etype.Value,
                    this.testConfig.LocalRealm.ClientComputer.Password,
                    this.testConfig.LocalRealm.ClientComputer.ServiceSalt);
                //cannot make a kdc key
                var kdcKey = KeyGenerator.MakeKey(
                    EncryptionType.AES256_CTS_HMAC_SHA1_96,
                    this.testConfig.LocalRealm.KDC[0].Password,
                    this.testConfig.LocalRealm.RealmName.ToUpper() + "krbtgt"
                    );
                bool isServerSignValidate = false;
                bool isKdcSignValidate = false;

                adWin2kPac.Pac.ValidateSign(serverKey, kdcKey, out isServerSignValidate, out isKdcSignValidate);
                BaseTestSite.Assert.IsTrue(isServerSignValidate, "Server signature should be valid.");

                if ((EncryptionType)tgsResponse.Response.ticket.enc_part.etype.Value == EncryptionType.RC4_HMAC
                    || (EncryptionType)tgsResponse.Response.ticket.enc_part.etype.Value == EncryptionType.DES_CBC_MD5)
                {
                    BaseTestSite.Assert.AreEqual(
                        PAC_SIGNATURE_DATA_SignatureType_Values.KERB_CHECKSUM_HMAC_MD5,
                        serverSignature.NativePacSignatureData.SignatureType,
                        "The server signature type is KERB_CHECKSUM_HMAC_MD5.");
                }
                else if ((EncryptionType)tgsResponse.Response.ticket.enc_part.etype.Value == EncryptionType.AES256_CTS_HMAC_SHA1_96)
                {
                    BaseTestSite.Assert.AreEqual(
                        PAC_SIGNATURE_DATA_SignatureType_Values.HMAC_SHA1_96_AES256,
                        serverSignature.NativePacSignatureData.SignatureType,
                        "The server signature type is HMAC_SHA1_96_AES256.");
                }
                else if ((EncryptionType)tgsResponse.Response.ticket.enc_part.etype.Value == EncryptionType.AES128_CTS_HMAC_SHA1_96)
                {
                    BaseTestSite.Assert.AreEqual(PAC_SIGNATURE_DATA_SignatureType_Values.HMAC_SHA1_96_AES128,
                        serverSignature.NativePacSignatureData.SignatureType,
                        "The server signature type is HMAC_SHA1_96_AES128.");
                }
                else
                {
                    throw new Exception("The cryptographic system is none. The checksum operation will fail.");
                }
            }
        }
        public void NetworkLogonLdapWithClaim_Ldap()
        {
            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,
                this.client.Context.SelectedEType,
                this.client.Context.CName.Password,
                this.client.Context.CName.Salt);
            PaPacRequest paPacRequest = new PaPacRequest(true);
            PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims);
            Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.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.LdapServer[0].LdapServiceName, options);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            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,
                this.testConfig.LocalRealm.LdapServer[0].GssToken);

            //AP exchange part
            byte[] repToken = this.SendAndRecieveLdapAp(this.testConfig.LocalRealm.LdapServer[0], token, this.testConfig.TrustedRealm.LdapServer[0].GssToken);
            KerberosApResponse apResponse = client.GetApResponseFromToken(repToken, this.testConfig.LocalRealm.LdapServer[0].GssToken);
        }
        public void UPN_DNS_INFO()
        {
            base.Logging();

            //Create kerberos test client and connect
            client = new KerberosTestClient(
                this.testConfig.LocalRealm.RealmName,
                this.testConfig.LocalRealm.User[5].Username,
                this.testConfig.LocalRealm.User[5].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;
            }

            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, this.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.ClientComputer.DefaultServiceName, options);
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();

            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
                tgsResponse.Response.ticket.realm.Value.ToLower(),
                "The realm in ticket should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName,
               KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname),
               "The Service principal name in ticket should match expected.");

            EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType);
            tgsResponse.DecryptTicket(key);

            //tgsResponse.DecryptTicket(this.testConfig.LocalRealm.ClientComputer.Password, this.testConfig.LocalRealm.ClientComputer.ServiceSalt);
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
               tgsResponse.TicketEncPart.crealm.Value.ToLower(),
               "The realm in ticket encrypted part should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[5].Username.ToLower(),
                KerberosUtility.PrincipalName2String(tgsResponse.TicketEncPart.cname).ToLower(),
                "The client principal name in ticket encrypted part should match expected.");
            //Verify PAC
            if (this.testConfig.IsKileImplemented)
            {
                BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data.");
                AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements);
                BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac.");
                UpnDnsInfo upnDnsInfo = null;
                foreach (var buf in adWin2kPac.Pac.PacInfoBuffers)
                {
                    if (buf is UpnDnsInfo)
                    {
                        upnDnsInfo = buf as UpnDnsInfo;
                        break;
                    }
                }
                BaseTestSite.Assert.IsNotNull(upnDnsInfo, "UPN_DNS_INFO is generated.");
                BaseTestSite.Assert.AreEqual(
                    upnDnsInfo.Upn.Length * 2,
                    upnDnsInfo.NativeUpnDnsInfo.UpnLength,
                    "The UpnLength field SHOULD be the length of the UPN field, in bytes.");
                BaseTestSite.Assert.AreEqual(
                    upnDnsInfo.DnsDomain.Length * 2,
                    upnDnsInfo.NativeUpnDnsInfo.DnsDomainNameLength,
                    "The DnsDomainNameLength field SHOULD be the length of the DnsDomainName field, in bytes.");
                BaseTestSite.Assert.AreEqual(
                    UPN_DNS_INFO_Flags_Values.NoUpnAttribute,
                    upnDnsInfo.NativeUpnDnsInfo.Flags & UPN_DNS_INFO_Flags_Values.NoUpnAttribute,
                    "The Flags field SHOULD set the U bit if the user account object does not have the userPrincipalName attribute ([MS-ADA3] (file://%5bMS-ADA3%5d.pdf) section 2.349) set.");
            }
        }