AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi LSALogonUser und Authentifikation (nichts komplexes!)
Thema durchsuchen
Ansicht
Themen-Optionen

LSALogonUser und Authentifikation (nichts komplexes!)

Ein Thema von Dezipaitor · begonnen am 10. Aug 2007 · letzter Beitrag vom 14. Aug 2007
Antwort Antwort
Seite 3 von 4     123 4      
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#21

Re: LSALogonUser und Authentifikation (nichts komplexes!)

  Alt 12. Aug 2007, 21:46
Actually I get this login SID, which is definitly a Session Logon ID :

(S-1-5-5-0-946199)

I translated your source - I hope it correct.

Delphi-Quellcode:
constructor TSecurityToken.CreateWTSQueryUserToken(SessionID : Cardinal {= INVALID_HANDLE_VALUE});
begin
  Self.Create;
  fShared := FALSE;

  if SessionID = INVALID_HANDLE_VALUE then
    SessionID := WtsGetActiveConsoleSessionID;

  fAccessMask := TOKEN_ALL_ACCESS;
  if not WTSQueryUserToken(SessionID, fTokenHandle) then
    raise ESMWinCallFailedException.CreateFmtEx('A call to WTSQueryUserToken failed. ',
                        'WTSQueryUserToken',ClassName,'USM_Token.pas', 0,true,[]);
end;

function GetLogonSID(aToken: TSecurityToken) : TSecurityID;
var i : integer;
    ptg : TSecurityIDList;
begin
  result := nil;
  ptg := aToken.GetTokenGroups;

  // Loop through the groups to find the logon SID.
  for i := 0 to ptg.Count-1 do
  begin
    if (ptg[i].Attributes and SE_GROUP_LOGON_ID) = SE_GROUP_LOGON_ID then
    begin
      // Found the logon SID; make a copy of it.
      result := TSecurityID.Create(ptg[i].CreateCopyOfSID);
      Break;
    end;
  end;
end;
And the code that replaces the old one :

Delphi-Quellcode:
var WTSToken := TSecurityToken;
    aLocalGroups : TSecurityID;
...
    WTSToken := TSecurityToken.CreateWTSQueryUserToken();

    aLocalGroups := TSecurityIDList.Create(true);
    aLogonSid := GetLogonSID(WTSToken);
    ShowMessage('aLogonSid: '+ aLogonSid.GetText(true));


    aLocalGroups.Add(aLogonSid);
    aLocalGroups.Add(TSecurityID.Create('','DebuggerUser'));
    aLocalGroups.Add(AdministratorsSID);
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Benutzerbild von Remko
Remko

Registriert seit: 10. Okt 2006
Ort: 's-Hertogenbosch, Die Niederlande
222 Beiträge
 
RAD-Studio 2010 Arc
 
#22

Re: LSALogonUser und Authentifikation (nichts komplexes!)

  Alt 12. Aug 2007, 21:57
This works for me (adapt username and password to something of your liking):
It uses dialogs to give some debug info when something goes wrong (make service interactive to see the messageboxes), offcourse you can remove these in the final version.
Delphi-Quellcode:
unit uMain;

interface

uses
  Windows, SvcMgr, SysUtils,
  JwaWinType, JwaWinBase, JwaWinNT, JwaNtSecApi, JwaNTStatus,
  JwaNative, JwaUserEnv, JwaWinSta, JwaWtsApi32, Dialogs, uWinStation;
const
  DNLEN = 15;
  UNLEN = 256;

type
  TAuthInfo = record
    Header: MSV1_0_INTERACTIVE_LOGON;
    Domain: array[0..DNLEN] of WideChar;
    User: array[0..UNLEN] of WideChar;
    Password: array[0..UNLEN] of WideChar;
  end;

type
  TService1 = class(TService)
    procedure ServiceStart(Sender: TService; var Started: Boolean);
  private
    { Private declarations }
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;

var
  Service1: TService1;

implementation

{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  Service1.Controller(CtrlCode);
end;

function TService1.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

Procedure LsaInitUnicodeString(Var LsaString: TLsaUnicodeString; Const WS:
  WideString);
Begin
  FillChar(LsaString, SizeOf(LsaString), 0);
  If WS <> 'Then
  Begin
    LsaString.Length:=Length(WS) * SizeOf(WideChar);
    LsaString.MaximumLength:=LsaString.Length + SizeOf(WideChar);
    LsaString.Buffer:=PWideChar(WS);
  End;
End;

procedure GetLogonSID(hToken: THandle; var ppsid: PSID);
var dwLength: DWORD;
    ptg : ^TOKEN_GROUPS;
    i : integer;
begin
  dwLength := 0;
  ptg := nil;

  try
    // Get required buffer size and allocate the TOKEN_GROUPS buffer.
    if not GetTokenInformation(hToken, TokenGroups, ptg, 0, dwLength) then
    begin
      if GetLastError <> ERROR_INSUFFICIENT_BUFFER then
      begin
        ShowMessage('GetTokenInformation failed');
        Exit;
      end;

      ptg := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwLength);
      if ptg = nil then
      begin
        Exit;
      end;

      // Get the token group information from the access token.
      if not GetTokenInformation(hToken, TokenGroups, ptg, dwLength, dwLength) then
      begin
        Exit;
      end;

      // Loop through the groups to find the logon SID.
      for i := 0 to ptg.GroupCount-1 do
      begin
       if ptg.Groups[i].Attributes and SE_GROUP_LOGON_ID = SE_GROUP_LOGON_ID then
       begin
         // Found the logon SID; make a copy of it.
         dwLength := GetLengthSid(ptg.Groups[i].Sid);
         ppsid := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwLength);
         if ppsid = nil then
         begin
           Exit;
         end;
         if not CopySid(dwLength, ppsid, ptg.Groups[i].Sid) then
         begin
