internal static void VerifyTrust(DirectoryContext context, string sourceName, string targetName, bool isForest, TrustDirection direction, bool forceSecureChannelReset, string preferredTargetServer)
        {
            PolicySafeHandle   handle = null;
            LSA_UNICODE_STRING result = null;
            int    errorCode          = 0;
            IntPtr zero       = IntPtr.Zero;
            IntPtr ptr        = IntPtr.Zero;
            IntPtr buffer     = IntPtr.Zero;
            IntPtr ptr4       = IntPtr.Zero;
            bool   flag       = true;
            IntPtr s          = IntPtr.Zero;
            string serverName = null;

            serverName = System.DirectoryServices.ActiveDirectory.Utils.GetPolicyServerName(context, isForest, false, sourceName);
            flag       = System.DirectoryServices.ActiveDirectory.Utils.Impersonate(context);
            try
            {
                try
                {
                    handle = new PolicySafeHandle(System.DirectoryServices.ActiveDirectory.Utils.GetPolicyHandle(serverName));
                    result = new LSA_UNICODE_STRING();
                    s      = Marshal.StringToHGlobalUni(targetName);
                    UnsafeNativeMethods.RtlInitUnicodeString(result, s);
                    ValidateTrust(handle, result, sourceName, targetName, isForest, (int)direction, serverName);
                    if (preferredTargetServer == null)
                    {
                        zero = Marshal.StringToHGlobalUni(targetName);
                    }
                    else
                    {
                        zero = Marshal.StringToHGlobalUni(targetName + @"\" + preferredTargetServer);
                    }
                    ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                    Marshal.WriteIntPtr(ptr, zero);
                    if (!forceSecureChannelReset)
                    {
                        errorCode = UnsafeNativeMethods.I_NetLogonControl2(serverName, NETLOGON_CONTROL_TC_VERIFY, NETLOGON_QUERY_LEVEL, ptr, out buffer);
                        if (errorCode != 0)
                        {
                            if (errorCode == ERROR_INVALID_LEVEL)
                            {
                                throw new NotSupportedException(Res.GetString("TrustVerificationNotSupport"));
                            }
                            throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
                        }
                        NETLOGON_INFO_2 structure = new NETLOGON_INFO_2();
                        Marshal.PtrToStructure(buffer, structure);
                        if ((structure.netlog2_flags & NETLOGON_VERIFY_STATUS_RETURNED) == 0)
                        {
                            throw ExceptionHelper.GetExceptionFromErrorCode(structure.netlog2_tc_connection_status);
                        }
                        int num2 = structure.netlog2_pdc_connection_status;
                        if (num2 != 0)
                        {
                            throw ExceptionHelper.GetExceptionFromErrorCode(num2);
                        }
                    }
                    else
                    {
                        errorCode = UnsafeNativeMethods.I_NetLogonControl2(serverName, NETLOGON_CONTROL_REDISCOVER, NETLOGON_QUERY_LEVEL, ptr, out ptr4);
                        if (errorCode != 0)
                        {
                            throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
                        }
                    }
                }
                finally
                {
                    if (flag)
                    {
                        System.DirectoryServices.ActiveDirectory.Utils.Revert();
                    }
                    if (s != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(s);
                    }
                    if (ptr != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(ptr);
                    }
                    if (zero != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(zero);
                    }
                    if (buffer != IntPtr.Zero)
                    {
                        UnsafeNativeMethods.NetApiBufferFree(buffer);
                    }
                    if (ptr4 != IntPtr.Zero)
                    {
                        UnsafeNativeMethods.NetApiBufferFree(ptr4);
                    }
                }
            }
            catch
            {
                throw;
            }
        }
Exemplo n.º 2
0
        internal static void VerifyTrust(DirectoryContext context, string? sourceName, string? targetName, bool isForest, TrustDirection direction, bool forceSecureChannelReset, string? preferredTargetServer)
        {
            PolicySafeHandle? policyHandle = null;
            LSA_UNICODE_STRING? trustedDomainName = null;
            int win32Error = 0;
            IntPtr data = (IntPtr)0;
            IntPtr ptr = (IntPtr)0;
            IntPtr buffer1 = (IntPtr)0;
            IntPtr buffer2 = (IntPtr)0;
            bool impersonated = true;
            IntPtr target = (IntPtr)0;
            string? policyServerName = null;

            policyServerName = Utils.GetPolicyServerName(context, isForest, false, sourceName);

            impersonated = Utils.Impersonate(context);

            try
            {
                try
                {
                    // get the policy handle
                    policyHandle = new PolicySafeHandle(Utils.GetPolicyHandle(policyServerName));

                    // get the target name
                    trustedDomainName = new LSA_UNICODE_STRING();
                    target = Marshal.StringToHGlobalUni(targetName);
                    UnsafeNativeMethods.RtlInitUnicodeString(trustedDomainName, target);

                    // validate the trust existence
                    ValidateTrust(policyHandle, trustedDomainName, sourceName, targetName, isForest, (int)direction, policyServerName);  // need to verify direction

                    if (preferredTargetServer == null)
                        data = Marshal.StringToHGlobalUni(targetName);
                    else
                        // this is the case that we need to specifically go to a particular server. This is the way to tell netlogon to do that.
                        data = Marshal.StringToHGlobalUni(targetName + "\\" + preferredTargetServer);
                    ptr = Marshal.AllocHGlobal(IntPtr.Size);
                    Marshal.WriteIntPtr(ptr, data);

                    if (!forceSecureChannelReset)
                    {
                        win32Error = UnsafeNativeMethods.I_NetLogonControl2(policyServerName, NETLOGON_CONTROL_TC_VERIFY, NETLOGON_QUERY_LEVEL, ptr, out buffer1);

                        if (win32Error == 0)
                        {
                            NETLOGON_INFO_2 info = new NETLOGON_INFO_2();
                            Marshal.PtrToStructure(buffer1, info);

                            if ((info.netlog2_flags & NETLOGON_VERIFY_STATUS_RETURNED) != 0)
                            {
                                int result = info.netlog2_pdc_connection_status;
                                if (result == 0)
                                {
                                    // verification succeeded
                                    return;
                                }
                                else
                                {
                                    // don't really know which server is down, the source or the target
                                    throw ExceptionHelper.GetExceptionFromErrorCode(result);
                                }
                            }
                            else
                            {
                                int result = info.netlog2_tc_connection_status;
                                throw ExceptionHelper.GetExceptionFromErrorCode(result);
                            }
                        }
                        else
                        {
                            if (win32Error == ERROR_INVALID_LEVEL)
                            {
                                // it is pre-win2k SP3 dc that does not support NETLOGON_CONTROL_TC_VERIFY
                                throw new NotSupportedException(SR.TrustVerificationNotSupport);
                            }
                            else
                            {
                                throw ExceptionHelper.GetExceptionFromErrorCode(win32Error);
                            }
                        }
                    }
                    else
                    {
                        // then try secure channel reset
                        win32Error = UnsafeNativeMethods.I_NetLogonControl2(policyServerName, NETLOGON_CONTROL_REDISCOVER, NETLOGON_QUERY_LEVEL, ptr, out buffer2);
                        if (win32Error != 0)
                            // don't really know which server is down, the source or the target
                            throw ExceptionHelper.GetExceptionFromErrorCode(win32Error);
                    }
                }
                finally
                {
                    if (impersonated)
                        Utils.Revert();

                    if (target != (IntPtr)0)
                        Marshal.FreeHGlobal(target);

                    if (ptr != (IntPtr)0)
                        Marshal.FreeHGlobal(ptr);

                    if (data != (IntPtr)0)
                        Marshal.FreeHGlobal(data);

                    if (buffer1 != (IntPtr)0)
                        UnsafeNativeMethods.NetApiBufferFree(buffer1);

                    if (buffer2 != (IntPtr)0)
                        UnsafeNativeMethods.NetApiBufferFree(buffer2);
                }
            }
            catch { throw; }
        }