Solved

User permissions, username and domain at login

Posted on 2004-10-04
3
529 Views
Last Modified: 2010-04-05
how can I determine if the current user has administrator or domain Admin user rights on the network. I need a procedure or function that work on win95, win98, WinNT, XP and ME, or alternatively how can I get the username and domain the user is logged onto for a specific computer.

m2maths
0
Comment
Question by:m2maths
3 Comments
 
LVL 11

Expert Comment

by:calinutz
ID: 12215398
Try this link:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsecure/html/msdn_ntprog.asp


or

Download Bill Stewart's 'Windows Admin Script Tools' from http://home.comcast.net/~stewartb/files/wast61.zip.

The Readme.txt file contains:

Windows Admin Script Tools
(C) 2001-2004 by Bill Stewart (bstewart@iname.com)

These utilities provide a Windows system administrator with several
essential functions that can be particularly useful in logon scripts.

FVER.EXE
    FVER allows a batch file to perform version checking on a Win32
    executable file, provided it contains version information.

ISADMIN.EXE
    ISADMIN checks if the currently logged-on user is an administrator
    (Windows NT 4.0 and later). It runs fine on Windows 9x/Me, where the
    current logged on user is always an administrator.

ISMEMBER.EXE
    ISMEMBER can check if the currently logged-on user is a member of one
    or more groups that you can specify on the command line, and it can
    also list group memberships. Requires Windows NT 4.0 or later.

MINWIN.EXE
    MINWIN minimizes the topmost window on the screen (useful in logon
    scripts).

NEEDBOOT.EXE
    NEEDBOOT determines if there are pending file rename/move/delete
    operations for the next system boot. On Windows 9x/Me, it checks for
    the existence of any entries in the [Rename] section of WININIT.INI; on
    the Windows NT platform, it checks for the existence of the
    PendingFileRenameOperations registry entry. It can also list the
    entries in the [Rename] section or the contents of the registry entry.

NUPP.EXE
    NUPP lets you temporarily map a drive letter, do some things, then
    restore the mapping to its previous value.

OSVER.EXE
    OSVER allows a batch file to perform operating system platform
    checking. It can differentiate between Windows 95, Windows 98, Windows
    Me, Windows NT 4.0, Windows 2000, Windows XP, and Windows Server 2003.
    For NT-based systems, it can also return the system's service pack
    level and role (e.g. workstation, server, or domain controller). For
    Windows NT 4.0 SP6 and later, it can also detect whether the system is
    a Terminal Server (either remote administration mode or application
    server mode).

RASCONNS.EXE
    RASCONNS allows a batch file to determine if one or more RAS
    connections are active. It can also list active RAS connections and
    determine if a named RAS connection is active.

WINMSG.EXE
    Displays a Windows dialog box with a customizable message, buttons and
    icon. A batch file can detect which button was pressed. You can also
    read the dialog box text from a text file and specify a timeout period.
0
 
LVL 17

Accepted Solution

by:
Wim ten Brink earned 500 total points
ID: 12216378
win95/98/ME isn't really administrator-aware or domain-aware. User management under these operating systems is nearly non-existant and the little bit it does have is basically sloppy patchwork. Forget about these versions if you need security for your application.
From Windows 2000 there's something called Active Directory that you can easily use by importing the type library from C:\WINNT\system32\activeds.tlb which is probably in your %system% folder somewhere. Through Active Directory you have a good access to the user management of your local system and whatever domain the system is part of. It even allows you to examine other systems on the network if you have proper access rights.

You could also use WMI instead to retrieve the information about users. WMI is available on more systems but not always uptodate. To use WMI into Delphi you have to import the type library C:\WINNT\system32\wbem\wbemdisp.tlb and use that one.

The biggest problem is getting information about the current user, though. Still, all you need access to is the SID of the user. Here's the code:

function GetUserSID: PSID;
var
  TokenHandle: THandle;
  ReturnLength: DWORD;
  UserToken: PSIDAndAttributes;
begin
  Result := nil;
  if not OpenProcessToken( GetCurrentProcess, TOKEN_ALL_ACCESS, TokenHandle ) then Exception.Create( 'Failed to open token.' );
  ReturnLength := 0;
  UserToken := nil;
  GetTokenInformation( TokenHandle, Tokenuser, UserToken, 0, ReturnLength );
  GetMem( UserToken, ReturnLength );
  try
    if GetTokenInformation( TokenHandle, Tokenuser, UserToken, ReturnLength, ReturnLength ) then begin
      GetMem( Result, GetLengthSid( UserToken.Sid ) );
      CopySid( GetLengthSid( UserToken.Sid ), Result, UserToken.Sid );
    end;
  finally
    FreeMem( UserToken );
  end;
end;

Now, this SID needs to be used properly. (And freed properly! Use FreeSid() fot freeing the SID once you're done with it.) To get the information, use this method:

function SidToUserInfo(const SID: PSID; out UserName, Domain: WideString; out peUse: SID_NAME_USE): Boolean;
var
  vName, vDomain: array[0..MAX_PATH] of Char;
  cbName, cbDomain: DWORD;
begin
  cbName := SizeOf(vName);
  cbDomain := SizeOf(vDomain);
  if LookupAccountSid(nil, SID, vName, cbName, vDomain, cbDomain, peUse) then begin
    Result := True;
    UserName := string(vName);
    Domain := string(vDomain);
  end
  else begin
    Result := False;
    UserName := SysErrorMessage(GetLastError);
    Domain := '';
    peUse := 0;
  end;
end;

Proper usage would be:

var
  UserName, Domain: WideString;
  peUse: SID_NAME_USE;
  SID: PSID;
begin
  Result := GetComputerName;
  SID := GetUserSID;
  if Assigned(SID) then begin
    if SidToUserInfo(SID, UserName, Domain, peUse) then Result := Domain;
    FreeSid(SID);
  end;
end;

This will provide you the domain name and username of the user that started your process. Still doesn't tell you if the current user is an administrator. Still, you could look him up in WMI or AD. But if you have a SID, you can check if the user is a LOCAL administrator, like this:

function UserIsAdministrator: Boolean;
const
  SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_BUILTIN_DOMAIN_RID = $00000020;
  DOMAIN_ALIAS_RID_ADMINS = $00000220;
var
  hAccessToken: THandle;
  ptgGroups: PTokenGroups;
  InfoBufferSize: DWORD;
  dwInfoBufferSize: DWORD;
  psidAdministrators: PSID;
  I: DWORD;
  TokenOpen: Boolean;
begin
  Result := False;
  // Get a token.
  TokenOpen := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, hAccessToken);
  if (not TokenOpen) and (GetLastError = ERROR_NO_TOKEN) then begin
    TokenOpen := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hAccessToken);
  end;
  if TokenOpen then begin
    // Determine buffer size.
    ptgGroups := nil;
    GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, 0, InfoBufferSize);
    // Allocate memory and retrieve SID.
    GetMem(ptgGroups, InfoBufferSize);
    TokenOpen := GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, InfoBufferSize, dwInfoBufferSize);
    CloseHandle(hAccessToken);
    if TokenOpen then begin
      // Create the administrator SID.
      AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, psidAdministrators);
      {$R-} // No range checking.
      I := 0;
      while (I < ptgGroups.GroupCount) and not EqualSid(psidAdministrators, ptgGroups.Groups[I].Sid) do
        inc(I);
      Result := (I < ptgGroups.GroupCount);
      {$R+}
      FreeSid(psidAdministrators);
    end;
    FreeMem(ptgGroups);
  end;
end;

But again, this code doesn't work on 95/98/ME since they're not aware of any domain, or SID or whatever...
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now