System.Diagnostics.Process. Start a process in another domain

We have a scenario in which we need our users to be able to run SQLServer and authenticate in it using a different domain than they are currently logged into. Therefore, to clarify the configuration method:

  • The user comes to the office and logs in to the corporate domain (for simplicity, calls it LOCALDOMAIN)
  • They want to connect to our remote database in another domain (let's call it REMOTEDOMAIN)
  • First, they launch the VPN tool, which sets up the VPN tunnel in REMOTEDOMAIN (all of this is verified and works fine).
  • But if they start SSMS by default, it will allow Windows Auth through LOCALDOMAIN, the option to select REMOTEDOMAIN is not even available

We found that doing 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 

the message "Enter the password for REMOTEDOMAIN \ AUserName:" appears, and if you specify the correct password, SSMS will start and will be able to connect to the remote dbs. However, when I try to do the same in C # with a more convenient interface, I get "Login error: unknown username or invalid password", here is my code:

 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 a username with and without a domain, but it doesn’t work. Has anyone ever tried to do something like this? thanks

+4
source share
2 answers

You must delete 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 being run procInfo.Verb = "runas"; 

Basically, you pass the /netonly to SMSS, while on the command line you run runas not SMSS. Same thing with the verb, you are not using runas .

The Start call should succeed at this point, since you are pointing to the correct executable with the correct credentials.

0
source

I did something that could be related. I enter one domain and try to get a list of directories of a shared folder in another domain. For this, I use LogonUser and Impersonate. The code is as follows (sorry, I do not have a SQL server to try your exact script) ...

 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 used this with Directory.GetDirectories (UNCPath), where the path leads to a machine in another domain, and it works there. I have not tried it to implement "runas" yet.

I call it that ...

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

Perhaps you can adapt it to your problem. LMK

0
source

Source: https://habr.com/ru/post/1441612/


All Articles