Detecting registered & running service without administrator rights - winapi

I have a desktop application should behave differently depending on if an optional service is running. I was using the service control manager to check if the service was registered, and if so, whether or not it was running. This worked well until I realized that this seems to require the desktop application to run as administrator.
What would be the best way of checking these conditions (registered and running) in my desktop application, without requiring administrative rights?

You do not need admin rights to query the SCM for service information.
Call OpenSCManager() requesting SC_MANAGER_CONNECT access, then call OpenService() requesting SERVICE_QUERY_STATUS access. That will tell you if the service is installed or not. If so, then call QueryServiceStatus() to find out if it is running or not.

As I'm more familiar with the C# side, I'm not sure if there's a formal API for doing this in C++ that doesn't require some form of elevated privileges. That said, a couple of alternatives come to mind.
You could have your service open a server socket and listen on the localhost address (127.0.0.1) on a specific port. When your application starts running, it would connect to this address. If the connection succeeded, your service is running.
Another option would be to have your service create a named, system-level mutex when it starts running and close it when the service closes. Your application could check to see if the mutex exists. If it does, your service is running.
HTH

Related

Start up or register a Windows Service without having to enter user credentials during start up or installation

We have written a Windows Service that is planned to be deployed to many or all client windows machines in a company. For technical reasons this service has to be run under the logged in user (i.e. not under LocalSystem or any Service Account).
Furthermore it's a requirement that our software has to be deployed using an installer that requires no user interaction (e.g. silent mode is fully supported).
We now face the problem that we are unable to install our service without having the user to provide it's credentials.
My question now is:
Is it possible somehow either during the installation process or in a start up script of the end user to have a service registered or started up without having to enter the users credentials?
If that is not possible (which I assume): Is it possible to start a process as a regular process and
have it register itself as a service at startup, so it appears in the Services panel?
Any help or idea is appreciated.

Installing services as different users

I was installing the filebeat application and I noticed that I needed to run powershell as administrator in order to install them. When I checked the service using wmic service get name,startname,status it showed Local System. I'm wondering what this account is as this is neither the user account or the administrator account. Will this always be the case when I install services as administrator? What is the difference if I install it as a normal user and as administrator?
In any case, I've set this service to start automatically when windows start. Would this service start only when the user I used to install it logs in or will it start regardless of which user logs in?
OK, let's unpack that one by one, in no particular order:
Only a user with administrator rights can install a service.
Services that are configured to start automatically are started as soon as Windows is up and running; Windows does not wait until somebody logs in. It makes no difference to the service who the logged-on user is, or whether anybody is logged in at all, unless the service application itself has been explicitly programmed to check.
The program that installs the service decides what account the service uses to run. Windows doesn't care what user account was used to install the service, it doesn't even keep track.
If the program that installs the service wants it to use an ordinary user account, it must know the password for that account. There are various special accounts that a service can run in, these accounts do not require a password. One of these special accounts is Local System.
Local System is the highest-privilege service account in Windows; it has all the same rights as an administrator, and can do things an administrator can't. Local System is also the account that the user-mode part of Windows itself runs in, roughly equivalent to the UNIX root account except that it doesn't have a password.
Additional notes, for completeness:
One alternative to Local System is for the service to run as Local Service or as Network Service, which are non-administrative service accounts. The only difference between the two is that if the computer is joined to an Active Directory domain, the Network Service account has network access to other machines in the domain and the Local Service account does not.
It is also possible to configure a service to run in a special service account that is unique to that particular service. This is mostly useful if you want the service to have access to a particular file or folder, but do not want to give it administrator rights.
Nitpickers corner:
It is I believe technically possible to reconfigure Windows to allow non-administrators to install services, but this is not supported and would be a Very Bad Idea. If you did, though, it would still make no difference who installed the service. Windows doesn't record this information.

WNetGetConnection and run as admin