// raise exception.Create(Format('CopySid: %s', [SysErrorMessage(GetLastError)]));
           HeapFree(GetProcessHeap, 0, ppsid);
           Exit;
         end;

         Break;
        end;
      end;
    end;
  finally
    // Free the buffer for the token groups.
    if ptg <> nil then
    begin
      HeapFree(GetProcessHeap, 0, ptg);
    end;
  end;
end;


procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
var hToken: THandle;
  si: _STARTUPINFOA;
  pi: _PROCESS_INFORMATION;
  Res: NTSTATUS;
  hLSA: THandle;
  LSAString: _LSA_STRING;
  AuthenticationPackage: ULONG;
  AuthentificationInfo: TAuthInfo;
  pProfileBuffer: Pointer;
  LogonID: _LUID;
  hLsaToken: THandle;
  QuotaLimits: QUOTA_LIMITS;
  SubStatus: Integer;
  wsDomain: WideString;
  wsUser: WideString;
  wsPwd: WideString;
  TokenSource: TOKEN_SOURCE;
  dwReturnLength: DWORD;
  Mode: LSA_OPERATIONAL_MODE;
  pGroups: PTOKEN_GROUPS;
  AdminSid: PSid;
  dwSizeSid: Cardinal;
  dwSizeDomain: Cardinal;
  SidType: TSidNameUse;
  Domain: String;
  MaxGroups: Integer;
  bRes: Longbool;
begin
  ZeroMemory(@si, SizeOf(si));
  si.cb := SizeOf(si);
  si.lpDesktop := nil;

  if WTSQueryUserToken(WtsGetActiveConsoleSessionID, hToken) then
  begin
    RtlInitString(@LsaString, PCSZ(PChar('Winlogon')));
    Res := LsaRegisterLogonProcess(LsaString, hLSA, @Mode);
    if Failed(Res) then
    begin
      ShowMessageFmt('LsaRegisterLogonProcess: %s', [SysErrorMessage(LsaNtStatusToWinError(Res))]);
    end;

    RtlInitString(@LsaString, PCSZ(PChar(MSV1_0_PACKAGE_NAME)));

    Res := LsaLookupAuthenticationPackage(hLSA, LSAString, AuthenticationPackage);
    if Failed(Res) then
    begin
      ShowMessageFmt('LookupAuthPackage: %s', [SysErrorMessage(LsaNtStatusToWinError(Res))]);
    end;

    TokenSource.SourceName := '**ANON**';
    if not AllocateLocallyUniqueId(TokenSource.SourceIdentifier) then
    begin
      ShowMessageFmt('AllocLocUniqueId: %s', [SysErrorMessage(GetLastError)]);
    end;

    // The number of TOKEN_GROUPS we're going to insert
    MaxGroups := 2;

    // Reserve memory for MaxGroups numbur of PTOKEN_GROUPS
    pGroups := PTOKEN_GROUPS(GlobalAlloc(GPTR, sizeof(_SID_AND_ATTRIBUTES) * MaxGroups));
    pGroups^.GroupCount := MaxGroups;

    // Get the Logon Sid and it to the LocalGroups parameter of LsaLogonUser
    // The Logon Sid has the form S-1-5-5-XXXXXXXX-YYYYYYYY
    // We need it to obtain access to the user's desktop
    GetLogonSid(hToken, pGroups^.Groups[0].Sid);
    pGroups^.Groups[0].Attributes := SE_GROUP_MANDATORY or
                                     SE_GROUP_ENABLED or
                                     SE_GROUP_ENABLED_BY_DEFAULT or
                                     SE_GROUP_LOGON_ID;

    // Now get the Administrator's SID
    dwSizeSid := 0;
    dwSizeDomain := 0;
    bRes := LookupAccountName(nil, 'Administrator', nil, dwSizeSid, nil, dwSizeDomain, SidType);

    if (not bRes) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
    begin
      // Reserve memory
      AdminSid := AllocMem(dwSizeSid);
      SetLength(Domain, dwSizeDomain);

      // Lookup Sid from Accountname
      // Assuming that the Admin account has not been renamed!
      bRes := LookUpAccountName(nil, 'Administrator', AdminSid, dwSizeSid, PChar(Domain), dwSizeDomain, SidType);
      if not bRes then
      begin
        // Cleanup
        FreeMem(AdminSid);
        AdminSid := nil;
      end;
    end
    else begin
      RaiseLastOSError;
    end;

    ShowMessageFmt('Administrator Sid: %s, Domain: %s', [SidToStr(AdminSid), Domain]);

    // Add the Administrator's sid to pGroups
    pGroups^.Groups[MaxGroups -1].Sid := AdminSid;
    pGroups^.Groups[MaxGroups -1].Attributes := SE_GROUP_MANDATORY or
                                                SE_GROUP_ENABLED or
                                                SE_GROUP_ENABLED_BY_DEFAULT;

    // Fill the AuthentificationInfo structure
    // First convert the EDITs to WideString
    wsDomain:= '';
    wsUser:= 'username';
    wsPwd:= 'password';

    // Fill with zeros
    RtlZeroMemory(@AuthentificationInfo, sizeof(AuthentificationInfo));
    AuthentificationInfo.Header.MessageType := MsV1_0InteractiveLogon;
    // AuthentificationInfo.Header.MessageType := MsV1_0NetworkLogon;

    // Copy the strings into a buffer.
    RtlCopyMemory(@AuthentificationInfo.Domain, @wsDomain[1], sizeof(WideChar) * Length(wsDomain));
    RtlCopyMemory(@AuthentificationInfo.User, @wsUser[1], sizeof(WideChar) * Length(wsUser));
    RtlCopyMemory(@AuthentificationInfo.Password, @wsPwd[1], sizeof(WideChar) * Length(wsPwd));

    // Now set which buffer we want to use (the arrays of WideChar from the struct)
    RtlInitUnicodeString(@AuthentificationInfo.Header.LogonDomainName, AuthentificationInfo.Domain);
    RtlInitUnicodeString(@AuthentificationInfo.Header.UserName, AuthentificationInfo.User);
    RtlInitUnicodeString(@AuthentificationInfo.Header.Password, AuthentificationInfo.Password);

    Res := LsaLogonUser(hLSA, LsaString, RemoteInteractive,
                        AuthenticationPackage, @AuthentificationInfo,
                        SizeOf(AuthentificationInfo), pGroups, @TokenSource,
                        pProfileBuffer, dwReturnLength, LogonID, hLSAToken,
                        QuotaLimits, SubStatus);

    if Failed(Res) then
    begin
      ShowMessageFmt('LsaLogonUser: %s', [SysErrorMessage(LsaNtStatusToWinError(Res))]);
    end;

    ZeroMemory(@si, SizeOf(si));
    si.cb := SizeOf(si);
    si.lpReserved := nil;
    si.lpDesktop := nil;
    si.dwFlags := STARTF_USESHOWWINDOW;;
    si.wShowWindow := SW_SHOWNORMAL;

    if not CreateProcessAsUser(hLsaToken, nil, PChar('notepad.exe'), nil, nil, False,
                               NORMAL_PRIORITY_CLASS or CREATE_NEW_PROCESS_GROUP,
                               nil, nil, &si, &pi) then
    begin
      ShowMessageFmt('CreateProcessAsUser: %s', [SysErrorMessage(GetLastError)]); end
    else
    begin
    end;

    // Cleanup
    CloseHandle(hToken);
    FreeMem(AdminSid);
    LsaDeregisterLogonProcess(hLSA);
    LsaFreeReturnBuffer(pProfileBuffer);
  end;
  Self.DoStop;
