2

Is there a way in C# to determine if I am authorized to start and stop windows services?

If my process is running under the NETWORK SERVICE account and I attempt to stop a service I will get a "Access denied" exception, which is fine, but I would like to be able to determine if I am authorized before attempting the operation.

I am trying to improve code that looks like this:

var service = new ServiceController("My Service");
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));

to something like:

if (AmIAuthorizedToStopWindowsService())
{
    var service = new ServiceController("My Service");
    service.Stop();
    service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
}

UPDATE What about something like this:

private bool AutorizedToStopWindowsService()
{
    try
    {
        // Try to find one of the well-known services
        var wellKnownServices = new[]
        { 
            "msiserver",    // Windows Installer
            "W32Time"       // Windows Time
        };
        var services = ServiceController.GetServices();
        var service = services.FirstOrDefault(s => s.ServiceName.In(wellKnownServices) && s.Status.In(new[] { ServiceControllerStatus.Running, ServiceControllerStatus.Stopped }));

        // If we didn't find any of the well-known services, we'll assume the user is not autorized to stop/start services
        if (service == null) return false;

        // Get the current state of the service
        var currentState = service.Status;

        // Start or stop the service and then set it back to the original status
        if (currentState == ServiceControllerStatus.Running)
        {
            service.Stop();
            service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(5));
            service.Start();
            service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(5));
        }
        else
        {
            service.Start();
            service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(5));
            service.Stop();
            service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(5));
        }

        // If we get this far, it means that we successfully stopped and started a windows service
        return true;
    }
    catch
    {
        // An error occurred. We'll assume it's due to the fact the user is not authorized to start and stop services
        return false;
    }
}
desautelsj
  • 3,587
  • 4
  • 37
  • 55
  • 4
    I think you could do some basic permissions checks, such as finding out if your process is running as an Administrator; but that's not always definitive. I think the only thing you can do that will be 100% accurate is attempt to stop the service and trap the exception if you don't have the proper permissions. – CodingGorilla Aug 30 '13 at 19:01
  • @CodingGorilla Yup. I doubt that there is a way to "lock" the OS to prevent permission changes between a test to see if an account can stop a service, and actually stopping the service. – Keith Payne Aug 30 '13 at 19:05
  • 1
    I found a "IsAdministrator" method in this article http://stackoverflow.com/questions/3892088/servicecontroller-permissions-in-windows-7 which returns a Boolean indicating if a user is member of the local admin role but that's probably overkill – desautelsj Aug 30 '13 at 19:07
  • Generally you need to be an admin to control a service, so checking for local admin rights should be effective. – JNYRanger Aug 30 '13 at 19:16
  • What about stopping and restarting the "Windows Time" service (or any other well-known service)? If it succeeds we assume the current user is authorized, otherwise we assume he is not. Is that a good idea? Is there one 'well-known' service that we can assume will be present on most system? – desautelsj Aug 30 '13 at 22:09
  • @desautelsj: Windows time setting is a specific privilege (`SE_SYSTEMTIME_NAME`). It can be enabled or disabled separately, and on Vista and above is only included by default to administrators. Trying to stop and start a "well known service" to determine privileges won't be any different than trying to start your own. – Ken White Aug 30 '13 at 22:56

2 Answers2

1

Not really. You can try to reason if your account could have permissions (like member of Admins or domain admins groups) which may be enough for your case.

Permissions in Windows can be set on very granular objects/operations, so any particular membership does not necessary guarantee that your account have permissions for particular operation on particular object even if it has permissions for similar/same operation on other objects.

The way to handle is to try operation and handle exceptions.

If you are nice - provide detailed instructions in exception message (or link to) about what permission are required for account, what are good practices for your particular case and what is possible cheap solution (i.e. "This program requires XXXX permission for YYYY. You can run as admin for tests, but not recommended for production").

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
0

I implemented the AutorizedToStopWindowsService() method that I described in my updated question and it's working quite well.

desautelsj
  • 3,587
  • 4
  • 37
  • 55