Remote installing of windows service - c++

I need to remotely install windows service on number of computers, so I use CreateService() and other service functions from winapi. I know admin password and user name for machines that I need access to. In order to gain access to remote machine I impersonate calling process with help of LogonUser like this:
//all variables are initialized correctly
int status = 0;
status = LogonUser(lpwUsername,
lpwDomain,
lpwPassword,
LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_DEFAULT,
&hToken);
if (status == 0)
{
//here comes a error
}
status = ImpersonateLoggedOnUser(hToken);
if (status == 0)
{
//once again a error
}
//ok, now we are impersonated, do all service work there
So, I gain access to machine in a domain, but some of computers are out of domain. On machines that are out of domain this code doesn't work. Is there any way to access service manager on machine out of domain?

You can do it , the account needs to exist on the remote machine and you need to use the machine name for the domain name in the LogonUser call.

Rather than rolling your own, why not just use the SC built-in command?

OK, problem resolved (not really very good, but rather OK). I used WNetAddConnection() to ipc$ on remote machine.

Related

CoRegisterClassObject returns error (session 0?)

A customer is running one of our programs, usually run as a service, as an application. The customer is getting the following error on CoRegisterClassObject():
The class is configured to run as a security id different from the caller.
It looks like some type of session 0 error, but why should CoRegisterClassObject() care about session 0? COM should allow both services (session 0) and apps (session > 0) and not care what registers what, shouldn't it?
Also, I don't like the fact that it's not in the list of errors returnable by CoRegisterClassObject(), as per the Microsoft doc webpage.
The error code in question is CO_E_WRONG_SERVER_IDENTITY (0x80004015).
Per this page:
COM security frequently asked questions
Q6 Why does CoRegisterClassObject return CO_E_WRONG_SERVER_IDENTITY? When launching my ATL 1.1 server service as an .exe file, I receive CO_E_WRONG_SERVER_IDENTITY from CoRegisterClassObject. (The class is configured to run as a security ID different from the caller.) This seems to occur whether I skip the CoInitializeSecurity or not. It fails running as a service or as an .exe file.
A. Many services are debugged by running them as console applications in the interactive user identity. Because the service is already registered to run in a different identity (configurable by the Services control panel applet), OLE fails the CoRegisterClassObject and RunningObjectTable::Register(ROTFLAGS_ALLOWANYCLIENT) calls by returning CO_E_WRONG_SERVER_IDENTITY to enforce security and to prevent malicious servers from spoofing the server. To debug by running in the interactive user's identity, make the following changes in the server's registry entries to prevent these failures:
• To prevent CoRegisterClassObject failure, remove the following named value:
[HKEY_CLASSES_ROOT\APPID\{0bf52b15-8cab-11cf-8572-00aa00c006cf}]
"LocalService"="HelloOleServerService"
• To prevent a IRunningObjectTable::Register(ROTFLAGS_ALLOWANYCLIENT) failure, follow these steps:
Remove the following named value:
[HKEY_CLASSES_ROOT\APPID\{0bf52b15-8cab-11cf-8572-00aa00c006cf}]
"LocalService"="HelloOleServerService"
Then add the following named value:
[HKEY_CLASSES_ROOT\APPID\{0bf52b15-8cab-11cf-8572-00aa00c006cf}]
"RunAs"="Interactive User"
You muist restore the modified registry entries after debugging.
I am assuming you would have to replace {0bf52b15-8cab-11cf-8572-00aa00c006cf} with your COM object's actual CLSID instead.

Verify Active Directory domain trust relationship of the local machine