end;

end.
Maybe you'll need unit uWinStation to compile:
Delphi-Quellcode:
unit uWinStation;

interface

uses SysUtils, Dialogs,
     JwaWinType, JwaWinBase, JwaWinNT, JwaNtSecApi, JwaNTStatus, JwaNative,
     JwaWinUser, JwaWinError;

function StartInteractiveClientProcess(const lpszUsername: PAnsiChar; const lpszDomain: PAnsiChar; const lpszPassword: PAnsiChar; const lpCommandLine: PChar): Boolean;
function GetLogonSID(hToken: THandle; var ppsid: PSID): Boolean;
function AddAceToWindowStation(hwinsta: HWINSTA; psid: PSID): Boolean;
function AddAceToDesktop(hdesktop: HDESK; ps: PSID): Boolean;
function SIDToStr (sid : PSID) : string;
procedure StrToSid (const sidName : string; sid : PSid; sidLen : DWORD);

implementation

const
DESKTOP_ALL = DESKTOP_READOBJECTS or DESKTOP_CREATEWINDOW or DESKTOP_CREATEMENU or DESKTOP_HOOKCONTROL or
DESKTOP_JOURNALRECORD or DESKTOP_JOURNALPLAYBACK or DESKTOP_ENUMERATE or DESKTOP_WRITEOBJECTS or
DESKTOP_SWITCHDESKTOP or STANDARD_RIGHTS_REQUIRED;

WINSTA_ALL = WINSTA_ENUMDESKTOPS or WINSTA_READATTRIBUTES or WINSTA_ACCESSCLIPBOARD or WINSTA_CREATEDESKTOP or
WINSTA_WRITEATTRIBUTES or WINSTA_ACCESSGLOBALATOMS or WINSTA_EXITWINDOWS or WINSTA_ENUMERATE or
WINSTA_READSCREEN or STANDARD_RIGHTS_REQUIRED;

GENERIC_ACCESS = GENERIC_READ or GENERIC_WRITE or GENERIC_EXECUTE or GENERIC_ALL;