I need to call WNetGetConnection to get the UNC path and it works good when application run as standard user but it returns 1201(ERROR_CONNECTION_UNAVAIL) error code when application run as admin. According to the documentation its working as expected.
If the network connection was made using the Microsoft LAN Manager
network, and the calling application is running in a different logon
session than the application that made the connection, a call to the
WNetGetConnection function for the associated local device will fail.
The function fails with ERROR_NOT_CONNECTED or
ERROR_CONNECTION_UNAVAIL. This is because a connection made using
Microsoft LAN Manager is visible only to applications running in the
same logon session as the application that made the connection. (To
prevent the call to WNetGetConnection from failing it is not
sufficient for the application to be running in the user account that
created the connection.)
that means its not possible at all to get the UNC path from the app running as admin ? Is there some other way ?
This is by design. Network shares created by a non-elevated account are not visible under elevation, and vice versa.
See this question on Super User for discussion of the issue. There is apparently a registry setting that enables mapped drives to be shared between elevated and non-elevated accounts but I've never tried it myself.
Network connections cannot normally be shared across different Windows login sessions. This is regardless of admin account / elevation level. Each Windows login or impersonation session needs to create its own network connections.

Debugging Topshelf service that won't run under restrictive account

I have a Windows service written using Topshelf. I'm trying to configure it to run using a Windows account with restricted privileges rather than using LocalSystem. That's also necessary as I'd like to connect to a database using integrated authentication.
The service works when run as LocalSystem (albeit with a database connection string containing credentials) and running the console application as my limited account (using runas) also works.
However, when I try to start the service the service control manager times out waiting for a response:
The service did not respond to the start or control request in a timely fashion.
I also get the following in the Application Popup event log:
Application Error : The exception unknown software exception (0xc06d007e) occurred in the application at location 0x77e4bef7.
The first thing that the application does is writes to a log file but it doesn't reach that when I start the service. The logging works if I run via the console.
Any suggestions what I might be missing or what I might try next?
This problem seems to be related to the server (a domain controller) rather than TopShelf. A service built with the .NET service component also exhibits the same behaviour.
The service runs successfully on a different machine (in the same domain).
Unfortunately this doesn't help diagnose the problem but gives me an acceptable workaround.
Check the MSDN article Debugging windows services which describes how you debug windows services.
I've just started seeing this on a few of my services written in .net 2.0. They'll start fine when the server boots, but if I were to restart them throughout the day, they would not start, and give this error message.
They currently ran under a domain account which has admin rights on the box, but for kicks, I switched it to Local System, and the service started normally. I stopped it, changed it back to the domain account (reentering the password), and it started normally again as expected.
Don't know if this counts as a 'fix' so much, but that's what worked for me.

Restarting windows service from website

I've a website that puts info into a mySQL database and a windows service (written in VB.Net) that polls the db and actions what's in there.
However, occasionally it stalls and rather than having to RDP into the server, I want superusers to click on a button to restart the service.
I can get the button to say, do a directory listing of c:\ output to a test file so the whole 'getting a command to execute on a remote server' issue works. However, I can't restart services.
I assume this is a security thing (although it has full rights to c:\ I thought I'd sussed that already).
The website runs under the normal IUSR_user so am I doing something really stupid or can someone explain how to get the service to be restarted ?
Many thanks
Adrian
I think a significantly bigger problem is that you have a service that's stalling. Do you have any logs or errors that the service outputs to that you could use to diagnose why it's stalling?
I'd write a service that restarts selected services and call that from my website, just for fun!
It seems that you need to give the user permissions on the specific service. The simplest way to do this (in my view) is to use subinacl.exe from the Windows Resource Kit.
subinacl.exe /service MySQL /Grant=IUSR_user
I'm would be very careful when doing this on a public-facing web server. Have both authentication and rate limiting on the restarting code.
Use the ServiceController class:
http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicecontroller.aspx
This should allow you to connect to the named service and stop/start it.
EDIT:
In addition, you probably need to have your web app impersonate a user with rights to restart the service. This can be accomplished via an identity impersonate in the web.config, or running the web app in a configured application pool in IIS. Keep in mind that the web app will have to run on the same box as the service is running on.

Resources