I have to find out if the local machine is still joined to a domain, or if another computer has used the computer account or, if the computer account has been reset.
In other words, i need to verify the trust relationship between the local machine and the domain
NLTest /SC_VERIFY:{Domain} does the job pretty well.
Are there any API functions that i can use to detect whether the local machine has lost the trust relationship to a domain? I don't like to call external executables from my program.
What i tried so far:
NetGetJoinInformation(): It doesn't realize it.
DsBind*(): It doesn't realize it. Also tried to call it under the local system account.
Any ideas?
Okay. After a lot of digging, i finally found a solution: I_NetLogonControl2
NETLOGON_INFO_2* buffer=NULL;
LPBYTE domainName = (LPBYTE) L"eng";
int ret = I_NetLogonControl2(NULL, NETLOGON_CONTROL_TC_VERIFY, 2, (LPBYTE) &domainName, (LPBYTE*)&buffer);
wprintf( L"I_NetLogonControl2() returned %i\n", ret);
if (ret==0)
{
wprintf( L"PdcConenctionStatus: %i\n", buffer->netlog2_pdc_connection_status);
if (buffer->netlog2_pdc_connection_status==0)
wprintf(L"Trust relationship verified.\n");
else
wprintf(L"Trust relationship FAILED.\n");
wprintf( L"TcConenctionStatus: %i\n", buffer->netlog2_tc_connection_status);
wprintf( L"Flags: %i\n", buffer->netlog2_flags);
}
return 0;
So the magic thing is hidden in NETLOGON_INFO_2::netlog2_pdc_connection_status.If this value is 86 (ERROR_INVALID_PASSWORD) or 5 (ERROR_ACCESS_DENIED) the computer account has been changed (or reset).
If the computer account has been deleted, the value is 1787 (ERROR_NO_TRUST_SAM_ACCOUNT)
Hope this helps others!
Unfortunately, the MSDN documentation is not precise. When you are specifying "NETLOGON_CONTROL_TC_VERIFY", the data argument (LPBYTE) must point to (LPWSTR*)!
you can try LogonUser function to perform network login (LOGON32_LOGON_NETWORK).
If workstation has broken trust with domain, it will not be able to verify your credentials.
You will need some domain credentials which can perform network logon of course, not local.
Your other option is to use local account which has granted network service logon and try to access other domain workstation resource.You can receive access denied error or trust relation failed depends on which resource on which server.
Finally, you can still search system event log for event ID signaling trust failure.
but we don't have any well known accounts that we can use for this
You can not check for workstation account status on domain site (in AD) until you authenticate somehow, just local status.
NetLogon_Control2 is for BDC to PDC communications; does not work for my tests in Win 7
Microsoft page --
Remarks
This function can be used to request that a BDC ensure that its copy of the SAM database is brought up-to-date. It can also be used to determine if a BDC currently has a secure channel open to the PDC.

Application Failed to Initialize Properly (0xc0000142)