HEAP_ZERO_MEMORY = 8;
ACL_REVISION = 2;
ACCESS_ALLOWED_ACE_TYPE = 0;
CONTAINER_INHERIT_ACE = 2;
INHERIT_ONLY_ACE = 8;
OBJECT_INHERIT_ACE = 1;
NO_PROPAGATE_INHERIT_ACE = 4;
SE_GROUP_LOGON_ID = $C0000000;

type
ACL_SIZE_INFORMATION = record
AceCount: DWORD;
AclBytesInUse: DWORD;
AclBytesFree: DWORD;
end;

ACE_HEADER = record
AceType: BYTE;
AceFlags: BYTE;
AceSize: WORD;
end;
PACE_HEADER = ^ACE_HEADER;

ACCESS_ALLOWED_ACE = record
Header: ACE_HEADER;
Mask: ACCESS_MASK;
SidStart: DWORD;
end;

function SIDToStr (sid : PSID) : string;
var
  psia : PSIDIdentifierAuthority;
  dwSubAuthorities : DWORD;
  dwSidRev : DWORD;
  dwCounter : DWORD;
begin
  dwSidRev := SID_REVISION;


  if IsValidSid (sid) then
  begin
    psia := GetSidIdentifierAuthority (sid);
    dwSubAuthorities := GetSidSubAuthorityCount (sid)^;


    result := Format ('S-%u-', [dwSidRev]);


    if (psia^.Value[0] <> 0) or (psia^.Value[1] <> 0) then
      result := result + format ('0x%02x%02x%02x%02x%02x%02x',[
                                   psia^.Value [0],
                                   psia^.Value [1],
                                   psia^.Value [2],
                                   psia^.Value [3],
                                   psia^.Value [4],
                                   psia^.Value [5]])
    else
      result := result + format ('%u',
                                 [DWORD (psia^.Value [5]) +
                                  DWORD (psia^.Value [4] shl 8) +
                                  DWORD (psia^.Value [3] shl 16) +
                                  DWORD (psia^.Value [2] shl 24)]);


    for dwCounter := 0 to dwSubAuthorities - 1 do
      result := result + Format ('-%u', [GetSidSubAuthority (sid,
dwCounter)^])
  end
  else
    raise Exception.Create ('Invalid SID');
end;


procedure StrToSid (const sidName : string; sid : PSid; sidLen : DWORD);
var
  ps : PChar;
  pn : PChar;
  p : PChar;
  pa : PChar;
  valueStr : string;
  psia : PSIDIdentifierAuthority;
  i : DWORD;
  d : DWORD;
  authorityCount : DWORD;
begin
(*
typedef struct _SID {
  BYTE  Revision;
  BYTE  SubAuthorityCount;
  SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
#ifdef MIDL_PASS
  [size_is(SubAuthorityCount)] DWORD SubAuthority[*];
#else // MIDL_PASS
  DWORD SubAuthority[ANYSIZE_ARRAY];
*)
 
  if not ((Length (sidName) > 3) and (sidName [1] = 'S') and (sidName [2] =
'-')) then
    raise Exception.Create ('Bad SID');


  if sidLen < sizeof (_SID_IDENTIFIER_AUTHORITY) + 2 then
    raise Exception.Create ('Bad SID');


  ps := PChar (sid);
  pn := PChar (sidName);
  Inc (pn, 2);


  p := StrScan (pn, '-');
  if not Assigned (p) then
    raise Exception.Create ('Bad SID');


  p^ := #0;


  ps^ := char (StrToInt (pn)); // Revision
  Inc (ps);
  pa := ps; // Save authority count position
  Inc (ps);


  pn := p + 1;
  p := StrScan (pn, '-');
  if not Assigned (p) then
    raise Exception.Create ('Bad SID');


  p^ := #0;


  valueStr := pn;


  if Length (valueStr) < 1 then
    raise Exception.Create ('Bad SID');


  psia := PSIDIdentifierAuthority (ps);
  Inc (ps, sizeof (_SID_IDENTIFIER_AUTHORITY));
  Dec (sidLen, 2 + sizeof (_SID_IDENTIFIER_AUTHORITY));
  if valueStr [1] = 'xthen
  begin
    if Length (valueStr) <> 14 then
      raise Exception.Create ('Bad SID');


    psia^.value [0] := StrToInt ('$' + Copy (valueStr, 3, 2));
    psia^.value [1] := StrToInt ('$' + Copy (valueStr, 5, 2));
    psia^.value [2] := StrToInt ('$' + Copy (valueStr, 7, 2));
    psia^.value [3] := StrToInt ('$' + Copy (valueStr, 9, 2));
    psia^.value [4] := StrToInt ('$' + Copy (valueStr, 11, 2));
    psia^.value [5] := StrToInt ('$' + Copy (valueStr, 13, 2))
  end
  else
  begin
    psia^.value [0] := 0;
    psia^.value [1] := 0;
    i := StrToInt (valueStr);


    d := i shl 24;
    psia^.value [2] := d and $ff;


    d := i shl 16;
    psia^.value [3] := d and $ff;


    d := i shl 8;
    psia^.value [4] := d and $ff;
    psia^.value [5] := i and $ff;
  end;


  pn := p + 1;
  authorityCount := 0;
  while lstrlen (pn) > 0 do
  begin
    p := StrScan (pn, '-');
    if Assigned (p) then
    begin
      p^ := #0;
      i := StrToInt (pn);
      pn := p + 1
    end
    else
    begin
      i := StrToInt (pn);
      pn := pn + lstrlen (pn)
    end;


    if sidLen < sizeof (DWORD) then
      raise Exception.Create ('Bad SID');


    PDWORD (ps)^ := i;
    Inc (ps, sizeof (DWORD));
    Dec (sidLen, sizeof (DWORD));
    Inc (authorityCount);
  end;


  pa^ := char (authorityCount);
  if not IsValidSID (sid) then
    raise Exception.Create ('Bad SID');
end;


function AddAceToWindowStation(hwinsta: HWINSTA; psid: PSID): Boolean;
var
si: SECURITY_INFORMATION;
psd, psdNew: PSECURITY_DESCRIPTOR;
dwSidSize, dwSdSizeNeeded, dwNewAclSize: DWORD;
bDaclPresent, bDaclExist: LongBool;
pdacl, pNewAcl: PACL;
aclSizeInfo: ACL_SIZE_INFORMATION;
i: integer;
pTempAce: PACE_HEADER;
pace: ^ACCESS_ALLOWED_ACE;
begin
Result := False;
si := DACL_SECURITY_INFORMATION;
pace := nil;
psd := nil;
dwSidSize := 0;
pNewAcl := nil;
psdNew := nil;
// Obtain the DACL for the window station.

try
if not GetUserObjectSecurity(hwinsta, si, psd, dwSidSize, dwSdSizeNeeded) then begin
if GetLastError = ERROR_INSUFFICIENT_BUFFER then begin
psd := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwSdSizeNeeded);
if psd = nil then
Exit;

