Discussion:
how the enumerate the groups of a user account SID?
(too old to reply)
Marc-Philip
2006-10-27 20:04:14 UTC
Permalink
Hi there,
2nd question :-)

Say I have the SID of a local user. How to I enumerate the SIDs of the
groups that this user is in? Searching on MSDN did not get me
anywhere...

T&R,
Marc-Philip
Eric Perlin [MSFT]
2006-10-27 21:43:02 UTC
Permalink
You'll have to lookup the account name from the SID first, but
NetUserGetLocalGroups & NetUserGetGroups should help.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Eric Perlin [MSFT]
Post by Marc-Philip
Hi there,
2nd question :-)
Say I have the SID of a local user. How to I enumerate the SIDs of the
groups that this user is in? Searching on MSDN did not get me
anywhere...
T&R,
Marc-Philip
Marc-Philip
2006-11-01 09:17:50 UTC
Permalink
Hi Eric,
your advice helped me, I got my stuff running now, but, frankly spoken,
I don't like the Windows API here.

All I wanted to do is to check, whether the owner of a file is a local
administrator. To accomplish this, I do the following:

1. get owner as SID using GetNamedSecurityInfo()
2. convert owner SID to ownerString using LookupAccountSid()
3. create SID of local administrators group using
AllocateAndInitializeSid()
4. convert local administrators group SID to groupString using
LookupAccountSid()
5. get all groups as strings that the owner is member of using
NetUserGetLocalGroups(ownerString) and check all group names whether
one of the equals groupString

There is a lot to do and a lot to pay attention to: get ownerString in
unicode format because NetUserGetLocalGroups needs it, free all the
memory that was allocated for the names,...

This is crazy from my point of view. Why can't all this operate on
SIDs? This would make life easier and programs smaller:
1. get owner as SID (ownerSID)
2. create SID of local administrators group (adminGroupSID)
3. get all SIDs of groups that ownerSID is member of and check if one
of them is adminGroupSID

On unix systems, some equivalent task would be to check whether the
file owner is root. The code for this would be:

struct stat fileInfo;
stat(filename, &fileInfo);
f( 0 == fileInfo.st_uid ) printf("owner is root.\n");

Quite short and straightforward, isn't it? :-)

Anyway, thank you for helping!
Marc-Philip
SteveS
2006-11-01 16:08:02 UTC
Permalink
Post by Marc-Philip
On unix systems, some equivalent task would be to check whether the
struct stat fileInfo;
stat(filename, &fileInfo);
f( 0 == fileInfo.st_uid ) printf("owner is root.\n");
Quite short and straightforward, isn't it? :-)
Yes, but that's because 0 is a well-known ID. If you wanted to check for a
specific non-root user, you'd have to get the user's ID from a name (unless
the UID was hardcoded in some way). In any event, this isn't the same. You
want to know whether a specific user id is a member of the Administrators
group. On UNIX you'd have to get the root group's group list and check it.
Because UNIX doesn't support groups in groups, it's a much simpler problem.

If you did

1. get file owner SID (f)
2. Get SID of local administrators group (well-known SID) (s)
3. Use recursion:
CheckForSidInGroup( f, s)
If in this, you encounter a SID that is a group (g), call
CheckForSidInGroup(g)
that should give you what you want.

Steve S
Marc-Philip
2006-11-01 19:19:15 UTC
Permalink
Post by SteveS
If you did
1. get file owner SID (f)
2. Get SID of local administrators group (well-known SID) (s)
CheckForSidInGroup( f, s)
If in this, you encounter a SID that is a group (g), call
CheckForSidInGroup(g)
that should give you what you want.
Steve,
the recursive call should be CheckForSidInGroup(f, g), shouldn't it?

After checking on MSDN I think that should be implemented using
NetLocalGroupGetMembers. Here again, it needs a local group's name, not
it's SID. But your right, it returns the group members as SIDs (for
level 0). This is one step in the right direction.

T&R,
Marc-Philip
SteveS
2006-11-02 11:17:01 UTC
Permalink
Post by Marc-Philip
Steve,
the recursive call should be CheckForSidInGroup(f, g), shouldn't it?
Yes it should. Sorry about that, I typed without too much thinking.

Having done some more thinking, I have an alternative approach.

1. Get the SID of the local Administrators group, and look up the name.
2. If you have a SID for the owner, use LookupAccountSid to convert to a
name.
3. Use NetUserGetLocalGroups(NULL, name, 0, LG_INCLUDE_INDIRECT, ....) to
get a set of groups the user is in. The LG_INCLUDE_INDIRECT will force the
recursion by the NETAPI function, saving you the trouble.
4. Go through each of the returned GROUP_USER_INFO_0 entries
Either
(a) Get the SID for that account, compare the SID with the one obtained
in (1),
or (b) Compare the name with the account name obtained in (1).

I did something similar a while back when enumerating users who were
(indirect) members of particular groups, but as a contractor, I didn't get to
keep the actual code.

Hope this helps,

Steve S
Marc-Philip
2006-11-02 12:42:45 UTC
Permalink
Post by SteveS
1. Get the SID of the local Administrators group, and look up the name.
2. If you have a SID for the owner, use LookupAccountSid to convert to a
name.
3. Use NetUserGetLocalGroups(NULL, name, 0, LG_INCLUDE_INDIRECT, ....) to
get a set of groups the user is in. The LG_INCLUDE_INDIRECT will force the
recursion by the NETAPI function, saving you the trouble.
4. Go through each of the returned GROUP_USER_INFO_0 entries
Either
(a) Get the SID for that account, compare the SID with the one obtained
in (1),
or (b) Compare the name with the account name obtained in (1).
I did something similar a while back when enumerating users who were
(indirect) members of particular groups, but as a contractor, I didn't get to
keep the actual code.
Steve,
that's exactly what I do (see my posting on Wednesday). All I'm saying
is that I don't like having to convert SIDs to names to do that:
NetUserGetLocalGroups needs a name (no SID) and returns names (no
SIDs). That's my point.

Regards,
MP

Loading...