I'm trying to launch notepad.exe(as a simpler test) from a web service using process.Start(). This web service is deployed to IIS 5.1 on Windows XP (for development) and will likely be deployed to a Windows 2003 server with IIS 6. This is the code that I am using:
[WebMethod]
public String ReqFormImage(String qString)
{
_qString = qString;
String imageLoc = #"http://localhost/MobileService/formImages/" + NameOfScreenshot(qString);
Process myProcess = new Process();
try
{
//Credentials
myProcess.StartInfo.Domain = "domain";
myProcess.StartInfo.UserName = "myUserName"; //local admin on development pc
myProcess.StartInfo.Password = PasswordGenerate("removed");
//StartInfo
myProcess.StartInfo.WorkingDirectory = #"C:\WINDOWS\System32";
myProcess.StartInfo.FileName = "notepad.exe";
//myProcess.StartInfo.Arguments = qString;
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardError = true;
//myProcess.StartInfo.LoadUserProfile = false;
myProcess.Start();
myProcess.WaitForExit();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return imageLoc;
}
I also have impersonate set to true in the web.config (I've tried with and without my credentials in the config file, as well as with impersonate set to false). I've also given read/execute permission to my user ID, aspnet, and the service account on notepad.exe.
A breakpoint on myProcess.WaitForExit() causes a message box to pop up that says, "Application Failed to Initialize Properly (0xc0000142)." I looked at the event log and there is no further information than this.
What I need in the end is to be able to launch an exe impersonating an account that can be hardcoded or impersonating the user that accesses the web service. I know that there are issues with opening an exe with a GUI server-side, but I need this to work. I'm sure this isn't the best practice, but I am running short on time and am looking for a workaround. For now, at least getting notepad to launch will be sufficient.
Thanks for any help.
In IIS I had to set the web service to run scripts and executables, not just scripts. Notepad launches now, but without a full GUI. I don't think what I need is possible, but I solved what I asked.

manual netlogon

Anyone know how I would do a manual netlogon or any other way to authenticate a user on a remote domain? I need to test authentication.
Right now we're using impersonation and calling an arbitrary function. The problem is that arbitrary winapi function that will login. The problem is that some domains allow that function to be called by null session thus causing false positives.
The only goal of this is to get reliable, fast authentication against a remote domain that the local computer is not added to so I wouldn't deny another approach.
This is the solution that we got from filing a MSDN ticket.
if(!LogonUser(username.c_str(), domain.c_str(), password.c_str(), LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, &token))
{
debug->DebugMessage(Error::GetErrorMessageW(GetLastError()));
CloseHandle(token);
RevertToSelf();
return false;
}
if(!ImpersonateLoggedOnUser(token))
{
debug->DebugMessage(Error::GetErrorMessageW(GetLastError()));
CloseHandle(token);
RevertToSelf();
return false;
}
...
int err = NetUserModalsGet ....
if (err != ERROR_SUCCESS) logged_on = false;
RevertToSelf();
If all you want to do is answer the question "are these credentials valid for a given domain which I may not be a member of?" then you might see some millage in existing things that do this. A number of Linux/UNIX applications offer NTLM authentication against an arbitrary domain without domain membership. Most use winbindd, which I suspect running on a Windows system would be asking for trouble.
Notably though there's an apache module for this, which can run without any external dependencies. You might have some luck looking through their sources, in particular mod_ntlm.c and seeing how they craft the request packets for the domain controller and parse the responses.
Not sure if you've considered the fact that there are many infrastructure configuration concerns associated with using Windows integrated security on remote domains. Are the trust policies appropriately in place? Which SSPI are you using NTLM, Kerberos, PKU2U, DPA, etc?
Have these been appropriately configured for your usage scenario?
Ok... After hearing more about your scenario, have you considered leveraging a custom GINA?
http://msdn.microsoft.com/en-us/library/aa380543(v=VS.85).aspx

Exchange Web Services, try to use ExchangeImpersonationType

I am trying to use EWS, first time trying to use the ExchangeServiceBinding. The code I am using is below:
_service = new ExchangeServiceBinding();
//_service.Credentials = new NetworkCredential(userName, userPassword, this.Domain);
_service.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
_service.Url = this.ServiceURL;
ExchangeImpersonationType ei = new ExchangeImpersonationType();
ConnectingSIDType sid = new ConnectingSIDType();
sid.PrimarySmtpAddress = this.ExchangeAccount;
ei.ConnectingSID = sid;
_service.ExchangeImpersonation = ei;
The application is an aspnet 3.5 trying to create a task using EWS. I have tried to use impersonation because I will not know the logon user's domain password, so I thought impersonation would be the best fit. Any thoughts on how I can utilize impersonation? Am I setting this correctly, I get an error while trying to run my application. I also tried without impersonation just to try to see if I can create a task, no luck either. Any help would be appreciated. Thanks.
Without broader context of your code snip, I can't tell for sure what's wrong, but here are a few things you might find useful...
You mention you had trouble connecting without impersonation.
I'm assuming you are using Exchange Server 2007 SP1, yes?
Do you have a mailbox for which you do know the username and password? If so, consider trying to connect to that mailbox, just to see if you can send an email or query for inbox count. That will help verify your connection at least.
As to exchange impersonation,
have the permissions been set on the Client Access Server (CAS) to enable impersonation?
Have the permissions been set on either the mailbox or mailbox database (containing the mailbox you are attempting to access)?
are you in a cross-forest scenario that requires additional trust relationships?
If not, that might explain why you cannot connect.
Some links you might find useful
Configuring (http://msdn.microsoft.com/en-us/library/bb204095.aspx)
Using Exchange impersonation (http://msdn.microsoft.com/en-us/library/bb204088.aspx)
Access multiple resource mailboxes (http://msexchangeteam.com/archive/2007/12/13/447731.aspx)