在其他用户

时间:2015-10-17 18:08:06

标签: c# ssl-certificate remote-desktop pfx

以下代码可以很好地在当前用户上安装pfx。 我想通过提供用户名和密码(无需使用该用户登录)将其安装在其他用户上。 我不久前用批处理文件做了这个,我怎么能用C#做到这一点?

我尝试了一些事情,包括模仿,但无法使其发挥作用。

X509Certificate2 certificate = new X509Certificate2("C:\\teste\\cert.pfx", "password");
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
store.Add(certificate);
store.Close();

更新

感谢Bill的代码,只要用户登录,该过程就可以正常运行。 注销后,尝试安装pfx时会抛出异常。 “系统找不到指定的文件”。 如果用户重新登录,它会再次运行!!

这段代码非常有用,但如果用户离线时它也能正常工作,那么这项工作就非常适合! 有办法吗?

提前致谢!

// obtains user token
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
    int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

// closes open handes returned by LogonUser
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);

public void DoWorkUnderImpersonation() {
    //elevate privileges before doing file copy to handle domain security
    WindowsImpersonationContext impersonationContext = null;
    IntPtr userHandle = IntPtr.Zero;
    const int LOGON32_PROVIDER_DEFAULT = 0;
    const int LOGON32_LOGON_INTERACTIVE = 2;
    string domain = ConfigurationManager.AppSettings["ImpersonationDomain"];
    string user = ConfigurationManager.AppSettings["ImpersonationUser"];
    string password = ConfigurationManager.AppSettings["ImpersonationPassword"];

    try {
        Console.WriteLine("windows identify before impersonation: " + WindowsIdentity.GetCurrent().Name);

        // if domain name was blank, assume local machine
        if (domain == "")
            domain = System.Environment.MachineName;

        // Call LogonUser to get a token for the user
        bool loggedOn = LogonUser(user,
                                    domain,
                                    password,
                                    LOGON32_LOGON_INTERACTIVE,
                                    LOGON32_PROVIDER_DEFAULT,
                                    ref userHandle);

        if (!loggedOn) {
            Console.WriteLine("Exception impersonating user, error code: " + Marshal.GetLastWin32Error());
            return;
        }

        // Begin impersonating the user
        impersonationContext = WindowsIdentity.Impersonate(userHandle);

        Console.WriteLine("Main() windows identify after impersonation: " + WindowsIdentity.GetCurrent().Name);

        //run the program with elevated privileges (like file copying from a domain server)
        DoWork();

    } catch (Exception ex) {
        Console.WriteLine("Exception impersonating user: " + ex.Message);
    } finally {
        // Clean up
        if (impersonationContext != null) {
            impersonationContext.Undo();
        }

        if (userHandle != IntPtr.Zero) {
            CloseHandle(userHandle);
        }
    }
}


private void DoWork() {
    //everything in here has elevated privileges
    X509Certificate2 certificate = new X509Certificate2("C:\\teste\\cert.pfx", "password");
    X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadWrite);
    store.Add(certificate);
    store.Close();
}

1 个答案:

答案 0 :(得分:1)

你是怎么做模仿的?我之前成功地使用过这个答案中的模拟片段: How to use LogonUser properly to impersonate domain user from workgroup client

我使用它的方式是将它包装在DLL中并从powershell调用它。它可以用于访问该用户的证书存储,从而允许StoreLocation.CurrentUser完成它的工作。

要将此应用于您的情况,您可以尝试:

// obtains user token
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
    int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

// closes open handes returned by LogonUser
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);

public void DoWorkUnderImpersonation() {
    //elevate privileges before doing file copy to handle domain security
    WindowsImpersonationContext impersonationContext = null;
    IntPtr userHandle = IntPtr.Zero;
    const int LOGON32_PROVIDER_DEFAULT = 0;
    const int LOGON32_LOGON_INTERACTIVE = 2;
    string domain = ConfigurationManager.AppSettings["ImpersonationDomain"];
    string user = ConfigurationManager.AppSettings["ImpersonationUser"];
    string password = ConfigurationManager.AppSettings["ImpersonationPassword"];

    try {
        Console.WriteLine("windows identify before impersonation: " + WindowsIdentity.GetCurrent().Name);

        // if domain name was blank, assume local machine
        if (domain == "")
            domain = System.Environment.MachineName;

        // Call LogonUser to get a token for the user
        bool loggedOn = LogonUser(user,
                                    domain,
                                    password,
                                    LOGON32_LOGON_INTERACTIVE,
                                    LOGON32_PROVIDER_DEFAULT,
                                    ref userHandle);

        if (!loggedOn) {
            Console.WriteLine("Exception impersonating user, error code: " + Marshal.GetLastWin32Error());
            return;
        }

        // Begin impersonating the user
        impersonationContext = WindowsIdentity.Impersonate(userHandle);

        Console.WriteLine("Main() windows identify after impersonation: " + WindowsIdentity.GetCurrent().Name);

        //run the program with elevated privileges (like file copying from a domain server)
        DoWork();

    } catch (Exception ex) {
        Console.WriteLine("Exception impersonating user: " + ex.Message);
    } finally {
        // Clean up
        if (impersonationContext != null) {
            impersonationContext.Undo();
        }

        if (userHandle != IntPtr.Zero) {
            CloseHandle(userHandle);
        }
    }
}


private void DoWork() {
    //everything in here has elevated privileges
    X509Certificate2 certificate = new X509Certificate2("C:\\teste\\cert.pfx", "password");
    X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadWrite);
    store.Add(certificate);
    store.Close();
}