psdNew := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwSdSizeNeeded);
if psdNew = nil then
Exit;

dwSidSize := dwSdSizeNeeded;

if not GetUserObjectSecurity(hwinsta, si, psd, dwSidSize, dwSdSizeNeeded) then
Exit;
end
else begin
Exit;
end;
end;

// Create a new DACL.

if not InitializeSecurityDescriptor(psdNew, SECURITY_DESCRIPTOR_REVISION) then
Exit;

// Get the DACL from the security descriptor.

if not GetSecurityDescriptorDacl(psd, bDaclPresent, pdacl, bDaclExist) then
Exit;

// Initialize the ACL.

ZeroMemory(@aclSizeInfo, SizeOf(ACL_SIZE_INFORMATION));
aclSizeInfo.AclBytesInUse := SizeOf(ACL);

// Call only if the DACL is not NULL.

if pdacl <> nil then begin
// get the file ACL size info
if not GetAclInformation(pdacl, @aclSizeInfo, SizeOf(ACL_SIZE_INFORMATION), AclSizeInformation) then
Exit;
end;

// Compute the size of the new ACL.

dwNewAclSize := aclSizeInfo.AclBytesInUse + (2 * SizeOf(ACCESS_ALLOWED_ACE)) + (2 * GetLengthSid(psid)) - (2 * SizeOf(DWORD));

// Allocate memory for the new ACL.

pNewAcl := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwNewAclSize);

if pNewAcl = nil then
Exit;

// Initialize the new DACL.

if not InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION) then
Exit;

// If DACL is present, copy it to a new DACL.

if bDaclPresent then begin
// Copy the ACEs to the new ACL.
if aclSizeInfo.AceCount > 0 then begin
for i := 0 to aclSizeInfo.AceCount - 1 do begin
// Get an ACE.
if not GetAce(pdacl, i, Pointer(pTempAce)) then
Exit;

// Add the ACE to the new ACL.
if not AddAce(pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, pTempAce.AceSize) then
Exit;
end;
end;
end;

// Add the first ACE to the window station.

pace := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, SizeOf(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - SizeOf(DWORD));

if pace = nil then
Exit;

