IsAdministrator()

Share your advanced PureBasic knowledge/code with the community.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

IsAdministrator()

Post 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
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post 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
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by fred.

Of course it works ! :).

Fred - AlphaSND
User avatar
wichtel
User
User
Posts: 71
Joined: Fri May 02, 2003 11:14 am
Location: Germany
Contact:

Post 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
Lucifer
User
User
Posts: 26
Joined: Wed Apr 30, 2003 6:11 pm
Location: UK

Post 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.
Lucifer
User
User
Posts: 26
Joined: Wed Apr 30, 2003 6:11 pm
Location: UK

Post 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?
User avatar
wichtel
User
User
Posts: 71
Joined: Fri May 02, 2003 11:14 am
Location: Germany
Contact:

Post 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
PB 5.40 LTS, W7,8,10 64bit and Mint x64
Lucifer
User
User
Posts: 26
Joined: Wed Apr 30, 2003 6:11 pm
Location: UK

Post by Lucifer »

I'm willing to try anything.

Any chance of an example?
User avatar
NoahPhense
Addict
Addict
Posts: 1999
Joined: Thu Oct 16, 2003 8:30 pm
Location: North Florida

Re: IsAdministrator()

Post by NoahPhense »

Very nice Fred, thx!

- np
User avatar
wichtel
User
User
Posts: 71
Joined: Fri May 02, 2003 11:14 am
Location: Germany
Contact:

Post 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
PB 5.40 LTS, W7,8,10 64bit and Mint x64
Lucifer
User
User
Posts: 26
Joined: Wed Apr 30, 2003 6:11 pm
Location: UK

Post by Lucifer »

Thanks, I'll give that a go.
Lucifer
User
User
Posts: 26
Joined: Wed Apr 30, 2003 6:11 pm
Location: UK

Post by Lucifer »

Wichtel,

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

Many thanks.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

For Windows 2000 and higher:

Code: Select all

Debug IsUserAnAdmin_() ; 1=Yes, 0=No
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
wichtel
User
User
Posts: 71
Joined: Fri May 02, 2003 11:14 am
Location: Germany
Contact:

Post 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
PB 5.40 LTS, W7,8,10 64bit and Mint x64
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post 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.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
Post Reply