The problem in WMI access to remote server with Windows Credentials

V

Vadim Malishev

Hello,

Can anybody help to solve the following problem?

My Windows Service trying to access remote machine to get WindowsDirectory
Property over Win32_OperatingSystem WMI class. Both servers are in the same
Active Directory domain, so I create special active directory user and
impersonate to it before invoke WMI.

My code looks like:

foreach (WMI.OperatingSystem sysTest in
WMI.OperatingSystem.GetInstances(scope, new string[] {
"WindowsDirectory" }))
{
return sysTest.WindowsDirectory;
}

This code works fine if I specify UserName and password in the scope, but it
is fail if I use WindowsImpersonation (and specify null as userName in the
scope) with the following error:

System.ArgumentException: Value does not fall within the expected range.
at
System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32
errorCode, IntPtr errorInfo)
at System.Management.SecurityHandler.Secure(IEnumWbemClassObject
enumWbem)
at System.Management.ManagementObjectCollection.GetEnumerator()
at WMI.OperatingSystem.OperatingSystem0Collection.GetEnumerator()



The problem here:


public class System.Management.ManagementObjectCollection
{
//...
public ManagementObjectEnumerator GetEnumerator()
{
//...
IEnumWbemClassObject ppEnum = null;
int errorCode = 0;
try
{
errorCode = this.enumWbem.Clone_(out ppEnum);
this.scope.GetSecurityHandler().Secure(ppEnum); //<<<<<<<<< Error
!!!!!!!!!!!!

if ((errorCode & 0x80000000) == 0)
{
errorCode = ppEnum.Reset_();
}
}

The IEnumWbemClassObject.Clone fails with code WBEM_E_ACCESS_DENIED and
returns ppEnum with null, then IWmiSec.BlessIEnumWbemClassObject (It is
called inside SecurityHandler.Secure) fails with ArgumentException.

The most strange in it is this code don't fail if I invoke it from
interactive user (not in service).

Can anybody help me to understand how to fix or workaround this problem? I
found only one solution: to create object without enumerate by specify
direct management path, but it is work only for objects like Win32_Service
here I can build this path, but for Win32_OperatingSystem I can't build
management path because its look like
"\\Server\root\CimV2:Win32_OperatingSystem.Name="Microsoft Windows Server
2003 Enterprise Edition|C:\\WINDOWS|\\Device\\Harddisk0\\Partition1" and I
have no idea how to build such path remotely.

Thanks.

Vadim Malishev
PEM Windows Platform Services Team Leader
SWsoft, Inc.
E-mail: (e-mail address removed)
Phone: +7 923 240 04 48
ICQ UIN: 74989244
Skype nick: lboos75
Google talk: (e-mail address removed)
MSN: (e-mail address removed)
Web Site: http://www.swsoft.com
 
W

Willy Denoyette [MVP]

Vadim Malishev said:
Hello,

Can anybody help to solve the following problem?

My Windows Service trying to access remote machine to get WindowsDirectory
Property over Win32_OperatingSystem WMI class. Both servers are in the
same
Active Directory domain, so I create special active directory user and
impersonate to it before invoke WMI.

My code looks like:

foreach (WMI.OperatingSystem sysTest in
WMI.OperatingSystem.GetInstances(scope, new string[] {
"WindowsDirectory" }))
{
return sysTest.WindowsDirectory;
}

This code works fine if I specify UserName and password in the scope, but
it
is fail if I use WindowsImpersonation (and specify null as userName in the
scope) with the following error:

System.ArgumentException: Value does not fall within the expected range.
at
System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32
errorCode, IntPtr errorInfo)
at System.Management.SecurityHandler.Secure(IEnumWbemClassObject
enumWbem)
at System.Management.ManagementObjectCollection.GetEnumerator()
at WMI.OperatingSystem.OperatingSystem0Collection.GetEnumerator()



The problem here:


public class System.Management.ManagementObjectCollection
{
//...
public ManagementObjectEnumerator GetEnumerator()
{
//...
IEnumWbemClassObject ppEnum = null;
int errorCode = 0;
try
{
errorCode = this.enumWbem.Clone_(out ppEnum);
this.scope.GetSecurityHandler().Secure(ppEnum); //<<<<<<<<< Error
!!!!!!!!!!!!

if ((errorCode & 0x80000000) == 0)
{
errorCode = ppEnum.Reset_();
}
}

The IEnumWbemClassObject.Clone fails with code WBEM_E_ACCESS_DENIED and
returns ppEnum with null, then IWmiSec.BlessIEnumWbemClassObject (It is
called inside SecurityHandler.Secure) fails with ArgumentException.

The most strange in it is this code don't fail if I invoke it from
interactive user (not in service).

Can anybody help me to understand how to fix or workaround this problem? I
found only one solution: to create object without enumerate by specify
direct management path, but it is work only for objects like Win32_Service
here I can build this path, but for Win32_OperatingSystem I can't build
management path because its look like
"\\Server\root\CimV2:Win32_OperatingSystem.Name="Microsoft Windows Server
2003 Enterprise Edition|C:\\WINDOWS|\\Device\\Harddisk0\\Partition1" and I
have no idea how to build such path remotely.

Thanks.

Vadim Malishev
PEM Windows Platform Services Team Leader
SWsoft, Inc.
E-mail: (e-mail address removed)
Phone: +7 923 240 04 48
ICQ UIN: 74989244
Skype nick: lboos75
Google talk: (e-mail address removed)
MSN: (e-mail address removed)
Web Site: http://www.swsoft.com



Please post your code, posting a piece of System.Management's implementation
is of no use for us.
What we need is a small but complete sample that illustrates the issue (a
console sample!), we need to see how you set-up the scope.
Also you need to make sure that the impersonating thread is the thread that
calls the remote server, from your description it looks like the call is
made using the process token (using the Service process identity), not the
impersonating token.
Also we need some more context, what OS and Framework version are you
running this from?

Willy.
 
V

Vadim Malishev

Sorry for the answer delay.
Please post your code, posting a piece of System.Management's
implementation is of no use for us.
What we need is a small but complete sample that illustrates the issue (a
console sample!), we need to see how you set-up the scope.

It is not easy.

It is:
MPF (Microsoft Provisioning Framework) provider. This provider registered to
impersonate to the system user (created by installer). This part is
correct - DCOM impersonate my code before invoke Process method. After that
I try to connect WMI.
Also you need to make sure that the impersonating thread is the thread
that calls the remote server, from your description it looks like the call
is made using the process token (using the Service process identity), not
the impersonating token.

Good idea - thank you - I will check it.
Also we need some more context, what OS and Framework version are you
running this from?
Win2003 Ent, .NET 2.

Vadim.
 
Top