pace.Header.AceType := ACCESS_ALLOWED_ACE_TYPE;
pace.Header.AceFlags := CONTAINER_INHERIT_ACE or INHERIT_ONLY_ACE or OBJECT_INHERIT_ACE;
pace.Header.AceSize := SizeOf(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - SizeOf(DWORD);
pace.Mask := GENERIC_ACCESS;

if not CopySid(GetLengthSid(psid), @pace.SidStart, psid) then
Exit;

if not AddAce(pNewAcl, ACL_REVISION, MAXDWORD, pace, pace.Header.AceSize) then
Exit;

// Add the second ACE to the window station.

pace.Header.AceFlags := NO_PROPAGATE_INHERIT_ACE;
pace.Mask := WINSTA_ALL;

if not AddAce(pNewAcl, ACL_REVISION, MAXDWORD, pace, pace.Header.AceSize) then
Exit;

// Set a new DACL for the security descriptor.

if not SetSecurityDescriptorDacl(psdNew, True, pNewAcl, False) then
Exit;

// Set the new security descriptor for the window station.

if not SetUserObjectSecurity(hwinsta, si, psdNew) then
Exit;

// Indicate success.

Result := True;
finally
// Free the allocated buffers.

if pace <> nil then
HeapFree(GetProcessHeap, 0, pace);

if pNewAcl <> nil then
HeapFree(GetProcessHeap, 0, pNewAcl);

if psd <> nil then
HeapFree(GetProcessHeap, 0, psd);

if psdNew <> nil then
HeapFree(GetProcessHeap, 0, psdNew);
end;
end;

function GetLogonSID(hToken: THandle; var ppsid: PSID): Boolean;
var dwLength: DWORD;
  ptg: ^TOKEN_GROUPS;
  i: integer;
begin
  Result := False;
  dwLength := 0;
  ptg := nil;

  try
    // Verify the parameter passed in is not NULL.
    // if ppsid = nil then
    // Exit;

    // Get required buffer size and allocate the TOKEN_GROUPS buffer.
    if not GetTokenInformation(hToken, TokenGroups, ptg, 0, dwLength) then
    begin
      if GetLastError <> ERROR_INSUFFICIENT_BUFFER then
      begin
        ShowMessage('GetTokenInformation failed');
        Exit;
      end;

      ptg := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwLength);
      if ptg = nil then
      begin
        Exit;
      end;

      // Get the token group information from the access token.

      if not GetTokenInformation(hToken, TokenGroups, ptg, dwLength, dwLength) then
      begin
        Exit;
      end;

      // Loop through the groups to find the logon SID.

      for i := 0 to ptg.GroupCount-1 do
      begin
        if ptg.Groups[i].Attributes and SE_GROUP_LOGON_ID = SE_GROUP_LOGON_ID then
        begin
          // Found the logon SID; make a copy of it.
          dwLength := GetLengthSid(ptg.Groups[i].Sid);
          ppsid := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwLength);
          if ppsid = nil then
          begin
            Exit;
          end;
          if not CopySid(dwLength, ppsid, ptg.Groups[i].Sid) then
          begin
            raise exception.Create(Format('CopySid: %s', [SysErrorMessage(GetLastError)]));
            HeapFree(GetProcessHeap, 0, ppsid);
            Exit;
          end;
          Break;
        end;
      end;
      Result := True;
    end;
  finally
    // Free the buffer for the token groups.
    if ptg <> nil then
    begin
      HeapFree(GetProcessHeap, 0, ptg);
    end;
  end;
end;

function AddAceToDesktop(hdesktop: HDESK; ps: PSID): Boolean;
var
aclSizeInfo: ACL_SIZE_INFORMATION;
bDaclExist, bDaclPresent: LongBool;
dwNewAclSize, dwSidSize, dwSdSizeNeeded: DWORD;
pdacl, pNewAcl: PACL;
psd, psdNew: PSECURITY_DESCRIPTOR;
pTempAce: PACE_HEADER;
si: SECURITY_INFORMATION;
i: integer;
begin
Result := False;
psd := nil;
psdNew := nil;
pNewAcl := nil;
si := DACL_SECURITY_INFORMATION;
dwSidSize := 0;
try
// Obtain the security descriptor for the desktop object.

if not GetUserObjectSecurity(hdesktop, si, psd, dwSidSize, dwSdSizeNeeded) then begin
if GetLastError = ERROR_INSUFFICIENT_BUFFER then begin
psd := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwSdSizeNeeded);
if psd = nil then
Exit;

psdNew := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwSdSizeNeeded);
if psdNew = nil then
Exit;

dwSidSize := dwSdSizeNeeded;

if not GetUserObjectSecurity(hdesktop, si, psd, dwSidSize, dwSdSizeNeeded) then
Exit;
end
else begin
Exit;
end;
end;

// Create a new security descriptor.

if not InitializeSecurityDescriptor(psdNew, SECURITY_DESCRIPTOR_REVISION) then
Exit;

// Obtain the DACL from the security descriptor.

if not GetSecurityDescriptorDacl(psd, bDaclPresent, pdacl, bDaclExist) then
Exit;

// Initialize.

ZeroMemory(@aclSizeInfo, SizeOf(ACL_SIZE_INFORMATION));
aclSizeInfo.AclBytesInUse := SizeOf(ACL);

// Call only if NULL DACL.

if pdacl <> nil then begin
// Determine the size of the ACL information.

if not GetAclInformation(pdacl, @aclSizeInfo, SizeOf(ACL_SIZE_INFORMATION), AclSizeInformation) then
Exit;
end;

// Compute the size of the new ACL.

dwNewAclSize := aclSizeInfo.AclBytesInUse + SizeOf(ACCESS_ALLOWED_ACE) + GetLengthSid(ps) - SizeOf(DWORD);

// Allocate buffer for the new ACL.

pNewAcl := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwNewAclSize);

if pNewAcl = nil then
Exit;

// Initialize the new ACL.

if not InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION) then
Exit;

// If DACL is present, copy it to a new DACL.

if bDaclPresent then begin
// Copy the ACEs to the new ACL.
if aclSizeInfo.AceCount > 0 then begin
for i := 0 to aclSizeInfo.AceCount - 1 do begin
// Get an ACE.
if not GetAce(pdacl, i, Pointer(pTempAce)) then
Exit;

// Add the ACE to the new ACL.
if not AddAce(pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, pTempAce.AceSize) then
Exit;
end;
end;
end;

// Add ACE to the DACL.

if not AddAccessAllowedAce(pNewAcl, ACL_REVISION, DESKTOP_ALL, ps) then
Exit;

// Set new DACL to the new security descriptor.

if not SetSecurityDescriptorDacl(psdNew, True, pNewAcl, False) then
Exit;

