I am trying to control a Windows Service via a Web Service interface.
(I am developing in .NET2003) I am using the ServiceController object
which allows me to read the state of the services with no problems.
However, I am not able to start or stop the service unless I go
through the process of impersonating an administrative user. (See
MSDN KB 306158)
Since it appears to be a privilege issue, I set the folders in IIS
holding the Web Service files to Anonymous Access with the privileges
of the administrative user that I was able to impersonate. This did
not work.
Does anybody have any ideas as to how I need to set the security of
the Web service such that I can get rid of the impersonation code in
my application?
Thanks
Doug
WORKS:
String __gc* streamAccessClass::turnStreamOn()
{
ServiceController * streamCtl = new ServiceController();
streamCtl->ServiceName = "newserviceWinService";
if(streamCtl->get_Status() == ServiceControllerStatus::Stopped
|| streamCtl->get_Status() == ServiceControllerStatus::Paused)
{
cImpersonation * user = new cImpersonation();
try
{
if(user->impersonateValidUser(S"IISTEST", S"BaileyD", S"IISTEST"))
{
streamCtl->Start();
streamCtl->WaitForStatus (ServiceControllerStatus::Running);
user->undoImpersonation();
return S"Streamer is On";
}
else
{
return S"Could not log on";
}
}
catch (Exception * startErr)
{
user->undoImpersonation();
return startErr->get_Message();
}
} return S"Streamer failed due to improper state";
}
bool cImpersonation::impersonateValidUser(String * userName, String *
domain, String * password)
{
WindowsIdentity * tempWindowsIdentity;
IntPtr token = IntPtr(0);
IntPtr tokenDuplicate = IntPtr(0);
if(RevertToSelf())
{
if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, token) != 0)
{
if(DuplicateToken(token, 2, tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity->Impersonate();
if (impersonationContext != 0)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if(token!= IntPtr::Zero)
CloseHandle(token);
if(tokenDuplicate!=IntPtr::Zero)
CloseHandle(tokenDuplicate);
return false;
}
void cImpersonation::undoImpersonation()
{
if (impersonationContext != 0)
impersonationContext->Undo();
}
DOES NOT WORK:
String __gc* streamAccessClass::turnStreamOn()
{
ServiceController * streamCtl = new ServiceController();
streamCtl->ServiceName = "newserviceWinService";
if(streamCtl->get_Status() == ServiceControllerStatus::Stopped
|| streamCtl->get_Status() ==ServiceControllerStatus::Paused)
{
try
{
streamCtl->Start();
streamCtl->WaitForStatus (ServiceControllerStatus::Running);
return S"Streamer is On";
}
catch (Exception * startErr)
{
return startErr->get_Message();
}
} return S"Streamer failed due to improper state";
}
Eric Cherng - 18 Aug 2004 01:13 GMT
I'm guessing it didn't work because setting the folder is not enough to give
the anonymous user access to the Windows Service. Instead of doing this,
consider running your web service as another user rather than the default
anonymous user. Then give the user enough rights to start/stop the Windows
Service. This way, when you call your Web service, the Web service will run
as the new user in IIS, and, assuming it has the proper rights, it should be
able to manipuate the Windows Services. Of course, if you plan on doing
this, you should properly secure your web service.
Eric

Signature
Eric Cherng
MCP, MCDBA, MCSD
http://echerng.com
>I am trying to control a Windows Service via a Web Service interface.
> (I am developing in .NET2003) I am using the ServiceController object
[quoted text clipped - 108 lines]
> } return S"Streamer failed due to improper state";
> }
Doug Bailey - 18 Aug 2004 13:33 GMT
What do I need to do this? I went to the service's IIS directory and
turned off the anonymous access. I still got the same results when I
ran it.
Do I need to do anything to the service's web.config file. Right now
it is set to the default which uses Windows authentication and all
users have privileges.
Doug
> I'm guessing it didn't work because setting the folder is not enough to give
> the anonymous user access to the Windows Service. Instead of doing this,
[quoted text clipped - 119 lines]
> > } return S"Streamer failed due to improper state";
> > }
Eric Cherng - 18 Aug 2004 18:37 GMT
Here's how to do it. This uses Windows Authentication so if your client
isn't or doesn't support it then this method will not work.
1. Uncheck anonymous access to your Web service and make sure your Windows
Authentication is checked. If you don't uncheck anonymous, access to the Web
service will use anonymous by default.
2. Add this into your web.config for your Web service (in the <system.web>
tag)
<identity impersonate="true" />
3. Access the Web service test page as a Windows user that has the proper
rights on the machine to start/stop web services.
Attached is my sample code that implements this solution and successfully
starts/stops the "FTP Publishing" service.
Eric

Signature
Eric Cherng
MCP, MCDBA, MCSD
http://echerng.com
> What do I need to do this? I went to the service's IIS directory and
> turned off the anonymous access. I still got the same results when I
[quoted text clipped - 133 lines]
>> > } return S"Streamer failed due to improper state";
>> > }