Может быть много причин, по которым Вы, вероятно, должны выполнить приложение от имени другого пользователя. Вот несколько вариантов для осуществления этого:
Вариант 1. function ValidateUserLogonAPI(const UserName : string; const Domain : string; const PassWord : string) : boolean; var Retvar : boolean; LHandle : THandle; begin Retvar := LogonUser(PChar(UserName), PChar(Domain),PChar(PassWord), LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, LHandle); if Retvar then CloseHandle(LHandle); Result := Retvar; end; Однако в Windows NT и 2000 этот вызов может закончиться с ошибкой "INSUFFICIENT_PRIVILEGES", т.к. процесс, вызывающий LogonUser, должен иметь привилегию SE_TCB_NAME (в управлении правами это называется "Act as part of the Operating System"). В Windows XP, в SE_TCB_NAME для вызова LogonUser уже нет необходимости. Вариант 2. (Более грамотный вариант на основе 1-го для выполнения только определенного кусочка программного кода под другим пользователем) var hToken: Cardinal; function PerformLogon(const User, Domain, Password: String): Cardinal; begin if NOT LogonUser(pChar(User), pChar(Domain), pChar(Password), LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, Result) then RaiseLastWin32Error; end; begin hToken := PerformLogon('Chris','DelphiDomain','MyPassword'); try ImpersonateLoggedOnUser(hToken); try (* Perform tasks as User. *) finally RevertToSelf; end; finally CloseHandle(hToken); end; end; Примечание (англ.): LogonUser is only passing you an impersonation token, and not a primary token in this instance. You can use the api calls DuplicateTokenEx, or CreateProcessAsUser which can help with creating Primary Tokens... Вариант 3. (Использование Security Support Provider Interface (SSPI) для "network style logon") Этот метод не требует специальных привилегий, однако при его использовании Вы не получите доступ к удаленным ресурсам под указанным пользователем. unit ValLogonW2000; interface uses Windows; // Prototype function LogonUserSSPI(const UserName,Domain,Password : string) : boolean; // ------------------------------------------------------------------------- implementation type // Secur32.dll function prototypes TQueryPackageInfo = function(PackageName : PChar; var PackageInfo : pointer) : integer; stdcall; TFreeContextBuffer = function(pBuffer : pointer) : integer; stdcall; TFreeCredentialsHandle = function(var hCred : Int64) : integer; stdcall; TDeleteSecurityContext = function(var hCred : Int64) : integer; stdcall; TAcquireCredentialsHandle = function(pszPrincipal : PChar; pszPackage : PChar; fCredentialUse : DWORD; pvLogonID : DWORD; pAuthData : pointer; pGetKeyFn : DWORD; pvGetKeyArgument : pointer; var phCredential : Int64; var ptsExpiry : DWORD) : integer; stdcall; TInitializeSecurityContext = function(var phCredential : Int64; phContext : pointer; pszTargetName : PChar; fContextReq : DWORD; Reserved1 : DWORD; TargetDataRep : DWORD; pInput : pointer; Reserved2 : DWORD; var phNewContext : Int64; pOutput : pointer; var pfContextAttr : Int64; var ptsExpiry : DWORD) : integer; stdcall; TAcceptSecurityContext = function(var phCredential : Int64; phContext : pointer; pInput : pointer; fContextReq : DWORD; TargetDataRep : DWORD; var phNewContext : Int64; pOutput : pointer; var pfContextAttr : Int64; var ptsExpiry : DWORD) : integer; stdcall; // AcquireCredentialsHandle() Internal Structure PAuthIdentity = ^TAuthIdentity; TAuthIdentity = packed record User : PChar; UserLength : DWORD; Domain : PChar; DomainLength : DWORD; Password : PChar; PasswordLength : DWORD; Flags : DWORD; end; // QuerySecurityPackageInfo Internal Structure PSecPkgInfo = ^TSecPkgInfo; TSecPkgInfo = packed record Capabilities : DWORD; Version : WORD; RPCID : WORD; MaxToken : DWORD; Name : PChar; Comment : PChar; end; // InitializeSecurityContext() Internal structure PSecBuffer = ^TSecBuffer; TSecBuffer = packed record cbBuffer : DWORD; BufferType : DWORD; pvBuffer : pointer; end; PSecBuffDesc = ^TSecBuffDesc; TSecBuffDesc = packed record ulVersion : DWORD; cBuffers : DWORD; pBuffers : PSecBuffer; end; function LogonUserSSPI(const UserName,Domain,Password : string) : boolean; var Retvar : boolean; FSecHandle : THandle; AuthIdentity : TAuthIdentity; pIdentity : PAuthIdentity; ContextAttr, hcTxt2,hCred2, hcTxt,hCred : Int64; pBuffer : pointer; E : integer; MaxToken, LifeTime : DWORD; InSecBuff,InSecBuff2, OutSecBuff,OutSecBuff2 : TSecBuffer; InBuffDesc,InBuffDesc2, OutBuffDesc,OutBuffDesc2 : TSecBuffDesc; pOut,pOut2, pBuffDesc,pBuffDesc2 : pointer; FQueryPackageInfo : TQueryPackageInfo; FFreeContextBuffer : TFreeContextBuffer; FAcquireCredHandle : TAcquireCredentialsHandle; FFreeCredHandle : TFreeCredentialsHandle; FInitSecContext : TInitializeSecurityContext; FDelSecContext : TDeleteSecurityContext; FAcceptSecContext : TAcceptSecurityContext; begin Retvar := false; FSecHandle := LoadLibrary('SECUR32.DLL'); FQueryPackageInfo := nil; FFreeContextBuffer := nil; FAcquireCredHandle := nil; FFreeCredHandle := nil; FInitSecContext := nil; FDelSecContext := nil; FAcceptSecContext := nil; if FSecHandle <> 0 then begin @FQueryPackageInfo := GetProcAddress(FSecHandle,'QuerySecurityPackageInfoA'); @FFreeContextBuffer := GetProcAddress(FSecHandle,'FreeContextBuffer'); @FAcquireCredHandle := GetProcAddress(FSecHandle,'AcquireCredentialsHandleA'); @FInitSecContext := GetProcAddress(FSecHandle,'InitializeSecurityContextA'); @FFreeCredHandle := GetProcAddress(FSecHandle,'FreeCredentialsHandle'); @FDelSecContext := GetProcAddress(FSecHandle,'DeleteSecurityContext'); @FAcceptSecContext := GetProcAddress(FSecHandle,'AcceptSecurityContext'); end; if FSecHandle <> 0 then begin AuthIdentity.User := PChar(UserName); AuthIdentity.UserLength := length(UserName); AuthIdentity.Domain := PChar(Domain); AuthIdentity.DomainLength := length(Domain); AuthIdentity.Password := PChar(Password); AuthIdentity.PasswordLength := length(Password); AuthIdentity.Flags := 1; // SEC_WINNT_AUTH_IDENTITY_ANSI pIdentity := @AuthIdentity; if FQueryPackageInfo('NTLM',pBuffer) = NO_ERROR then begin MaxToken := PSecPkgInfo(pBuffer).MaxToken; FFreeContextBuffer(pBuffer); // Negotiate Client Initialisation if FAcquireCredHandle(nil,'NTLM',2,0,pIdentity,0, nil,hCred,LifeTime) = NO_ERROR then begin pOut := HeapAlloc(GetProcessHeap,8,MaxToken); pOut2 := HeapAlloc(GetProcessHeap,8,MaxToken); OutSecBuff.pvBuffer := pOut; OutSecBuff.cbBuffer := MaxToken; OutSecBuff.BufferType := 2; // SEC_BUFFER_TOKEN OutBuffDesc.ulVersion := 0; OutBuffDesc.cBuffers := 1; OutBuffDesc.pBuffers := @OutSecBuff; pBuffDesc := @OutBuffDesc; E := FInitSecContext(hCred,nil,'AuthSamp',0,0,16,nil,0, hcTxt,pBuffDesc,ContextAttr,LifeTime); // Challenge if (E >= 0) and (FAcquireCredHandle(nil,'NTLM',1,0,nil,0, nil,hCred2,LifeTime) = NO_ERROR) then begin InSecBuff2.cbBuffer := OutSecBuff.cbBuffer; InSecBuff2.pvBuffer := OutSecBuff.pvBuffer; InSecBuff2.BufferType := 2; // SEC_BUFFER_TOKEN InBuffDesc2.ulVersion := 0; InBuffDesc2.cBuffers := 1; InBuffDesc2.pBuffers := @InSecBuff2; OutSecBuff2.cbBuffer := MaxToken; OutSecBuff2.pvBuffer := pOut2; OutSecBuff2.BufferType := 2; // SEC_BUFFER_TOKEN OutBuffDesc2.ulVersion := 0; OutBuffDesc2.cBuffers := 1; OutBuffDesc2.pBuffers := @OutSecBuff2; pBuffDesc := @InBuffDesc2; pBuffDesc2 := @OutBuffDesc2; E := FAcceptSecContext(hCred2,nil,pBuffDesc,0,16,hcTxt2,pBuffDesc2, ContextAttr,LifeTime); if E >= 0 then begin // Authenticate InSecBuff.cbBuffer := OutSecBuff2.cbBuffer; InSecBuff.pvBuffer := OutSecBuff2.pvBuffer; InSecBuff.BufferType := 2; InBuffDesc.ulVersion := 0; InBuffDesc.cBuffers := 1; InBuffDesc.pBuffers := @InSecBuff; OutSecBuff.cbBuffer := MaxToken; pBuffDesc := @InBuffDesc; pBuffDesc2 := @OutBuffDesc; E := FInitSecContext(hCred,@hcTxt,'AuthSamp',0,0,16,pBuffDesc,0, hcTxt,pBuffDesc2,ContextAttr,LifeTime); if E >= 0 then begin InSecBuff2.cbBuffer := OutSecBuff.cbBuffer; InSecBuff2.pvBuffer := OutSecBuff.pvBuffer; OutSecBuff2.cbBuffer := MaxToken; pBuffDesc := @InBuffDesc2; pBuffDesc2 := @OutBuffDesc2; E := FAcceptSecContext(hCred2, @hcTxt2, pBuffDesc, 0,16,hcTxt2, pBuffDesc2, ContextAttr,LifeTime); Retvar := (E >= 0); end; end; FDelSecContext(hcTxt2); FFreeCredHandle(hCred2); end; FDelSecContext(hcTxt); FFreeCredHandle(hCred); HeapFree(GetProcessHeap,0,pOut); HeapFree(GetProcessHeap,0,pOut2); end; end; end; if FSecHandle <> 0 then try FreeLibrary(FSecHandle); except end; Result := Retvar; end; end. |