简体   繁体   English

System.Diagnostics.Process。针对另一个域启动进程

[英]System.Diagnostics.Process.Start a process against a different domain

We have a scenario where we need our users to be able to launch SQLServer and authenticate into it using a different domain than they are currently logged into. 我们有一种情况,我们需要用户能够使用与当前登录的域不同的域来启动SQLServer并对其进行身份验证。 So to clarify the way this is setup: 因此,要澄清设置方法:

  1. User arrives at the office and logs in to the corporate domain (lets call it LOCALDOMAIN for simplicity) 用户到达办公室并登录到公司域(为简单起见,将其称为LOCALDOMAIN)
  2. They wish to connect to our remote database on a different domain (lets call it REMOTEDOMAIN) 他们希望连接到另一个域上的远程数据库(我们称其为REMOTEDOMAIN)
  3. First they launch the VPN tool which establishes the VPN tunnel to REMOTEDOMAIN (this is all tested and works great) 首先,他们启动了VPN工具,该工具建立了到REMOTEDOMAIN的VPN隧道(这已经过测试并且运行良好)
  4. But if they launch SSMS by default it will only allow Windows Auth via LOCALDOMAIN, the option to select REMOTEDOMAIN is not even available 但是,如果他们默认启动SSMS,它将仅允许通过LOCALDOMAIN进行Windows身份验证,因此选择REMOTEDOMAIN的选项甚至不可用

What we discovered is that running this from the command line will work: 我们发现,可以从命令行运行此命令:

RUNAS /user:REMOTEDOMAIN\AUserName /netonly "C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\Ssms.exe

it will prompt with the message "Enter the password for REMOTEDOMAIN\\AUserName:" and if you supply the correct password, SSMS will be launched and can connect to the remote dbs. 它将提示消息“输入REMOTEDOMAIN \\ AUserName的密码:”,如果提供正确的密码,SSMS将启动并可以连接到远程数据库。 However, when I try to do the same thing in C# with a nicer interface around it, I get "Logon failure: unknown user name or bad password", here is my code: 但是,当我尝试使用更好的接口在C#中执行相同的操作时,出现“登录失败:未知的用户名或错误的密码”,这是我的代码:

System.Security.SecureString password = new System.Security.SecureString();
foreach(char c in txtPassword.Text.ToCharArray()){
    password.AppendChar(c);
}
System.Diagnostics.ProcessStartInfo procInfo = new System.Diagnostics.ProcessStartInfo();
procInfo.Arguments = "/netonly";
procInfo.FileName = @"C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\Ssms.exe"; ;
procInfo.Domain = "REMOTEDOMAIN";
procInfo.Verb = "runas";
procInfo.UserName = txtUsername.Text;
procInfo.Password = password;
procInfo.UseShellExecute = false;
System.Diagnostics.Process.Start(procInfo);

I tried the username with and without the domain pre-pended but neither works. 我尝试使用带或不带域名的用户名,但都无法使用。 Anyone ever tried to do something similar? 是否有人尝试做类似的事情? thanks 谢谢

You should remove the following lines: 您应该删除以下几行:

// Not passing /netonly to SMSS, it was passed to RunAs originally.
procInfo.Arguments = "/netonly";
// Again, SMSS is not getting the verb, it's being run
procInfo.Verb = "runas";

Basically, you're passing the /netonly parameter to SMSS, whereas on the command line, you're running runas not SMSS . 基本上,您将/netonly参数传递给SMSS,而在命令行上,您正在运行runas 而不是SMSS Same with the verb, you're not running runas . 与动词相同,您没有运行runas

The call to Start should succeed at that point, as you'll be pointing to the correct executable with the correct credentials. 此时,对Start的调用应该会成功,因为您将指向具有正确凭据的正确可执行文件。

I've done something that may be related. 我做了一些可能相关的事情。 I login to one domain and try to get a directory listing of a shared folder on a different domain. 我登录到一个域,并尝试获取另一域上共享文件夹的目录列表。 To do this, I use LogonUser and Impersonate. 为此,我使用LogonUser和Impersonate。 The code looks like the following (sorry, I don't have an SQL server to try your exact scenario)... 该代码如下所示(抱歉,我没有SQL Server来尝试您的确切方案)...

public class Login : IDisposable
{
    public Login(string userName, string domainName)
    {
        _userName = userName;
        _domainName = domainName;
    }

