【问题标题】:System.Diagnostics.Process.Start a process against a different domainSystem.Diagnostics.Process.Start 针对不同域的进程
【发布时间】:2012-10-13 17:11:13
【问题描述】:

我们有一个场景,我们需要我们的用户能够启动 SQLServer 并使用与当前登录不同的域进行身份验证。因此,为了澄清这种设置方式:

  1. 用户到达办公室并登录到公司域(为简单起见,我们称之为 LOCALDOMAIN)
  2. 他们希望连接到我们在不同域上的远程数据库(我们称之为 REMOTEDOMAIN)
  3. 首先他们启动了 VPN 工具,该工具建立了到 REMOTEDOMAIN 的 VPN 隧道(这一切都经过测试并且效果很好)
  4. 但是如果他们默认启动 SSMS,它将只允许通过 LOCALDOMAIN 进行 Windows 身份验证,甚至无法选择 REMOTEDOMAIN 的选项

我们发现从命令行运行它是可行的:

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

它会提示“输入 REMOTEDOMAIN\AUserName 的密码:”,如果您提供正确的密码,SSMS 将启动并可以连接到远程数据库。但是,当我尝试在 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);

我尝试了带有和不带域的用户名,但都不起作用。有人尝试过做类似的事情吗?谢谢

【问题讨论】:

  • 小心这个。由它打开的 SSMS 实例可能没有本地机器的“用户”所拥有的任何本地权限。包括任何尚未持久化的映射网络驱动器。
  • 添加为评论,因为我不想因错误回答问题而感到愤怒。如果有文件可以恢复,SSMS 将自行关闭。我和你有同样的情况,为我解决的问题是手动打开 SSMS 处理恢复的文件,然后正常进行

标签: c# .net process


【解决方案1】:

我尝试了所有我能找到的各种用户模拟代码示例。他们都没有工作。

最后,我想出了以下代码。它使用/C 参数执行cmd.exe,其中Carries out the command specified by string and then terminates。我执行的命令是runas /netonly ...

注意事项

很遗憾,密码必须手动输入。我的下一步是调查将密钥发送到process。我尝试重定向标准输入并写入它,但它不起作用。我在某处读到,大多数密码提示只接受直接来自键盘的输入。

此外,当 SSMS 打开时,连接到服务器对话框将显示您当前的域\用户名,但它将使用您提供给 runas 的名称进行身份验证。

最后,如果您的 AD 帐户被锁定,在您尝试连接到 SQL Server 之前,您不会收到错误消息。我忘记将收到的错误消息复制下来,但没有提及帐户已被锁定。

代码

    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");
    }

【讨论】:

    【解决方案2】:

    我做了一些可能相关的事情。我登录到一个域并尝试获取另一个域上共享文件夹的目录列表。为此,我使用 LogonUser 和 Impersonate。代码如下所示(抱歉,我没有 SQL 服务器来尝试您的确切方案)...

    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
    }
    

    我已经将它与 Directory.GetDirectories(UNCPath) 一起使用,其中路径通向另一个域上的机器并且它在那里工作。我还没有尝试过实现“runas”。

    我这样称呼它......

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

    也许您可以根据您的问题调整它。 LMK

    【讨论】:

    • 感谢您的回复,我实际上尝试了与此非常相似的方法(我也尝试了您的代码),但无论出于何种原因,它似乎都不适用于我的场景
    • 这给了我:登录失败:未知用户名或密码错误
    【解决方案3】:

    您应该删除以下行:

    // 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";
    

    基本上,您将 /netonly 参数传递给 SMSS,而在命令行上,您正在运行 runas 不是 SMSS。与动词相同,您没有运行runas

    此时对Start 的调用应该会成功,因为您将使用正确的凭据指向正确的可执行文件。

    【讨论】:

    • 我试过了,但我得到了同样的错误,虽然我可以看到你在说什么,但是有很多通过使用 runas 作为动词的提升权限运行 exe 的例子
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多