Page 1 of 2

IsAdministrator()

Posted: Thu Apr 03, 2003 10:38 am
by BackupUser
Restored from previous forum. Originally posted by fred.


I've wrote a little routine which could be useful to some of you. It test if the currently logged is a member of the administrator group. It's also a good example of the NetAPI use for user and account management.

Code: Select all

; Need Windows NT/2000/XP
;

#SECURITY_BUILTIN_DOMAIN_RID = $00000020

Structure LOCALGROUP_MEMBERS_INFO_1
  *lgrmi1_sid.l
  lgrmi1_sidusage.l
  *lgrmi1_name.l      ; Warning, its WideCHAR
EndStructure


Procedure LookupAliasFromRid(TargetComputer, Rid, *Name)

  sia.SID_IDENTIFIER_AUTHORITY
    
  ; #define SECURITY_NT_AUTHORITY           {0,0,0,0,0,5}   // ntifs
  sia\Value[5] = 5
  
  If AllocateAndInitializeSid_(@sia, 2, #SECURITY_BUILTIN_DOMAIN_RID, Rid, 0, 0, 0, 0, 0, 0, @*Sid)
    
    NameSize       = 1024
    DomainNameSize = 1024

    DomainName$ = Space(DomainNameSize)
  
    Result = LookupAccountSid_(TargetComputer, *Sid, *Name, @NameSize, DomainName$, @DomainNameSize, @snu)
    
    FreeSid_(*Sid) ;
  EndIf
  
  ProcedureReturn Result
EndProcedure 


Procedure IsAdmininistrator()

  ; First, get the alias name for the admin group (depending of the langage)
  ;
  AdministratorGroupName$ = Space(1024)
  If LookupAliasFromRid(0, #DOMAIN_ALIAS_RID_ADMINS, @AdministratorGroupName$)
    
    ; Then, Get the current logged user name
    ;
    LoggedUserNameSize  = 1024
    LoggedUserName$     = Space(LoggedUserNameSize)
    If GetUserName_(@LoggedUserName$, @LoggedUserNameSize)

      ; Use the NetAPI32.dll. This is for Windows NT only (accounts support needed)
      ;    
      If OpenLibrary(0, "NetAPI32.dll" )
      
        ; Convert our admin group name into WideChar, as the API function need it
        ;
        AdministratorGroupNameW$ = Space(1024)  
        MultiByteToWideChar_(#CP_ACP, #MB_PRECOMPOSED, AdministratorGroupName$, -1, AdministratorGroupNameW$, 1024)

        ; Enumerate all the members of the administrators group and see if the logged user is inside
        ;                
        If CallFunction(0, "NetLocalGroupGetMembers", 0, AdministratorGroupNameW$, 1, @*MembersBuffer.LOCALGROUP_MEMBERS_INFO_1, 10000, @NbEntriesRead, @NbTotalEntries, @ResumeHandle) = #ERROR_SUCCESS
          
          For k=1 To NbEntriesRead

            MemberName$ = Space(1024)
            WideCharToMultiByte_(#CP_ACP, 0, *MembersBuffer\lgrmi1_name, -1, MemberName$, 1024, 0, 0)
            
            If MemberName$ = LoggedUserName$
              Result = 1
            EndIf
            
            ; Go to the next user
            ;
            *MembersBuffer+SizeOf(LOCALGROUP_MEMBERS_INFO_1)
          Next 
          
          ; Don't forget to release the buffer allocated by NetLocalGroupGetMembers()
          ;
          CallFunction(0, "NetApiBufferFree", @*MembersBuffer)
        EndIf
        
        CloseLibrary(0)
      EndIf
    EndIf
  EndIf
  
  ProcedureReturn Result
EndProcedure

; The test code
;
Debug IsAdmininistrator()
Enjoy,

Fred - AlphaSND

Posted: Thu Apr 03, 2003 2:28 pm
by BackupUser
Restored from previous forum. Originally posted by Berikco.

It works, i'm admin here :)


Regards,

Berikco

http://users.pandora.be/berikco/purebasic.htm

Posted: Thu Apr 03, 2003 7:17 pm
by BackupUser
Restored from previous forum. Originally posted by fred.

Of course it works ! :).

Fred - AlphaSND

Posted: Mon Jul 14, 2003 11:00 am
by wichtel
Does anyone know how to change this code, so that it works with active directory or NT domains.

e.g. Someone is logged on with domain admin rights, but this account is not explicit listed in the local admin group.
This code example would then return 0 (no admin rights) which is wrong.

Michael

Posted: Mon May 24, 2004 10:03 am
by Lucifer
This works great for LOCAL ADMIN but how do you look inside an admin group that is in the admin group?

Say you are on a domain and you (FRED BLOGGS) have admin rights in the group "PC Technician". You add the group "PC Technician" to the PC's admin group.

i.e.

Local Users and Groups
--Users
--Groups
----Administrators
------Administrator
------DOMAIN\Domain Admins
------DOMAIN\PC Technician <---- Check for FRED BLOGGS in here?
----Backup Operators
----Guests
----Network Configuration Operators
----Power Users
----Remote Dektop Users
----Replicator
----Users
----Help Services Group

I would assume you can do a search for a specific group but how do you then search inside that group.

Can each entry be tested in the admin group to see if it is a domain group that can then be searched further?

I am writing a program that automatically brings up the configuration window if you are an administrator.

Posted: Mon May 24, 2004 2:13 pm
by Lucifer
Would I be correct in thinking that using this routine as a starting platform then use
LocalGroupGetMembers(server, groupName, userArrayRef) to get the group names and if sidtype = 3 (DOMAIN) then use
GroupGetMembers(server, groupName, userArrayRef) and check the list against the logged in user.

Does anyone know if I’m going in the right direction?

Posted: Mon May 24, 2004 4:51 pm
by wichtel
Well, after all, I now use a different method to check if I'm admin.
It is a dumb, but working method.
I just connect to the local services manager and try to gain full access.
If this fails, I don't have admin right, if I'm allowed full access on the local services manager I have admin rights.

Workes for.

Michael

Posted: Mon May 24, 2004 6:14 pm
by Lucifer
I'm willing to try anything.

Any chance of an example?

Re: IsAdministrator()

Posted: Mon May 24, 2004 7:22 pm
by NoahPhense
Very nice Fred, thx!

- np

Posted: Mon May 24, 2004 8:37 pm
by wichtel
@Lucifer:

as simple as that...

Code: Select all

Procedure admin()
  ret = openSCmanager_(#NULL,#NULL,#SC_MANAGER_ALL_ACCESS)
  If ret
    closeServiceHandle_(ret)
  EndIf
  ProcedureReturn ret
EndProcedure  

another stupid and insecure way to gain admin access works only for XP.... (but helped sometime)

Code: Select all

Procedure impersonate()
  ret.l
  username.s="your_username"
  domain.s="your_domain"
  password.s="your_password"
  token.l
  Result=LogonUser_(@username,@domain,@password,#LOGON32_LOGON_INTERACTIVE,#LOGON32_PROVIDER_DEFAULT,@token)
  Result=ImpersonateLoggedOnUser_(token)
  If Result
    ret=1
  Else
    ret=0
  EndIf
;  ret=0
  ProcedureReturn ret
EndProcedure  
greetings
Michael

Posted: Mon May 24, 2004 10:21 pm
by Lucifer
Thanks, I'll give that a go.

Posted: Tue May 25, 2004 7:47 am
by Lucifer
Wichtel,

I have only tried your first example and it works well for me.

Many thanks.

Posted: Fri Jan 18, 2008 6:17 am
by PB
For Windows 2000 and higher:

Code: Select all

Debug IsUserAnAdmin_() ; 1=Yes, 0=No

Posted: Tue Feb 26, 2008 7:09 pm
by wichtel
There is a bug in the implementation of IsUserAnAdmin_()

Read about it here:
http://www.tech-archive.net/Archive/Dev ... 00568.html
It seems that this function is exported by ordinal only and not by name.

I had the same issue on some Windows 2000 boxes.
I even got an error "Cannot find entry point into shell32.dll" when I had the IsUserAnAdmin_ function in my code without calling it.
The workaround described in the link above works well.
I have translated it into purebasic.

Code: Select all

Procedure MyIsUserAnAdmin()
  SHELL32=OpenLibrary(#PB_Any,"shell32.dll")
  If IsLibrary(SHELL32)
    *pIsUserAnAdmin = GetFunctionEntry(SHELL32, 680)
    If *pIsUserAnAdmin
      ret=CallFunctionFast(*pIsUserAnAdmin)
    EndIf
    CloseLibrary(SHELL32)
  EndIf  
  ProcedureReturn ret
EndProcedure
Greetings
Michael

Posted: Tue Feb 26, 2008 8:47 pm
by PB
> There is a bug in the implementation of IsUserAnAdmin_()

There's another API command: IsUserAdmin_()

Perhaps that one is okay? Love how Microsoft bloats Windows with
multiple commands that do the same thing. :) Ah well.