    string _userName = null;
    string _domainName = null;

    IntPtr tokenHandle = new IntPtr(0);
    IntPtr dupeTokenHandle = new IntPtr(0);
    WindowsImpersonationContext impersonatedUser = null;

    const int LOGON32_PROVIDER_DEFAULT = 0;
    const int LOGON32_LOGON_INTERACTIVE = 2;
    const int LOGON32_LOGON_NEW_CREDENTIALS = 9;

    [DllImport("advapi32.dll", SetLastError = true, EntryPoint = "LogonUser")]
    public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
        int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

    [DllImport("advapi32.dll", SetLastError = true, EntryPoint = "LogonUser")]
    public static extern bool LogonUserPrompt(String lpszUsername, String lpszDomain, IntPtr lpszPassword,
        int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

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

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
        int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

    public void AccessShare(string password)
    {
        tokenHandle = IntPtr.Zero;

        bool returnValue = LogonUser(_userName, _domainName, password,
            LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT,
            ref tokenHandle);

        if (false == returnValue)
        {
            int ret = Marshal.GetLastWin32Error();
            throw new System.ComponentModel.Win32Exception(ret);
        }

        // Use the token handle returned by LogonUser.
        WindowsIdentity newId = new WindowsIdentity(tokenHandle);
        impersonatedUser = newId.Impersonate();
    }

#region IDisposable Members
    public void  Dispose()
    {
        impersonatedUser.Undo();

        // Free the tokens.
        if (tokenHandle != IntPtr.Zero)
            CloseHandle(tokenHandle);
    }
#endregion
}

I've used this with Directory.GetDirectories(UNCPath) where the path leads to a machine on another domain and it works there. 我已经将它与Directory.GetDirectories(UNCPath)一起使用,其中该路径通向另一个域上的计算机,并且在那里可以正常工作。 I have not yet tried it for implementing a "runas". 我尚未尝试实现“ runas”。

I call it like so... 我这样称呼它...

using(var login = new Login("myname","mydomain))
{
    login.AccessShare("mypassword");
    // do stuff
}

Maybe you can adapt it to your problem. 也许您可以使其适应您的问题。 LMK LMK

I tried all the various user impersonation code samples I could find. 我尝试了所有可以找到的各种用户模拟代码示例。 None of them worked. 他们都没有工作。

Finally, I came up with the following code. 最后,我想出了以下代码。 It executes cmd.exe with the /C argument, which Carries out the command specified by string and then terminates . 它使用/C参数执行cmd.exe ,该参数Carries out the command specified by string and then terminates The command that I execute is runas /netonly ... 我执行的命令是runas /netonly ...

Caveats 注意事项

Unfortunately, the password has to be typed manually. 不幸的是,必须手动输入密码。 My next step is to investigate sending key stokes to the process . 我的下一步是研究向process发送关键笔画。 I tried redirecting standard input and writing to it, but it didn't work. 我尝试重定向标准输入并将其写入,但是没有用。 I read somewhere on SO that most password prompts only accept input directly from the keyboard. 我在某处读到,大多数密码提示仅接受直接来自键盘的输入。

Also, when SSMS opens, the Connect to Server dialog will show your current domain\\username, but it will authenticate using the one you gave to runas . 同样,当SSMS打开时,“ 连接到服务器”对话框将显示您当前的域\\用户名,但它将使用您给runas提供的身份进行身份验证。

Finally, if your AD account is locked, you won't get an error until you try to connect to SQL Server. 最后,如果您的AD帐户已锁定,则在尝试连接到SQL Server之前不会收到错误消息。 I neglected to copy down the error message that I received, but it did not mention the account was locked. 我忽略了复制收到的错误消息,但没有提及该帐户已被锁定。

Code

    public static void RunAsNetonly(string username, string domain, string exePath)
    {

        var psi = new ProcessStartInfo();

        psi.FileName = "cmd.exe";
        psi.Arguments = $"/C runas /netonly /user:{domain}\\{username} \"{exePath}\"";            
        psi.UseShellExecute = false;

        var process = Process.Start(psi);

        // not sure if this is required
        process.WaitForExit();

    }        

    // usage example
    public static void RunSSMS()
    {
        RunAsNetonly("walter", "domain123", @"C:\Program Files (x86)\Microsoft SQL Server\140\Tools\Binn\ManagementStudio\ssms.exe");
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM