Ejemplo n.º 1
0
        internal ForestTrustDomainInformation(int flag, LSA_FOREST_TRUST_DOMAIN_INFO domainInfo, LARGE_INTEGER time)
        {
            _status     = (ForestTrustDomainStatus)flag;
            DnsName     = Marshal.PtrToStringUni(domainInfo.DNSNameBuffer, domainInfo.DNSNameLength / 2);
            NetBiosName = Marshal.PtrToStringUni(domainInfo.NetBIOSNameBuffer, domainInfo.NetBIOSNameLength / 2);

            string sidLocal;

            global::Interop.BOOL result = global::Interop.Advapi32.ConvertSidToStringSid(domainInfo.sid, out sidLocal);
            if (result == global::Interop.BOOL.FALSE)
            {
                throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
            }

            DomainSid = sidLocal;
            this.time = time;
        }
        public void Save()
        {
            int    count               = 0;
            IntPtr records             = (IntPtr)0;
            int    currentCount        = 0;
            IntPtr tmpPtr              = (IntPtr)0;
            IntPtr forestInfo          = (IntPtr)0;
            SafeLsaPolicyHandle?handle = null;
            IntPtr    collisionInfo    = (IntPtr)0;
            ArrayList ptrList          = new ArrayList();
            ArrayList sidList          = new ArrayList();
            bool      impersonated     = false;
            IntPtr    target           = (IntPtr)0;
            string?   serverName       = null;
            IntPtr    fileTime         = (IntPtr)0;

            // first get the count of all the records
            int toplevelNamesCount = TopLevelNames.Count;
            int excludedNamesCount = ExcludedTopLevelNames.Count;
            int trustedDomainCount = TrustedDomainInformation.Count;
            int binaryDataCount    = _binaryData.Count;

            checked
            {
                count += toplevelNamesCount;
                count += excludedNamesCount;
                count += trustedDomainCount;
                count += binaryDataCount;

                // allocate the memory for all the records
                records = Marshal.AllocHGlobal(count * IntPtr.Size);
            }

            try
            {
                try
                {
                    IntPtr ptr = (IntPtr)0;
                    fileTime = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(FileTime)));
                    UnsafeNativeMethods.GetSystemTimeAsFileTime(fileTime);

                    // set the time
                    FileTime currentTime = new FileTime();
                    Marshal.PtrToStructure(fileTime, currentTime);

                    for (int i = 0; i < toplevelNamesCount; i++)
                    {
                        // now begin to construct top leve name record
                        LSA_FOREST_TRUST_RECORD record = new LSA_FOREST_TRUST_RECORD();
                        record.Flags           = (int)_topLevelNames[i].Status;
                        record.ForestTrustType = LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelName;
                        TopLevelName TLN = _topLevelNames[i];
                        record.Time = TLN.time;
                        ptr         = Marshal.StringToHGlobalUni(TLN.Name);
                        ptrList.Add(ptr);
                        UnsafeNativeMethods.RtlInitUnicodeString(out record.TopLevelName, ptr);

                        tmpPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_FOREST_TRUST_RECORD)));
                        ptrList.Add(tmpPtr);
                        Marshal.StructureToPtr(record, tmpPtr, false);

                        Marshal.WriteIntPtr(records, IntPtr.Size * currentCount, tmpPtr);

                        currentCount++;
                    }

                    for (int i = 0; i < excludedNamesCount; i++)
                    {
                        // now begin to construct excluded top leve name record
                        LSA_FOREST_TRUST_RECORD record = new LSA_FOREST_TRUST_RECORD();
                        record.Flags           = 0;
                        record.ForestTrustType = LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelNameEx;
                        if (_excludedNameTime.Contains(_excludedNames[i] !))
                        {
                            record.Time = (LARGE_INTEGER)_excludedNameTime[i] !;
                        }
                        else
                        {
                            record.Time          = new LARGE_INTEGER();
                            record.Time.lowPart  = currentTime.lower;
                            record.Time.highPart = currentTime.higher;
                        }

                        ptr = Marshal.StringToHGlobalUni(_excludedNames[i]);
                        ptrList.Add(ptr);
                        UnsafeNativeMethods.RtlInitUnicodeString(out record.TopLevelName, ptr);
                        tmpPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_FOREST_TRUST_RECORD)));
                        ptrList.Add(tmpPtr);
                        Marshal.StructureToPtr(record, tmpPtr, false);

                        Marshal.WriteIntPtr(records, IntPtr.Size * currentCount, tmpPtr);

                        currentCount++;
                    }

                    for (int i = 0; i < trustedDomainCount; i++)
                    {
                        // now begin to construct domain info record
                        LSA_FOREST_TRUST_RECORD record = new LSA_FOREST_TRUST_RECORD();
                        record.Flags           = (int)_domainInfo[i].Status;
                        record.ForestTrustType = LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustDomainInfo;
                        ForestTrustDomainInformation tmp = _domainInfo[i];
                        record.Time = tmp.time;
                        IntPtr pSid = (IntPtr)0;
                        global::Interop.BOOL result = global::Interop.Advapi32.ConvertStringSidToSid(tmp.DomainSid, out pSid);
                        if (result == global::Interop.BOOL.FALSE)
                        {
                            throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
                        }
                        record.DomainInfo.sid = pSid;
                        sidList.Add(pSid);
                        record.DomainInfo.DNSNameBuffer = Marshal.StringToHGlobalUni(tmp.DnsName);
                        ptrList.Add(record.DomainInfo.DNSNameBuffer);
                        record.DomainInfo.DNSNameLength        = (short)(tmp.DnsName == null ? 0 : tmp.DnsName.Length * 2);      // sizeof(WCHAR)
                        record.DomainInfo.DNSNameMaximumLength = (short)(tmp.DnsName == null ? 0 : tmp.DnsName.Length * 2);
                        record.DomainInfo.NetBIOSNameBuffer    = Marshal.StringToHGlobalUni(tmp.NetBiosName);
                        ptrList.Add(record.DomainInfo.NetBIOSNameBuffer);
                        record.DomainInfo.NetBIOSNameLength        = (short)(tmp.NetBiosName == null ? 0 : tmp.NetBiosName.Length * 2);
                        record.DomainInfo.NetBIOSNameMaximumLength = (short)(tmp.NetBiosName == null ? 0 : tmp.NetBiosName.Length * 2);
                        tmpPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_FOREST_TRUST_RECORD)));
                        ptrList.Add(tmpPtr);
                        Marshal.StructureToPtr(record, tmpPtr, false);

                        Marshal.WriteIntPtr(records, IntPtr.Size * currentCount, tmpPtr);

                        currentCount++;
                    }

                    for (int i = 0; i < binaryDataCount; i++)
                    {
                        LSA_FOREST_TRUST_RECORD record = new LSA_FOREST_TRUST_RECORD();
                        record.Flags           = 0;
                        record.Time            = (LARGE_INTEGER)_binaryDataTime[i] !;
                        record.Data.Length     = ((byte[])_binaryData[i] !).Length;
                        record.ForestTrustType = (LSA_FOREST_TRUST_RECORD_TYPE)_binaryRecordType[i] !;
                        if (record.Data.Length == 0)
                        {
                            record.Data.Buffer = (IntPtr)0;
                        }
                        else
                        {
                            record.Data.Buffer = Marshal.AllocHGlobal(record.Data.Length);
                            ptrList.Add(record.Data.Buffer);
                            Marshal.Copy((byte[])_binaryData[i] !, 0, record.Data.Buffer, record.Data.Length);
                        }
                        tmpPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_FOREST_TRUST_RECORD)));
                        ptrList.Add(tmpPtr);
                        Marshal.StructureToPtr(record, tmpPtr, false);

                        Marshal.WriteIntPtr(records, IntPtr.Size * currentCount, tmpPtr);

                        currentCount++;
                    }

                    // finally construct the LSA_FOREST_TRUST_INFORMATION
                    LSA_FOREST_TRUST_INFORMATION trustInformation = new LSA_FOREST_TRUST_INFORMATION();
                    trustInformation.RecordCount = count;
                    trustInformation.Entries     = records;
                    forestInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_FOREST_TRUST_INFORMATION)));
                    Marshal.StructureToPtr(trustInformation, forestInfo, false);

                    // get policy server name
                    serverName = Utils.GetPolicyServerName(context, true, true, SourceName);

                    // do impersonation first
                    impersonated = Utils.Impersonate(context);

                    // get the policy handle
                    handle = Utils.GetPolicyHandle(serverName);

                    // get the target name
                    global::Interop.UNICODE_STRING trustedDomainName;
                    target = Marshal.StringToHGlobalUni(TargetName);
                    UnsafeNativeMethods.RtlInitUnicodeString(out trustedDomainName, target);

                    // call the unmanaged function
                    uint error = UnsafeNativeMethods.LsaSetForestTrustInformation(handle, trustedDomainName, forestInfo, 1, out collisionInfo);
                    if (error != 0)
                    {
                        throw ExceptionHelper.GetExceptionFromErrorCode((int)global::Interop.Advapi32.LsaNtStatusToWinError(error), serverName);
                    }

                    // there is collision, throw proper exception so user can deal with it
                    if (collisionInfo != (IntPtr)0)
                    {
                        throw ExceptionHelper.CreateForestTrustCollisionException(collisionInfo);
                    }

                    // commit the changes
                    error = UnsafeNativeMethods.LsaSetForestTrustInformation(handle, trustedDomainName, forestInfo, 0, out collisionInfo);
                    if (error != 0)
                    {
                        throw ExceptionHelper.GetExceptionFromErrorCode((int)error, serverName);
                    }

                    // now next time property is invoked, we need to go to the server
                    retrieved = false;
                }