How to verify a remote DSN entry? - c#

I am creating a verification utility that check various parts of an application to ensure they are configured correctly. One of the things I need to check is that the DSN entry in a Web.config file is a functional DSN, and that the DSN is pointing to the correct SQL server and database.
Currently you can run the utility in one of two modes, local or remote. My problem occurs when I am trying to verify a remote systems DSN on my local computer. I know why it doesnt work, I don't have the same DSN on my local computer. So what I need to figure out is how to either retrieve the DSN connection information from a remote machine to which I have administrative access, or to get the remote machine to verify it for me.
Any suggestions? Thanks!
EDIT
So apparenty the DSN info is stored in the registry too!
oRegConn = new ConnectionOptions();
oRegConn.Username = username;
oRegConn.Password = password;
scope = new ManagementScope(#"//" + servername + #"/root/default", oRegConn);
registry = new ManagementClass(scope, new ManagementPath("StdRegProv"), null);
inParams = registry.GetMethodParameters("GetStringValue");
inParams["sSubKeyName"] = "SOFTWARE\\ODBC\\ODBC.INI\\ODBC Data Sources\\" +
dsnName;
inParams["sValueName"] = "Server";
outParams = registry.InvokeMethod("GetStringValue", inParams, null);
server = outParams["sValue"].ToString();

Well I would say that its not really a valid check if you run it on another system (yours). The firewall rules could be different, the driver versions might be off, and a million more things. The first thing I would say is if this is a web application, build in a page that can run these checks, like a status page. If this is an application that you cant do that, you can use WMI to run a remote process and gather the results. Other than that your last option might be to do a self hosting WCF service or a windows service that you connect to for querying info. This isnt too uncommon, and I have done it many times using WMI.

In that case, you may want to investigate PSExec (by Sysinternals). You can run your utility on a remote machine in "local" mode, as long as you have Administrative access to that machine.
Your "DSN Verification" part would have to be a separate executable/command, which can be executed by your main utility using syntax similar to the following:
psexec \\REMOTE-Machine <DSN Verification Utility>.exe
The output can be captured within C# by redirecting stdout/stderr.
Forgive me if I'm mistaken, but wouldn't just opening a connection to remote database server let you know if your connection string/DSN is okay?

So the DSN conn values are stored in the registry as plaintext, which is what I needed.
oRegConn = new ConnectionOptions();
oRegConn.Username = username;
oRegConn.Password = password;
scope = new ManagementScope(#"//" + servername + #"/root/default", oRegConn);
registry = new ManagementClass(scope, new ManagementPath("StdRegProv"), null);
inParams = registry.GetMethodParameters("GetStringValue");
inParams["sSubKeyName"] = "SOFTWARE\\ODBC\\ODBC.INI\\ODBC Data Sources\\" +
dsnName;
inParams["sValueName"] = "Server";
outParams = registry.InvokeMethod("GetStringValue", inParams, null);
server = outParams["sValue"].ToString();

Related

Access denied when reading / writing to network location as a remote process

I'm currently trying to launch a process on a remote machine using WMI in C#. The process reads and writes to a file that is stored on a separate server.
When I manually login to the remote machine, I can run the process and it all works fine.
However, when I try to launch the process on the remote from my local machine using WMI, I get the following error:
System.UnauthorizedAccessException: Access to the path '\\server\path\input.txt' is denied.
I've tried multiple connection options, but I'm not sure how to re-create the permissions that I seem to have when I login manually... What do I need to do?
Local machine code
static void LaunchRemoteProcess(string remoteMachine, string command)
{
ConnectionOptions connectionOptions = new ConnectionOptions
{
Impersonation = ImpersonationLevel.Impersonate,
EnablePrivileges = true
};
var managementScope = new ManagementScope(string.Format(#"\\{0}\root\cimv2", remoteMachine), connectionOptions);
managementScope.Connect();
var managementPath = new ManagementPath("Win32_Process");
var objectGetOptions = new ObjectGetOptions();
var managementClass = new ManagementClass(managementScope, managementPath, objectGetOptions);
// Launch the command asynchronously
var inParams = managementClass.GetMethodParameters("Create");
inParams["CommandLine"] = command;
var outParams = managementClass.InvokeMethod("Create", inParams, null);
}
Remote machine code
string networkPath = #"\\server\path";
string inputFile = "input.txt";
string inputText = File.ReadAllText(Path.Combine(networkPath, inputFile));
string outputFile = "output.txt";
File.WriteAllText(Path.Combine(networkPath, outputFile), inputText);
Edit 1
I have already tried using the credentials of the user for which the process works if I log on to the remote machine manually and the process still fails with the same error:
ConnectionOptions connectionOptions = new ConnectionOptions
{
Username = "username",
Password = "password",
Authority = "ntlmdomain:COMPANYNAME.CO.UK,
EnablePrivileges = true
};
Am I missing something with regards to the Authority, Authentication, or Impersonation attributes?
Impersonation vs Delegation
Your WMI code uses impersonation, so the server side runs in the security context of the user who calls the code on the client. But this is only valid on the server itself, not for accessing e.g. a remote CIFS share (as in your case).
You have to use delegation.
First, change
Impersonation = ImpersonationLevel.Impersonate,
to
Impersonation = ImpersonationLevel.Delegate,
If you get an exception then, delegation does not yet work in your environment.
Check:
Calling user account: "Account is sensitive and cannot be delegated" must not be checked in the user properties (Active Directory Users and Computers)
server machine account: "Trust this computer for delegation to any service..." must be checked
local security policy on the server: "Enable computer and user accounts to be trusted for delegation" must include the calling user.
See
https://msdn.microsoft.com/en-us/library/aa389288%28VS.85%29.aspx
for further information on this topic.
Added: (see the comments below):
If Delegate is not an option in your environment (e.g. group policies do not allow for this, and you do not have the rights to change them), you may check some alternative ways.
You probably heard of psexec.
Or, what I did some years ago, and which runs in production in a enterprise environment on a few servers for many years very successfull:
I created a scheduled task which starts a program and set the technical user + password for this task. The task was configured for "run once in year 2200 :-)".
Then I wrote commands in a queue (I used a simple command file) and started the task from a remote machine.
Doing it this way, delegation is not required, since the scheduled task itself logs on as the technical user account ("logon as batch" privs are required).
As the reason states, the user id you are using on your PC does not seem to have access for to another computer's location (though it is a server, it is some other computer).
You may get access for your user id or use Impersonation to use an user id that already has access to the location.
Find more details here: https://msdn.microsoft.com/en-us/library/w070t6ka%28v=vs.110%29.aspx
Edited: Add user name password too. That may help.

How to execute debug view on remote computer using wmi

I am looking to run Debugview on a remote machine (I have the username,password and the ip adress of that machine). I have developed this code
object[] theProcessToRun = { "C:\\Dbgview.exe /t /l C:\\debugview1.log" };
ConnectionOptions theConnection = new ConnectionOptions();
theConnection.Username = "Username";
theConnection.Password = "Password";
ManagementScope theScope = new ManagementScope("\\\\ipaddress\\root\\cimv2", theConnection);
ManagementClass theClass = new ManagementClass(theScope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
theClass.InvokeMethod("Create", theProcessToRun);
This code starts the debugview on the remote computer in background(which can be viewed in taskmanager by selecting processes run by all users option) but the problem is, it does not connect the localhost.
so can anyone suggest me the changes or any other way to achieve what i am doing.
EDIT : GOT THE ANSWER
You need to have administrative rights to logon the remote computer so debug view gets connected automatically (to local host)

Trying to remotely access through wmi using C#

I have this piece of code:
private ManagementScope CreateNewManagementScope(string server)
{
string serverString = "\\\\" + server + "\\root\\cimv2";
ConnectionOptions options = new ConnectionOptions();
options.Username = "name";
options.Password = "password";
ManagementScope scope = new ManagementScope(serverString, options);
scope.Connect();
return scope;
}
With that code I am trying to remotely access another PC though WMI. The password and the username are 100% correct (I tested them with wmic /node:pc /username:name /password:pwd and this worked) but I am getting access denied
(Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
Any Ideas what I am doing wrong? I am working with Win 7/C#/.NET 4.0
Thanks for any Help!
you can try with admin credential :
string serverString = #"\\" + strIPAddress + #"\root\cimv2"
Check what is logged on the other machines Security eventlog since it will provide you with a clue on what's wrong with access permissions.
I'm quite sure that you can solve the issue after checking the TechNet article "Connecting to WMI Remotely Starting with Windows Vista" and the related one. Specifically this part:
"Setting DCOM Security to Allow a User to Access a Computer Remotely".
Check the code of Services+ (Advanced Windows Service Manager) contains all what you need about WMI Win32_Service.
To Troubleshoot or debug:
Make sure the computer and server are on the same domain
Remove your code credential and make an EXE form your code then Run
the EXE as privileged user.
Use Services+ (mentioned above) or Services.msc to connect to the
server.
Make sure RPC service is running on Remote Server.
Try to trun off the firewall temporary on the server.

How to RDP into a Terminal Server THEN access Active Directory on an internal-only DC

I have a dev network setup modeled after a production setup at work, and I've been able to successfully query Active Directory when I'm in the same subnet and can resolve the server. Now, I'm trying to set this up where I am required to remote into a terminal server, which is the only internet accessible server, and use that connection to gain access to an internal-only domain controller where I can then run my queries (all in C#). Maybe a better way of explaining this would be I'm trying to turn this RDP connection into a network bridge of sorts, where I can use the internal address of the DC (such as 192.168.1.1) from across the internet when I create my LDAP path.
Is RDP the right thing to use? I found this off of the code project, but it appears to be for setting up a remote desktop as opposed to allowing me access to the internal DC:
// RDP test
rdp.Server = "firewall";
rdp.UserName = "Administrator";
IMsTscNonScriptable secured = (IMsTscNonScriptable)rdp.GetOcx();
secured.ClearTextPassword = "mypassword";
rdp.Connect();
string moo2 = rdp.UserName;
string moo = rdp.ProductName;
rdp.Disconnect();
My dev TS is called "firewall", and from there I want to be able to execute the code below against the DC:
// Fire up the directory
DirectoryEntry ADRoot = new DirectoryEntry();
ADRoot.Username = "myusername";
ADRoot.Password = "mypassword";
ADRoot.Path = "LDAP://192.168.1.11";
// Search for all the computer objects
DirectorySearcher searcher = new DirectorySearcher();
searcher.Filter = "(&ObjectCategory=computer)";
searcher.SearchRoot = ADRoot;
SearchResultCollection results = searcher.FindAll();
I'm all for just about any approach that will let me hit this internal DC from over the internet.
After much google research, it looks like the best approach will require a VPN connection. Once I have an established VPN connection (doesn't matter where or what server in the network lets me in), I can then use the LDAP protocol.
Yes VPN basically extends the network to your machine as well. in some cases for security reasons you wont get this access. RDP is only a screen on a machine running there and does not fit your needs.

How to programmatically connect to IIS 7

I am trying to connect to IIS programmatically. I find there are a ton of examples online, but I can't seem to get any to work and have tried quite a few variations
Every time I try the following code the object that is returned has this error for each property: ..."threw an exception of type 'System.Runtime.InteropServices.COMException'"
using System.DirectoryServices;
String serverName = "serverName";
DirectoryEntry IIS = new DirectoryEntry("IIS://" + serverName + "/W3SVC");
IIS = new DirectoryEntry("IIS://" + serverName + "/W3SVC", "administrator", "mypassword");
IIS = new DirectoryEntry("IIS://" + serverName + "/W3SVC/1/ROOT", "administrator", "mypassword");
I am using Windows Directory user accounts and I have a bunch of sites running on IIS. I am trying this code on a windows xp development machine trying to connect to a windows 2008 Server with IIS 7. Anyone know what I am doing wrong?
Your account may not have launch permissions on the COM object wrapping the IIS calls. You may need to try adding yourself to the admin group on the box hosting IIS to get this to work.
Make sure you have the IIS6 management compatibility feature installed on the target server- you can't do remote management via ADSI on IIS7 without it.
Make sure that IIS is installed on your client machine - your program will throw a System.Runtime.InteropServices.COMException if it isn't installed.
This counts when you are looking at IIS on a remote machine too, the machine running your app will need IIS too.
EDIT: Also, I've recently discovered an assembly specifically for connecting to and configuring IIS7 - Microsoft.Web.Administration. Might be worth looking at whether you have access to this (or can get access, it should be on the machine with IIS7 in any case) and see what it can do. I'm afraid I've not used it myself, so I can't tell you if it'll do what you want, but it's another option to look into.
Finally, there's the option of System.Management and WMI scripts.
Dim scope As New Management.ManagementScope("\\" & server & "\root\MicrosoftIISv2")
scope.Connect()
Dim query As New Management.ObjectQuery("select * from IISWebVirtualDirSetting")
Dim searcher As New Management.ManagementObjectSearcher(scope, query)
For Each obj As Management.ManagementObject In searcher.Get()
DoSomethingWith(obj)
Next
The list of properties on obj is at http://msdn.microsoft.com/en-us/library/ms525005.aspx, there's also some more different queries you can run - just dig around on MSDN for more.

Categories