Re: Cannot obtain account SID using C#/WMI
- From: "Willy Denoyette [MVP]" <willy.denoyette@xxxxxxxxxx>
- Date: Wed, 18 Apr 2007 12:49:39 +0200
"VictorG" <grippiconsulting@xxxxxxxxx> wrote in message news:1176848997.732919.286150@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
On Apr 14, 1:56 am, "Willy Denoyette [MVP]"
<willy.denoye...@xxxxxxxxxx> wrote:
"VictorG" <grippiconsult...@xxxxxxxxx> wrote in message
news:1176492651.381794.57770@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> On Apr 12, 1:59 pm, "Willy Denoyette [MVP]"
> <willy.denoye...@xxxxxxxxxx> wrote:
>> "VictorG" <grippiconsult...@xxxxxxxxx> wrote in message
>>news:1176401511.343225.131440@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
>> > Hello,
>> > The below C# code works fine in obtaining the windows user's account
>> > SID when the user is local to the machine. It throws a "Not Found"
>> > exception when trying top obtain the SID for a user who is on a
>> > domain, but logged in locally. Specifically, for a corporate domain -
>> > the user logs into the local desktop and has a local profile - not a
>> > roaming profile.
>> > The below code is implemented in an NT service for the purpose of
>> > allowing the service to access the user's registry hive under "current
>> > user". Since the service runs under the SYSTEM account the current
>> > user mapping is for the default SYSTEM account. We impersonate the
>> > logged in windows user and then simulate the current user mapping by
>> > using the SID and accessing the HKEY_USER hive (basically the same as
>> > accessing the current user hive). This works fine for windows users
>> > who are named: machineName/userName but not for CORPORATE/userName.
>> > Is this SID available through WMI? Is there a different string I need
>> > to query for it? Could there be security settings on this corporate
>> > account? I am running under the SYTSTEM account so I should have full
>> > privileges?
>> > Here is the code:
>> > string slash = @"\";
>> > int pos = winUserName.IndexOfAny(slash.ToCharArray());
>> > string machineName = winUserName.Substring(0, pos);
>> > string userName = winUserName.Substring(pos + 1, winUserName.Length -
>> > pos - 1);
>> > // Use WMI to get the SID of the user
>> > string p = String.Format("ROOT\\CIMV2:Win32_UserAccount.Domain=
>> > \"{0}\",Name=\"{1}\"", machineName, userName);
>> > ManagementPath path = new ManagementPath(p);
>> > System.Management.ManagementObject account = new
>> > ManagementObject(path);
>> > sid = account["SID"] as string;
>> > account.Dispose();
>> > Any ideas or suggestion will be greatly appreciated.
>> > Thanks,
>> > Victor Grippi
>> The domain account SID's aren't stored on the local machine, they are stored on the >> DC,
>> so
>> will have to connect to DC of the users logon domain to obtain his SID.
>> Willy.- Hide quoted text -
>> - Show quoted text -
> Hi Willy,
> Thanks for the response. If there is no local SID for the domain
> user, then is there a registry hive for this user on the local
> machine? If there is a current user registry mapping - then how
> would I access this from a service? Or is the SID obtained
> dymanically, by the OS, so it is present on the local machine, but
> cannot be obtained through WMI?
> I am restricted to using .NET 1.1 and when impersonating a user need
> to P/Invoke. This includes loading the user profile, that does return
> an unmanaged handle to the user's registry hive. I cannot use it
> later in managed code since the .NET 1.1 registry classes do not
> accept a handle to the registry. And I cannot P/Invoke in the code
> that access the registry. So I use the SID with the .NET 1.1 registry
> classes and this has been working out good, except when the SID is not
> present with a domain account. I may not always have permissions on
> the domain controller to obtain the SID, and then there is the
> overhead also to consider.
> Am I stuck here?
> Victor
You can't get the SID from a domain account if you are disconnected from the domain.
However, you don't need the SID to map the USER hive from a cached profile, all you need is
to load the ntuser.dat by calling "RegLoadKey" through PInvoke, from that users profile
folder. The profile folder name, is the name of the user account under "Documents and
Settings" on XP and W2Kx or "Users" on Vista and Longhorn.
Note however, that this only works if the user has a profile cached on the local machine and
that it's not a portable solution, user profiles are best loaded from a login session or
when impersonating, using the "LoadUserProfile" API.
Also, you need to make sure that hives are unloaded when done with them!
Willy.- Hide quoted text -
- Show quoted text -
The problem is knowing which current_user registry mapping we need.
Not loading the hive. The NT service, we are developing, hosts
services (C# libraries) that are loaded into separate app domains.
Client applications receive a proxy interface to the service and
make .NET remoting calls on it. Multiple user applications can call
into these services, and in some cases we need to access their
registry hive. So one call (thread) may by from Windows user A, and
the next call (thread) in the same method may be from Windows user B.
Normally, in code running on a desktop, you simply access the
current_user registry hive. But in our case the call could have come
from any active desktop, so I was storing the user's SID in the call
context and using this to access the HKEY_USER hive, which is the same
as the current user mapping on a desktop.
But since there are edge cases where obtaining the SID breaks down, it
is not just a case of loading the hive, but in knowing which hive to
read or write. We want the protection of the user hive or else
everything could just go into the HKLM hive. Does this explain my
situation better?
Victor
Reading/writing from a USER hive can only be done after loading the users profile, loading is the act of mapping the ntuser.dat file into the Registry's namespace and as such creating a hive (a hive = a set of keys, sub-keys and values in this namespace).
Say there exists a profile "c:\documents And Settings\bob" and you want to read/write from it, then you'll have to call "LoadUserProfile" specifying the access token for the user Bob. The access token will be used to create the hive using the SID of the user (obtained through the token handle) as key.
Now in your case you don't have a token handle (you don't have a logon session for that user), that means that you can only load the profile of a user under HKEY_USERS (and HKLM) using "RegLoadKey", this API takes a file name eg. "c:\documents And Settings\bob" and a sub-key. The sub-key is in general the user's SID, but it can be any name, as long as you know the name of the key corresponding to the user BOB you are ok.
In short: if you only have the name of the user, you simply need to call "RegLoadKey" using the user name as file name from the users profile directory path, you can also use this name as the sub-key.
If you have both the SID and user name, you can use both in the "RegLoadKey" call. In any case you need the user name!
Reading and writing must obviously be done from HKU not from HKCU.
Willy.
Willy.
.
- References:
- Re: Cannot obtain account SID using C#/WMI
- From: VictorG
- Re: Cannot obtain account SID using C#/WMI
- From: Willy Denoyette [MVP]
- Re: Cannot obtain account SID using C#/WMI
- From: VictorG
- Re: Cannot obtain account SID using C#/WMI
- Prev by Date: Re: inherited object as ref
- Next by Date: Re: Generics lists and cloned combobox controls
- Previous by thread: Re: Cannot obtain account SID using C#/WMI
- Next by thread: GridView not being displayed: Lil silly mistake i guess....
- Index(es):
Relevant Pages
|
Loading