Mega Code Archive

 
Categories / Delphi / LAN Web TCP
 

Specifing authentication details & Impersonating a user for use on an Interface(Proxy) call (Client Side)

Title: Specifing authentication details & Impersonating a user for use on an Interface(Proxy) call (Client Side) Question: How to change authentication/authorization setting, and impersonate a user on an interface/proxy call. Answer: What we want to do ----------------------- When it comes to COM and client security, and the authentication level details used on interface call, you can be sure than sooner or later you'll need to specify the authentication information at runtime, or on a specific call to an interface. Usually you set up authentication/authorization/impersonation levels using the Dcomcnfg application provided. How ever, when you require these to be altered or wish to cloak or impersonate an alternate user on calls to a proxy so the server recongnises the alternate user as the callee rather than your natural login account, or the application user account ( i.e service user account). Finding out how.. --------------------- Well to find out how to do this is really not very easy.. very differcult to find examples, people asking how to do it.. people responding where to maybe find out how... msdn is definately the best resourse for information on low level security side of COM and authentication documentation on this subject, but finding full examples which work, or all the syntax/constants/data types that's required is always lacking when it comes to msdn library documentation. So for all those who have been looking for this answer. How it's done. ------------------ There are a few ways to setup this information, you can set it globally to your process using the call CoInitializeSecurity(). But I am going to explain how to use the CoSetProxyBlanket() which can set this information on a specific interface (proxy) which is far more flexible. CoSetProxyBlanket is a wrapper that simply uses the IClientSecurity interface provided by the proxy and calls the SetBlanket method of the interface. I will give you a quick code example of this here and provide you with an attachment which contains all the contants, data types, and a the wrapper function to cater for all the options. Enjoy..... const RPC_C_AUTHN_WINNT = 10; RPC_C_AUTHZ_DEFAULT = $ffffffff; RPC_C_AUTHN_LEVEL_CALL = 3; RPC_C_IMP_LEVEL_IMPERSONATE = 3; EOAC_NONE = $0; type (* The Auth Identity Structure *) PCoAuthIdentity = ^TCoAuthIdentity; _CoAuthIdentity = packed record User : PChar; UserLength : DWORD; Domain : PChar; DomainLength : DWORD; Password : PChar; PasswordLength : DWORD; Flags : DWORD; end; TCoAuthIdentity = _CoAuthIdentity; implementation (* Procedure to demonstrate the use of the CoSetProxyBlanket call and how to use it to impersonate another user when calling an interface. *) procedure SetUserImpersonateOnProxy( Proxy: IUnknown; //-- Interface const UserName, DomainName, Psword: String; //-- User Account AuthenicationService: DWORD = RPC_C_AUTHN_WINNT; AuthorizationService: DWORD = RPC_C_AUTHZ_DEFAULT; AuthenicationLevel: DWORD = RPC_C_AUTHN_LEVEL_CALL; ImpersonationLevel: DWORD = RPC_C_IMP_LEVEL_IMPERSONATE; CapabiltiesFlag: DWORD = EOAC_NONE ); var AuthIdent: TCoAuthIdentity; iResult: Integer; begin (* Populate an Auth Identity structure with the User Account Details *) ZeroMemory(@AuthIdent, 0); with AuthIdent do begin User := pChar(UserName); UserLength := length(UserName); Domain := pChar(DomainName); DomainLength := length(DomainName); Password := pChar(Psword); PasswordLength := length(Psword); Flags := SEC_WINNT_AUTH_IDENTITY_ANSI; end; iResult := CoSetProxyBlanket(Proxy, (* Authentication Service is the service which will be used for authentication i.e WinNT NTLM KERBEROS etc.. this rarely needs to be changed unless Delegation level of impersonation is required and this is only possible with Windows 2000 and Kerberos Authentication Service *) AuthenicationService, AuthorizationService, 0, (* Authentication level should be CALL or PKT as this is the level when authentication will take place.. On each CALL. *) AuthenicationLevel, (* Impersonation Level regards to the servers rights to impersonate as the authenticated user. *) ImpersonationLevel, @AuthIdent, CapabiltiesFlag); case iResult of S_OK: (* Success *) ; E_INVALIDARG : Raise Exception.Create('Invalid Arguments.'); E_OUTOFMEMORY : Raise Exception.Create('Out of Memory'); else Raise Exception.Create('Failed to blanket proxy') end; end; ------------- var Intf: IMyFooServer; begin Intf := CoMyFooServer.Create; try SetUserImpersonateOnProxy(Intf, 'AUser', 'DELPHIDOMAIN', 'FooBar'); (* Interface will authenticate the user AUser as the Callee on each call to the Server. *) Intf.CallMethodAsAUser(Blah); finally Intf := NIL; end; end; -------------- You will find attached the unit shortly. Regards to all, look forward to hearing any comments.