【问题标题】:Windows Impersonation fails silently with no error and ends executionWindows 模拟以静默方式失败,没有错误并结束执行
【发布时间】:2012-07-16 18:59:24
【问题描述】:

我正在使用以下代码在 Windows 7 上模拟用户。此代码编译为 dll 并从 python 调用。通常它可以工作,但最近我们看到主要执行失败并追溯到“WindowsIdentity.Impersonate(safeTokenHandle.DangerousGetHandle());”方法。当它被调用时,它不会冒充用户,不会引发错误,并且会立即停止执行(不会调用紧随其后的Console.WriteLine())。

有什么想法吗?请?我不想承认我花了多少时间来解决这个问题。

谢谢!

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
using System.Security;

namespace PEServ.DataIntegration.Utilities
{
    public class WindowsCredentialHelper
    {

        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
            int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);



        public WindowsCredentialHelper()
        {
            Console.WriteLine("CS: WindowsCredentialHelper instance created successfully");
        }

        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        public WindowsImpersonationContext LogonAsUser(string username, string password, string domain)
        {
            SafeTokenHandle safeTokenHandle;

            const int LOGON32_PROVIDER_DEFAULT = 0;
            //This parameter causes LogonUser to create a primary token. 
            const int LOGON32_LOGON_INTERACTIVE = 2;

            Console.WriteLine("DotNet: Attempting to Logon user: {0}", username);
            // Call LogonUser to obtain a handle to an access token. 
            bool returnValue = LogonUser(username, domain, password,
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                out safeTokenHandle);

            if (returnValue)
            {
                Console.WriteLine("DotNet: Successfully logged on as user: {0}", username);
            }
            else
            {
                Console.WriteLine("DotNet: Failed to create a user");

                int err = Marshal.GetLastWin32Error();
                if (err == 1909 || err == 1331)
                {
                    Console.WriteLine("Logon user failed because account is currently locked/disabled");
                }
                else
                {
                    Console.WriteLine("Logon user failed with error code: {0}", err);
                }

                throw new System.ComponentModel.Win32Exception(err);
            }


            //Console.WriteLine("DotNet: About to create a windows identity");
            //WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
            //Console.WriteLine("New windows identity is: {0}", newId.Name);

            //Console.WriteLine("Attempting to imperonate user: {0}", newId.Name);
            //WindowsImpersonationContext impersonatedUser = newId.Impersonate();
            //Console.WriteLine("DotNet: Impersonation of user: {0} was successful", newId.Name);

            Console.WriteLine("DotNet: Attempting to impersonate the user");
            WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(safeTokenHandle.DangerousGetHandle());
            Console.WriteLine("DotNet: Impersonated the user");

            return impersonatedUser;

        }

        public void Undo(WindowsImpersonationContext impersonatedUser)
        {
            impersonatedUser.Undo();
        }

        public string GetCurrentUser()
        {
            return WindowsIdentity.GetCurrent().Name;

        }

        public string GetCurrentUserNameOnly()
        {
            return this.GetCurrentUser().Split(new char[] { '\\' })[1];

        }  
    }

    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle()
            : base(true)
        {
        }

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }
    }
}

根据 Ben 的建议改为 python:

    def impersonate_user(self, user_name, password, domain):
        handel=win32security.LogonUser(user_name, domain, password, win32con.LOGON32_LOGON_INTERACTIVE,win32con.LOGON32_PROVIDER_DEFAULT)
        win32security.ImpersonateLoggedOnUser(handel)
    print "Hello"

    return True

【问题讨论】:

  • 你为什么使用 Python 中的 C# 只是为了调用 Win32 API?只需从 Python 调用该死的 API。
  • 谁对我的问题投了反对票,我想知道为什么会这样......
  • 您需要获取错误码。尝试捕获异常并查看相关消息。它在调试输出中给出什么错误消息?如果看不到任何调试输出,则需要在 IDE 中显示该窗口。如果你不知道怎么做,你需要给你的 IDE 和工具集命名。

标签: c# .net impersonation windows-identity


【解决方案1】:

您可以直接从 Python 执行此操作,使用 LogonUserImpersonateLoggedOnUserRevertToSelf

只需这样做并删除使事情复杂化的 C#。

起点:

【讨论】:

  • 感谢本的建议和链接。我们最初是在 .net 中做一些事情,这就是为什么我们在那里拥有它,但在您发表评论后,我考虑了更多,并确定将其移至 python 是好的......但是,它仍然默默地失败,现在在 @ 987654326@方法。
  • BOOL ImpersonateLoggedOnUser 返回 false 并在失败时设置线程最后一个错误,您可以通过 GetLastError 进行检查。
  • 嗨 @Ben ImpersoanteLoggedOnUser 没有返回值,但根据我拥有的文档:win32security
  • @dashstar,您能否详细说明“静默失败”。如果它是沉默的,你怎么知道它会失败 - 有什么症状?
  • 因为如果我单步执行代码,它会进入 ImpersonateLoggedOnUser 方法,当我运行它时,它不会执行下一行并退出。我发布了修改后的 python 代码,你会注意到该方法后面的 print 语句(这不会被调用)。
【解决方案2】:

回答迟了,但刚刚遇到这个问题。将LOGON32_LOGON_INTERACTIVE 更改为LOGON32_LOGON_BATCH (4)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 2016-02-23
    相关资源
    最近更新 更多