// Set the new security descriptor for the desktop object.

if not SetUserObjectSecurity(hdesktop, si, psdNew) then
Exit;

// Indicate success.

Result := True;
finally
// Free buffers.

if pNewAcl <> nil then
HeapFree(GetProcessHeap, 0, pNewAcl);

if psd <> nil then
HeapFree(GetProcessHeap(), 0, psd);

if psdNew <> nil then
HeapFree(GetProcessHeap(), 0, psdNew);
end;
end;

function StartInteractiveClientProcess(const lpszUsername: PAnsiChar; const lpszDomain: PAnsiChar; const lpszPassword: PAnsiChar; const lpCommandLine: PChar): Boolean;
var hToken : THandle;
    hdesktop : HDESK;
    hwinst : HWINSTA;
    hwinstSave: HWINSTA;
    pi : PROCESS_INFORMATION;
    pS : PSID;
    si : STARTUPINFO;
begin
  Result := False;
  hdesktop := 0;
  hwinst := 0;
  hwinstSave := 0;
  pS := nil;

// try
    // Log the client on to the local computer.

// if not LogonUser(lpszUsername, lpszDomain, lpszPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken) then
    if not LogonUser(lpszUsername, lpszDomain, lpszPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, hToken) then
    begin
    ShowMessageFmt('Logonuser failed: %s', [SysErrorMessage(GetLastError)]);
      Result := False;
    // raise exception.create(Format('LogonUser: %s', [SysErrorMessage(GetLastError)]));
      Exit;
    end;
    OutputDebugString(PChar(Format('LogonUser: %s', [SysErrorMessage(GetLastError)])));

    // Save a handle to the caller's current window station.
    hwinstSave := GetProcessWindowStation;
    if hwinstSave = 0 then
    begin
      raise exception.create(Format('GetProcessWindowStation: %s', [SysErrorMessage(GetLastError)]));
      Exit;
    end;
    OutputDebugString(PChar(Format('GetProcessWindowStation: %s', [SysErrorMessage(GetLastError)])));
//\Sessions\2\Windows\WindowStations\WinSta0\Default
    // Get a handle to the interactive window station.
    hwinst := OpenWindowStation('WinSta0', False, READ_CONTROL or WRITE_DAC);
    if hwinst = 0 then
    begin
      raise exception.create(Format('OpenWindowStation: %s', [SysErrorMessage(GetLastError)]));
      Exit;
    end;
    OutputDebugString(PChar(Format('OpenWindowStation: %s', [SysErrorMessage(GetLastError)])));

    // To get the correct default desktop, set the caller's
    // window station to the interactive window station.

    if not SetProcessWindowStation(hwinst) then
    begin
      raise exception.create(Format('SetProcessWindowStation(hwinst): %s', [SysErrorMessage(GetLastError)]));
      Exit;
    end;
    OutputDebugString(PChar(Format('SetProcessWindowStation(hwinst): %s', [SysErrorMessage(GetLastError)])));

    // Get a handle to the interactive desktop.
    hdesktop := OpenDesktop('default', 0, False, READ_CONTROL or WRITE_DAC or DESKTOP_WRITEOBJECTS or DESKTOP_READOBJECTS);
    if hdesktop = 0 then
    begin
      raise exception.create(Format('OpenDesktop: %s', [SysErrorMessage(GetLastError)]));
      Exit;
    end;
    OutputDebugString(PChar(Format('OpenDesktop: %s', [SysErrorMessage(GetLastError)])));

    // Restore the caller's window station.

    if not SetProcessWindowStation(hwinstSave) then
    begin
      raise exception.create(Format('SetProcessWindowStation(hwinstSave): %s', [SysErrorMessage(GetLastError)]));
      Exit;
    end;


    // Get the SID for the client's logon session.
    if not GetLogonSID(hToken, pS) then
    begin
      raise exception.create(Format('GetLogonSID: %s', [SysErrorMessage(GetLastError)]));
      Exit;
    end;

    // Allow logon SID full access to interactive window station.

    if not AddAceToWindowStation(hwinst, pS) then
    begin
      raise exception.create(Format('AddAceToWindowStation: %s', [SysErrorMessage(GetLastError)]));
      Exit;
    end;

    // Allow logon SID full access to interactive desktop.
    if not AddAceToDesktop(hdesktop, pS) then
    begin
      raise exception.create(Format('AddAceToDesktop: %s', [SysErrorMessage(GetLastError)]));
      Exit;
    end;

    // Impersonate client to ensure access to executable file.
    if not ImpersonateLoggedOnUser(hToken) then
    begin
      raise exception.create(Format('ImpersonateLoggedOnUser: %s', [SysErrorMessage(GetLastError)]));
      Exit;
    end;

    // Initialize the STARTUPINFO structure.
    // Specify that the process runs in the interactive desktop.
    ZeroMemory(@si, SizeOf(STARTUPINFO));
    si.cb := SizeOf(STARTUPINFO);
    si.lpDesktop := PChar('Sessions\3\Windows\WindowStations\WinSta0\Default');

    // Launch the process in the client's logon session.
    Result := CreateProcessAsUser(hToken, nil, lpCommandLine, nil, nil, False, // handles are not inheritable
                                  NORMAL_PRIORITY_CLASS or CREATE_NEW_CONSOLE,
                                  nil, nil, si, pi);

    // End impersonation of client.
    RevertToSelf();

    if Result and (pi.hProcess <> INVALID_HANDLE_VALUE) then
    begin
      WaitForSingleObject(pi.hProcess, INFINITE);
      CloseHandle(pi.hProcess);
    end;

    if pi.hThread <> INVALID_HANDLE_VALUE then
    begin
      CloseHandle(pi.hThread);
    end;

    Result := True;

