/// <summary>
 ///  The SamrRemoveMemberFromForeignDomain method removes
 ///  a member from all aliases. Opnum: 45 
 /// </summary>
 /// <param name="DomainHandle">
 ///  An RPC context handle, as specified in section , representing
 ///  a domain object.
 /// </param>
 /// <param name="MemberSid">
 ///  The SID to remove from the membership.
 /// </param>
 /// <returns>
 /// status of the function call, for example: 0 indicates STATUS_SUCCESS
 /// </returns>
 public int SamrRemoveMemberFromForeignDomain(System.IntPtr DomainHandle, _RPC_SID? MemberSid)
 {
     return rpc.SamrRemoveMemberFromForeignDomain(DomainHandle, MemberSid);
 }
 /// <summary>
 ///  The SamrOpenDomain method obtains a handle to a domain
 ///  object, given a SID. Opnum: 7 
 /// </summary>
 /// <param name="ServerHandle">
 ///  An RPC context handle, as specified in section , representing
 ///  a server object.
 /// </param>
 /// <param name="DesiredAccess">
 ///  An ACCESS_MASK. See section  for a list of domain access
 ///  values.
 /// </param>
 /// <param name="DomainId">
 ///  A SID value of a domain hosted by the server side of
 ///  this protocol.
 /// </param>
 /// <param name="DomainHandle">
 ///  An RPC context handle, as specified in section.
 /// </param>
 /// <returns>
 /// status of the function call, for example: 0 indicates STATUS_SUCCESS
 /// </returns>
 public int SamrOpenDomain(System.IntPtr ServerHandle,
     uint DesiredAccess, _RPC_SID? DomainId, out System.IntPtr DomainHandle)
 {
     return rpc.SamrOpenDomain(ServerHandle, DesiredAccess, DomainId, out DomainHandle);
 }
 /// <summary>
 ///  The SamrRemoveMemberFromAlias method removes a member
 ///  from an alias. Opnum: 32 
 /// </summary>
 /// <param name="AliasHandle">
 ///  An RPC context handle, as specified in section , representing
 ///  an alias object.
 /// </param>
 /// <param name="MemberId">
 ///  The SID of an account to remove from the alias.
 /// </param>
 /// <returns>
 /// status of the function call, for example: 0 indicates STATUS_SUCCESS
 /// </returns>
 public int SamrRemoveMemberFromAlias(System.IntPtr AliasHandle, _RPC_SID MemberId)
 {
     return rpc.SamrRemoveMemberFromAlias(AliasHandle, MemberId);
 }
        public static KERB_SID_AND_ATTRIBUTES[] GetResourceGroupExtraSids(string domainName, NetworkCredential cred, uint resourceGroupCount, Group[] resourceGroups)
        {
            LdapConnection connection = new LdapConnection(domainName);
            connection.Credential = cred;
            KERB_SID_AND_ATTRIBUTES[] resourceGroupExtraSids = new KERB_SID_AND_ATTRIBUTES[resourceGroupCount];

            for (int i = 0; i < resourceGroupCount; i++)
            {
                string dn = GetDomainDnFromDomainName(domainName);
                string targetOu = dn;
                string filter = "cn=" + resourceGroups[i].GroupName;
                SearchRequest searchRequest = new SearchRequest(targetOu, filter, SearchScope.Subtree, "objectSid");
                SearchResponse searchResponse = (SearchResponse)connection.SendRequest(searchRequest);
                if (searchResponse.Entries.Count > 1)
                {
                    throw new Exception("There are more than one entries with the same resourceGroupName.");
                }
                SearchResultAttributeCollection groupAttributes = searchResponse.Entries[0].Attributes;
                string[] tmp = GetobjectSid(groupAttributes).Split('-');

                _RPC_SID resourceGroupSid = new _RPC_SID();
                resourceGroupSid.Revision = 0x01;
                resourceGroupSid.IdentifierAuthority = new _RPC_SID_IDENTIFIER_AUTHORITY();
                resourceGroupSid.IdentifierAuthority.Value = new byte[] { 0, 0, 0, 0, 0, 5 };
                resourceGroupSid.SubAuthorityCount = Convert.ToByte(tmp.Length - 3);
                resourceGroupSid.SubAuthority = new uint[tmp.Length - 3];
                for (int j = 3; j < tmp.Length; j++)
                {
                    resourceGroupSid.SubAuthority[j - 3] = Convert.ToUInt32(tmp[j]);
                }

                resourceGroupExtraSids[i] = new KERB_SID_AND_ATTRIBUTES();
                resourceGroupExtraSids[i].Attributes = Attributes_Values.Mandatory | Attributes_Values.EnabledByDefault | Attributes_Values.Enabled | Attributes_Values.Resource;
                resourceGroupExtraSids[i].SID = new _RPC_SID[1];
                resourceGroupExtraSids[i].SID[0] = resourceGroupSid;
            }
            return resourceGroupExtraSids;
        }
 /// <summary>
 ///  The SamrLookupDomainInSamServer method obtains the SID
 ///  of a domain object, given the object's name. Opnum
 ///  : 5 
 /// </summary>
 /// <param name="ServerHandle">
 ///  An RPC context handle, as specified in section , representing
 ///  a server object.
 /// </param>
 /// <param name="Name">
 ///  A UTF-16 encoded string.
 /// </param>
 /// <param name="DomainId">
 ///  A SID value of a domain that matches the Name passed
 ///  in. The match must be exact (no wildcards are permitted).
 ///  See message processing later in this section for more
 ///  details.
 /// </param>
 /// <returns>
 /// status of the function call, for example: 0 indicates STATUS_SUCCESS
 /// </returns>
 public int SamrLookupDomainInSamServer(System.IntPtr ServerHandle,
     _RPC_UNICODE_STRING Name, out _RPC_SID? DomainId)
 {
     return rpc.SamrLookupDomainInSamServer(ServerHandle, Name, out DomainId);
 }
 /// <summary>
 ///  Decodes the request stub, and fills the fields of the class
 /// </summary>
 /// <param name="sessionContext">The session context of the request received</param>
 /// <param name="requestStub">The request stub got from RPCE layer</param>
 internal override void Decode(SamrServerSessionContext sessionContext, byte[] requestStub)
 {
     using (RpceInt3264Collection inParams = RpceStubDecoder.ToParamList(
    RpceStubHelper.GetPlatform(),
     SamrRpcStubFormatString.TypeFormatString,
     new RpceStubExprEval[]{
         new RpceStubExprEval(SamrRpcAdapter.samr_SAMPR_USER_LOGON_INFORMATIONExprEval_0000),
         new RpceStubExprEval(SamrRpcAdapter.samr_SAMPR_USER_LOGON_HOURS_INFORMATIONExprEval_0001),
         new RpceStubExprEval(SamrRpcAdapter.samr_SAMPR_USER_ACCOUNT_INFORMATIONExprEval_0002),
         new RpceStubExprEval(SamrRpcAdapter.samr_SAMPR_LOGON_HOURSExprEval_0003)},
     SamrRpcStubFormatString.ProcFormatString,
     SamrRpcStubFormatString.ProcFormatStringOffsetTable[(int)Opnum],
     false,
     requestStub))
     {
         AliasHandle = inParams[0].ToIntPtr();
         MemberId = TypeMarshal.ToStruct<_RPC_SID>(inParams[1]);
     }
 }
        /// <summary>
        ///  The SamrRidToSid method obtains the SID of an account,
        ///  given a RID. Opnum: 65 
        /// </summary>
        /// <param name="ObjectHandle">
        ///  An RPC context handle, as specified in section. The
        ///  message processing shown later in this section contains
        ///  details on which types of ObjectHandle are accepted
        ///  by the server.
        /// </param>
        /// <param name="Rid">
        ///  A RID of an account.
        /// </param>
        /// <param name="Sid">
        ///  The SID of the account referenced by Rid.
        /// </param>
        /// <returns>
        /// status of the function call, for example: 0 indicates STATUS_SUCCESS
        /// </returns>
        public int SamrRidToSid(System.IntPtr ObjectHandle, uint Rid, out _RPC_SID? Sid)
        {
            const ushort opnum = 65;
            Int3264[] paramList;
            int retVal = 0;

            paramList = new Int3264[] {
                ObjectHandle,
                Rid,
                IntPtr.Zero,
                IntPtr.Zero
            };

            using (RpceInt3264Collection outParamList = RpceCall(paramList, opnum))
            {
                Sid = TypeMarshal.ToNullableStruct<_RPC_SID>(Marshal.ReadIntPtr(outParamList[2]));
                retVal = outParamList[3].ToInt32();
            }

            return retVal;
        }
        /// <summary>
        ///  The SamrOpenDomain method obtains a handle to a domain
        ///  object, given a SID. Opnum: 7 
        /// </summary>
        /// <param name="ServerHandle">
        ///  An RPC context handle, as specified in section , representing
        ///  a server object.
        /// </param>
        /// <param name="DesiredAccess">
        ///  An ACCESS_MASK. See section  for a list of domain access
        ///  values.
        /// </param>
        /// <param name="DomainId">
        ///  A SID value of a domain hosted by the server side of
        ///  this protocol.
        /// </param>
        /// <param name="DomainHandle">
        ///  An RPC context handle, as specified in section.
        /// </param>
        /// <returns>
        /// status of the function call, for example: 0 indicates STATUS_SUCCESS
        /// </returns>
        public int SamrOpenDomain(IntPtr ServerHandle, uint DesiredAccess, _RPC_SID? DomainId, out IntPtr DomainHandle)
        {
            const ushort opnum = 7;
            Int3264[] paramList;
            int retVal = 0;

            SafeIntPtr pDomainId = TypeMarshal.ToIntPtr(DomainId);

            paramList = new Int3264[] {
                ServerHandle,
                DesiredAccess,
                pDomainId,
                IntPtr.Zero,
                IntPtr.Zero
            };

            try
            {
                using (RpceInt3264Collection outParamList = RpceCall(paramList, opnum))
                {
                    DomainHandle = Marshal.ReadIntPtr(outParamList[3]);
                    retVal = outParamList[4].ToInt32();
                }
            }
            finally
            {
                pDomainId.Dispose();
            }

            return retVal;
        }
        /// <summary>
        ///  The SamrRemoveMemberFromAlias method removes a member
        ///  from an alias. Opnum: 32 
        /// </summary>
        /// <param name="AliasHandle">
        ///  An RPC context handle, as specified in section , representing
        ///  an alias object.
        /// </param>
        /// <param name="MemberId">
        ///  The SID of an account to remove from the alias.
        /// </param>
        /// <returns>
        /// status of the function call, for example: 0 indicates STATUS_SUCCESS
        /// </returns>
        public int SamrRemoveMemberFromAlias(IntPtr AliasHandle, _RPC_SID MemberId)
        {
            const ushort opnum = 32;
            Int3264[] paramList;
            int retVal = 0;

            SafeIntPtr pMemberId = TypeMarshal.ToIntPtr(MemberId);

            paramList = new Int3264[] {
                AliasHandle,
                pMemberId,
                IntPtr.Zero
            };

            try
            {
                using (RpceInt3264Collection outParamList = RpceCall(paramList, opnum))
                {
                    retVal = outParamList[2].ToInt32();
                }
            }
            finally
            {
                pMemberId.Dispose();
            }

            return retVal;
        }
        /// <summary>
        /// Convert RPC_SID to SDDL string.
        /// </summary>
        /// <param name="rpcSid">RPC_SID to convert.</param>
        /// <returns>SDDL string.</returns>
        /// <exception cref="ArgumentException">
        /// Thrown when the Revision field of sid is invalid. 
        /// Thrown when length of identifierAuthority is not 6 bytes.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// Thrown when identifierAuthority is null.
        /// </exception>
        public static string ToSddlString(_RPC_SID rpcSid)
        {
            _SID sid = CreateSid(rpcSid.IdentifierAuthority.Value, rpcSid.SubAuthority);

            return ToSddlString(sid);
        }
        /// <summary>
        ///  The SamrLookupDomainInSamServer method obtains the SID
        ///  of a domain object, given the object's name. Opnum
        ///  : 5 
        /// </summary>
        /// <param name="ServerHandle">
        ///  An RPC context handle, as specified in section , representing
        ///  a server object.
        /// </param>
        /// <param name="Name">
        ///  A UTF-16 encoded string.
        /// </param>
        /// <param name="DomainId">
        ///  A SID value of a domain that matches the Name passed
        ///  in. The match must be exact (no wildcards are permitted).
        ///  See message processing later in this section for more
        ///  details.
        /// </param>
        /// <returns>
        /// status of the function call, for example: 0 indicates STATUS_SUCCESS
        /// </returns>
        public int SamrLookupDomainInSamServer(IntPtr ServerHandle, _RPC_UNICODE_STRING Name, out _RPC_SID? DomainId)
        {
            const ushort opnum = 5;
            Int3264[] paramList;
            int retVal = 0;

            SafeIntPtr pName = TypeMarshal.ToIntPtr(Name);

            paramList = new Int3264[] {
                ServerHandle,
                pName,
                IntPtr.Zero,
                IntPtr.Zero
            };

            try
            {
                using (RpceInt3264Collection outParamList = RpceCall(paramList, opnum))
                {
                    DomainId = TypeMarshal.ToNullableStruct<_RPC_SID>(Marshal.ReadIntPtr(outParamList[2]));
                    retVal = outParamList[3].ToInt32();
                }
            }
            finally
            {
                pName.Dispose();
            }

            return retVal;
        }
        /// <summary>
        /// Create an instance of RPC_SID.
        /// </summary>
        /// <param name="identifierAuthority">
        /// Six element arrays of 8-bit unsigned integers that specify 
        /// the top-level authority of a RPC_SID.
        /// </param>
        /// <param name="subAuthorities">
        /// A variable length array of unsigned 32-bit integers that 
        /// uniquely identifies a principal relative to the IdentifierAuthority.
        /// </param>
        /// <returns>Created RPC_SID structure.</returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown when identifierAuthority or subAuthorities is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Thrown when length of identifierAuthority is not 6 bytes.
        /// </exception>
        public static _RPC_SID CreateRpcSid(
            byte[] identifierAuthority,
            params uint[] subAuthorities)
        {
            if (identifierAuthority == null)
            {
                throw new ArgumentNullException("identifierAuthority");
            }
            if (identifierAuthority.Length != SID_AUTHORITY_LENGTH)
            {
                throw new ArgumentException("Incorrect size of identifierAuthority.", "identifierAuthority");
            }
            if (subAuthorities == null)
            {
                throw new ArgumentNullException("subAuthorities");
            }

            const byte DEFAULT_REVISION = 1;

            _RPC_SID rpcSid = new _RPC_SID();
            rpcSid.Revision = DEFAULT_REVISION;
            rpcSid.SubAuthorityCount = (byte)subAuthorities.Length;
            rpcSid.IdentifierAuthority.Value = identifierAuthority;
            rpcSid.SubAuthority = subAuthorities;
            return rpcSid;
        }
        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 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...");
            }
        }
 /// <summary>
 ///  The SamrRidToSid method obtains the SID of an account,
 ///  given a RID. Opnum: 65 
 /// </summary>
 /// <param name="ObjectHandle">
 ///  An RPC context handle, as specified in section. The
 ///  message processing shown later in this section contains
 ///  details on which types of ObjectHandle are accepted
 ///  by the server.
 /// </param>
 /// <param name="Rid">
 ///  A RID of an account.
 /// </param>
 /// <param name="Sid">
 ///  The SID of the account referenced by Rid.
 /// </param>
 /// <returns>
 /// status of the function call, for example: 0 indicates STATUS_SUCCESS
 /// </returns>
 public int SamrRidToSid(System.IntPtr ObjectHandle, uint Rid, out _RPC_SID? Sid)
 {
     return rpc.SamrRidToSid(ObjectHandle, Rid, out Sid);
 }
        /// <summary>
        ///  The SamrRemoveMemberFromForeignDomain method removes
        ///  a member from all aliases. Opnum: 45 
        /// </summary>
        /// <param name="DomainHandle">
        ///  An RPC context handle, as specified in section , representing
        ///  a domain object.
        /// </param>
        /// <param name="MemberSid">
        ///  The SID to remove from the membership.
        /// </param>
        /// <returns>
        /// status of the function call, for example: 0 indicates STATUS_SUCCESS
        /// </returns>
        public int SamrRemoveMemberFromForeignDomain(IntPtr DomainHandle, _RPC_SID? MemberSid)
        {
            const ushort opnum = 45;
            Int3264[] paramList;
            int retVal = 0;

            SafeIntPtr pMemberSid = TypeMarshal.ToIntPtr(MemberSid);

            paramList = new Int3264[] {
                DomainHandle,
                pMemberSid,
                IntPtr.Zero
            };

            try
            {
                using (RpceInt3264Collection outParamList = RpceCall(paramList, opnum))
                {
                    retVal = outParamList[2].ToInt32();
                }
            }
            finally
            {
                pMemberSid.Dispose();
            }

            return retVal;
        }
 /// <summary>
 ///  The SamrAddMemberToAlias method adds a member to an
 ///  alias. Opnum: 31 
 /// </summary>
 /// <param name="AliasHandle">
 ///  An RPC context handle, as specified in section , representing
 ///  an alias object.
 /// </param>
 /// <param name="MemberId">
 ///  The SID of an account to add to the alias.
 /// </param>
 /// <returns>
 /// status of the function call, for example: 0 indicates STATUS_SUCCESS
 /// </returns>
 public int SamrAddMemberToAlias(System.IntPtr AliasHandle, _RPC_SID MemberId)
 {
     return rpc.SamrAddMemberToAlias(AliasHandle, MemberId);
 }
        public void CrossRealm_OtherOrgSIDinPACSuccess()
        {
            base.Logging();

            //setSelectiveAuth is for windows only
            if (this.testConfig.TrustedRealm.KDC[0].IsWindows && this.testConfig.TrustType != TrustType.NoTrust)
            {
                sutController.setSelectiveAuth(this.testConfig.TrustedRealm.RealmName,
                    this.testConfig.TrustedRealm.Admin.Username,
                    this.testConfig.TrustedRealm.Admin.Password,
                    this.testConfig.LocalRealm.RealmName,
                    true);
            }
            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);

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

            Asn1SequenceOf<PA_DATA> seqOfPaData2 = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] {paPacRequest.Data, paPacOptions.Data });
            //Create and send TGS request
            if (this.testConfig.TrustType == Adapter.TrustType.Forest)
            {
                client.SendTgsRequest(this.testConfig.TrustedRealm.FileServer[0].Smb2ServiceName, options, seqOfPaData2);
            }
            else if (this.testConfig.TrustType == Adapter.TrustType.Realm)
            {
                client.SendTgsRequest(this.testConfig.TrustedRealm.KDC[0].DefaultServiceName, options, seqOfPaData2);
            }
            KerberosTgsResponse tgsResponse = client.ExpectTgsResponse();
            EncryptionKey key = testConfig.QueryKey(
                    this.testConfig.TrustedRealm.KDC[0].DefaultServiceName + "@" + this.testConfig.LocalRealm.RealmName,
                    client.Context.Realm.ToString(),
                    client.Context.SelectedEType);
            tgsResponse.DecryptTicket(key);

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

            //Change realm
            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.SendTgsRequest(this.testConfig.TrustedRealm.FileServer[0].Smb2ServiceName, options, seqOfPaData2);
            KerberosTgsResponse refTgsResponse = client.ExpectTgsResponse();

            BaseTestSite.Assert.AreEqual(this.testConfig.TrustedRealm.FileServer[0].Smb2ServiceName,
               KerberosUtility.PrincipalName2String(refTgsResponse.Response.ticket.sname),
               "The service principal name in service ticket should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.TrustedRealm.RealmName.ToLower(),
               refTgsResponse.Response.ticket.realm.Value.ToLower(),
               "The realm name in service ticket should match expected.");

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

            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(),
                refTgsResponse.TicketEncPart.crealm.Value.ToLower(),
                "Realm name in service ticket encrypted part should match expected.");
            BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[1].Username.ToLower(),
                KerberosUtility.PrincipalName2String(refTgsResponse.TicketEncPart.cname).ToLower(),
                "User name in service ticket encrypted part should match expected.");

            //Verify PAC
            if (this.testConfig.IsKileImplemented && this.testConfig.LocalRealm.KDC[0].IsWindows)
            {
                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.");
                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 = 3 because, one for AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY SID, one for CLAIMS_VALID SID and one for OTHER_ORGANIZATION SID
                uint expectedSidCount = 3;
                BaseTestSite.Assert.AreEqual(expectedSidCount, kerbValidationInfo.NativeKerbValidationInfo.SidCount, "The SidCount includes the number of one AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY, one CLAIMS_VALID, and one OTHER_ORGANIZATION.");

                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;

                //The AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY SID is "S-1-5-1000"
                _RPC_SID OTHER_ORGANIZATION = new _RPC_SID();
                OTHER_ORGANIZATION.Revision = 0x01;
                OTHER_ORGANIZATION.IdentifierAuthority = new _RPC_SID_IDENTIFIER_AUTHORITY();
                OTHER_ORGANIZATION.IdentifierAuthority.Value = new byte[] { 0, 0, 0, 0, 0, 5 };
                OTHER_ORGANIZATION.SubAuthorityCount = 1;
                OTHER_ORGANIZATION.SubAuthority = new uint[] { 1000 };
                expectedDefaultExtraSids[2] = new KERB_SID_AND_ATTRIBUTES();
                expectedDefaultExtraSids[2].Attributes = Attributes_Values.Mandatory | Attributes_Values.EnabledByDefault | Attributes_Values.Enabled;
                expectedDefaultExtraSids[2].SID = new _RPC_SID[1];
                expectedDefaultExtraSids[2].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.");

                //setSelectiveAuth is for windows only
                if (this.testConfig.TrustedRealm.KDC[0].IsWindows && this.testConfig.TrustType != TrustType.NoTrust)
                {

                    sutController.setSelectiveAuth(this.testConfig.TrustedRealm.RealmName,
                    this.testConfig.TrustedRealm.Admin.Username,
                    this.testConfig.TrustedRealm.Admin.Password,
                    this.testConfig.LocalRealm.RealmName,
                    false);
                }
            }
        }