Archive: User Management using API calls


User Management using API calls
Hello

Using this fantastic article, when eumerating users is it possible to determine which group they are associated to?

regards

Carl


The macro posted on the Wiki uses a USER_INFO_0 structure to pick the usernames. You can use a USER_INFO_3 structure which also contains the user's RID as well as his/her group's RID. Alternatively you can use NetUserGetInfo using the username to get the group information.

Another option would be to use NetUserGetLocalGroups using the usernames from the NetUserEnum call in order to get the group names associated with that particular user.

Note however that a single user may be associated with multiple groups.

Hope this helps
CF


Thanks Cancer face, would it be possible for an example?


Here is an example using the NetUserGetLocalGroups API function:

!macro GetUserGroups SERVER_NAME USERNAME GROUP_ARRAY_NAME
# Get user's group(s)
!define Index "Line${__LINE__}"
# $R0 buffer with an array of LOCALGROUP_USERS_INFO_0 structures
# $R1 holds the number of entries processed
# $R2 holds the total number of entries
System::Call 'netapi32::NetUserGetLocalGroups(w "${SERVER_NAME}",w "${USERNAME}",i 0,i 0,*i.R0,i ${NSIS_MAX_STRLEN},*i.R1,*i.R2)i.r2'
StrCpy $R8 $R0
StrCpy $9 0
NSISArray::New /NOUNLOAD ${GROUP_ARRAY_NAME}
${Index}-loop:
StrCmp $9 $R2 ${Index}-stop +1
System::Call "*$R0(w.R9)"
NSISArray::Write /NOUNLOAD ${GROUP_ARRAY_NAME} $9 "$R9"
IntOp $R0 $R0 + 4
IntOp $9 $9 + 1
Goto ${Index}-loop
${Index}-stop:
NSISArray::SizeOf /NOUNLOAD ${GROUP_ARRAY_NAME}
Pop $0
StrCmp $0 $R2 +2 +1
MessageBox MB_OK|MB_ICONEXCLAMATION "Could not place all the user's groups into an array!"
System::Call 'netapi32.dll::NetApiBufferFree(i R8)i .r2'
!undef Index
!macroend
and call the macro using for example:
!insertmacro GetUserGroups "$ServerName" "$UserName" "UserGroupsArray"
Note that leaving $ServerName blank is the same as using the name of the local machine.

So you could use the NetUserEnum function to enumerate all the users and place them in an array, then call the above macro for each user that you pop out of the array to see where he/she belongs. Don't forget to delete the array object(s) once you are done and to unload the array plugin.

Note that I am using version 1 of the Array plugin

Hope this helps
CF

(updated also the wiki ,adding the above macro)

i trying to use this function and i got the "Could not place all the user's groups into an array!"
msg, and i don't know what to do.


What are the values of R1 and R2 that you get after calling NetUserGetLocalGroups? Try to pop them out.
Also, what does the array contain at the end of the call? Try the /Debug option (check Afro's plugin documentation)
If you are *not* using version 1 of the array plugin then you have to define the array in a different way - check Afro's plugin documentation ...

I assume that you are calling the macro for an existing user that belongs to at least one group ...
CF


i using Version: 1.7...
what does the array contain at the end of the call? he contain 2 vars.

after calling NetUserGetLocalGroups
R1 = 2
R2 = 2

but the user belogs to at lest 3 groups.
and in the end of the func i get the "Could not place all the user's groups into an array!"
msg.

what can i do?


also i defined the array like this: ${Array} "ArrayName" 10 10


If *right* after the NetUserGetLocalGroups call R2 equals 2 it means that your user belongs only to 2 local groups, ie the call does not fail. Is it possible that the rest of the groups are, say, domain groups? Check also $2 after the NetApi call to see if there is an error and refer to the NetUserGetLocalGroups MSDN page for a description of the error.

MSDN seems to be shifting their pages a lot, you can find more info about NetUserGetLocalGroups here
According to that page you should be using NetUserGetGroups to get the Global groups.

The posted macro works in my hands and correctly enumerates 10 local groups for a user, using Array plugin v.1.0

It would appear that the problem you have is related to the array plugin. In v.1.0 the following gives you the size of the array (ie the number of elements stored in the array)

NSISArray::SizeOf /NOUNLOAD ${GROUP_ARRAY_NAME}
Pop $0
However, at some point Stu added more options to that call, so you would have to pop a couple of times in order to get the number of elements out in v.1.7 of the plugin.
The following code which is Array v.1.7 compatible works for me and correctly enumerates 10 local groups for a user:
  # Get user's group(s)
!define Index "Line${__LINE__}"
# $R0 buffer with an array of LOCALGROUP_USERS_INFO_0 structures
# $R1 holds the number of entries processed
# $R2 holds the total number of entries
System::Call 'netapi32::NetUserGetLocalGroups(w "${SERVER_NAME}",w "${USERNAME}",i 0,i 0,*i.R0,i ${NSIS_MAX_STRLEN},*i.R1,*i.R2)i.r2'
StrCpy $R8 $R0
StrCpy $9 0
NSISArray::New /NOUNLOAD ${GROUP_ARRAY_NAME} 2 2
${Index}-loop:
StrCmp $9 $R2 ${Index}-stop +1
System::Call "*$R0(w.R9)"
NSISArray::Write /NOUNLOAD ${GROUP_ARRAY_NAME} $9 "$R9"
IntOp $R0 $R0 + 4
IntOp $9 $9 + 1
Goto ${Index}-loop
${Index}-stop:
NSISArray::SizeOf /NOUNLOAD ${GROUP_ARRAY_NAME}
Pop $0
Pop $0
Pop $0
StrCmp $0 $R2 +2 +1
MessageBox MB_OK|MB_ICONEXCLAMATION "Could not place all the user's groups into an array!"
System::Call 'netapi32.dll::NetApiBufferFree(i R8)i .r2'
!undef Index


CF