// finally

    if hwinstSave <> 0 then
    begin
      SetProcessWindowStation(hwinstSave);
    end;

    // Free the buffer for the logon SID.

    if pS <> nil then
    begin
      HeapFree(GetProcessHeap, 0, pS);
    end;

    // Close the handles to the interactive window station and desktop.

    if hwinst <> 0 then
    begin
      CloseWindowStation(hwinst);
    end;

    if hdesktop <> 0 then
    begin
      CloseDesktop(hdesktop);
    end;

    // Close the handle to the client's access token.

    if hToken <> INVALID_HANDLE_VALUE then
    begin
      CloseHandle(hToken);
    end;
  end;
//end;

end.
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#23

Re: LSALogonUser und Authentifikation (nichts komplexes!)

  Alt 12. Aug 2007, 22:42
Okay thats great.

I reread your code and found the problem :

I forgot to add the attributes
Delphi-Quellcode:
pGroups^.Groups[0].Attributes := SE_GROUP_MANDATORY or
                                     SE_GROUP_ENABLED or
                                     SE_GROUP_ENABLED_BY_DEFAULT or
                                     SE_GROUP_LOGON_ID;

Delphi-Quellcode:
    aLocalGroups := TSecurityIDList.Create(true);
    aLogonSid := GetLogonSID(WTSToken);
[b]OR[/b]
    aLogonSid := GetLogonSID();
    
    aLocalGroups.Add(aLogonSid);
    aLogonSid.Attributes := SE_GROUP_MANDATORY or
                                     SE_GROUP_ENABLED or
                                     SE_GROUP_ENABLED_BY_DEFAULT or
                                     SE_GROUP_LOGON_ID;

You see both versions of GetLogonSID are working.

Question:
Do I have to set the attributes for the my special debugger user ?
aLocalGroups.Add(TSecurityID.Create('','DebuggerUser')); I get debug privileges but cannot bring the taskmanager to enable "show processes of all users" .
('C:\WINDOWS\system32\taskmgr.exe')


Only this works:
Delphi-Quellcode:
    aSID := AdministratorsSID;
    aLocalGroups.Add(aSID);
    aSID.Attributes := SE_GROUP_MANDATORY or
                                     SE_GROUP_ENABLED or
                                     SE_GROUP_ENABLED_BY_DEFAULT or
                                     SE_GROUP_LOGON_ID;
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Benutzerbild von Remko
Remko

Registriert seit: 10. Okt 2006
Ort: 's-Hertogenbosch, Die Niederlande
222 Beiträge
 
RAD-Studio 2010 Arc
 
#24

Re: LSALogonUser und Authentifikation (nichts komplexes!)

  Alt 12. Aug 2007, 22:49
Just remembered something: GetWtsActiveConsoleSessionID is for XP/2003 and higher. On lower versions the functions doesn't exist and the active console session is always session id 0. If you want to be safe wrap the function and do an OS check and return 0 if NT or 2000.
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#25

Re: LSALogonUser und Authentifikation (nichts komplexes!)

  Alt 13. Aug 2007, 16:44
The WTA function family is one more class to be implemented.
OMG the security library grows and grows and grows and did I mention "grows" ?
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Benutzerbild von Remko
Remko

Registriert seit: 10. Okt 2006
Ort: 's-Hertogenbosch, Die Niederlande
222 Beiträge
 
RAD-Studio 2010 Arc
 
#26

Re: LSALogonUser und Authentifikation (nichts komplexes!)

  Alt 13. Aug 2007, 17:10
LOL
BTW Don't forget to look at my JwaWinSta in that case, it has got some undocumented Terminal Server stuff (shadow sessions, connect to other sessions and obtaining login and idle time for terminal server sessions).
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#27

Re: LSALogonUser und Authentifikation (nichts komplexes!)

  Alt 13. Aug 2007, 18:18
I know your unit - its part of the jedi api lib - I converted it

I developed a desktop class named UDesktop.
I did this also for winstation - but without implementation - only interface section is available (if I could even find it).
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#28

Re: LSALogonUser und Authentifikation (nichts komplexes!)

  Alt 14. Aug 2007, 00:12
Guys, you are notorious! Get a life!
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#29

Re: LSALogonUser und Authentifikation (nichts komplexes!)

  Alt 14. Aug 2007, 00:21
Zitat von Olli:
Guys, you are notorious! Get a life!
And that is saying you who works 25 hours a day ?
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#30

Re: LSALogonUser und Authentifikation (nichts komplexes!)

  Alt 14. Aug 2007, 00:22
Zitat von Dezipaitor:
Zitat von Olli:
Guys, you are notorious! Get a life!
And that is saying you who works 25 hours a day ?
Argh, you got me
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 4     123 4      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:33 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz