views:

78

answers:

1

I'm trying to create a WCF service to expose a some services. In one of contracts I have to impersonate to another user and call a COM object. I know that if I want to propagate impersonation into COM object I should call CoInitializaSecurity before any marshaling.

int result = CoInitializeSecurity(IntPtr.Zero, -1,
 IntPtr.Zero, IntPtr.Zero,
            RpcAuthnLevel.Connect, RpcImpLevel.Impersonate,
            IntPtr.Zero, EoAuthnCap.DynamicCloaking, IntPtr.Zero);

but it returns 80010119 which means RPC_E_TOO_LATE.

I know that it means CoInitializeSecurity has been already called. But I want to call this function as first instruction in my contract. I've tried calling CoInitializeSecurity even in constructor of service but it returns same error. It means WCF built in codes contains CoInitializeSecurity and I can't run this function again.

I want to call a com object and I want to make com object to work with impersonated user in C# but if I'm nut successful in calling CoInitializeSecurity it means COM object will not run by impersonated user.


Just added after answer by @Remus Rusanu

I've created a service contract like following

   [OperationBehavior(Impersonation = ImpersonationOption.Required)]
    public string GetData()
    {
        MyComClass comObj = new MyComClass();
        string ComUser = comObj.GetLogOnUser();
        return System.Security.Principal.WindowsIdentity.GetCurrent().Name + " " + ComUser;
    }

and in client I called this service by desired credentials

    ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
    client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
    client.ClientCredentials.Windows.ClientCredential.Domain = "Domain";
    client.ClientCredentials.Windows.ClientCredential.UserName = "DomainUser";
    client.ClientCredentials.Windows.ClientCredential.Password = "passw0rd";
    string str = client.GetData();

the result is

DOMAIN\DomainUser DOMAIN\CurrentUser

Which means WCF has impersonated to DomainUser but inside of COM object is still working with previous user.

+1  A: 

The managed hosting is initializing COM for you already. You do not have to re-initialize the thread COM security. Simply impersonate in the WCF (eg. via [OperationBehavior(Impersonation=ImpersonationOption.Required)]) and make the COM object instantiation, it will occur under an impersonated context. Not that if the COM object is remote then constrained delegation occurs and your WCF host process has to be configured for constrained delegation.

See How to: Impersonate a Client on a Service, Delegation and Impersonation with WCF and Enabling Delegated Authentication

Remus Rusanu
Thanks for your response. I haven't tried this yet but as far as I can remember I have to impersonate to a specific user by <identity impersonate="true ... />. but what if I want to pass username and password from WCF client?
Ahmadreza
You impersonate the caller of your WCF service. If you want to impersonate a different user then you have to `LogonUser` that credntials (see the sample at http://msdn.microsoft.com/en-us/library/chf6fbt4.aspx) and then make your COM object instantiation. But impersonating a user/password is a bad practice in general, a good design should use either the caller's credentials, either the service credentials, but never explicit credentials because pf password storage issues.
Remus Rusanu
Actually I've updated question based on your suggestion but COM object doesn't get information from caller. I've experienced this in console application and by calling CoInitializeSecurity It works. But unfortunately in this case I can't call CoInitializeSecurity again.
Ahmadreza
By declaring `ImpersonationOption.NotAllowed` you are doing exactly the opposite of what you declared you need to do: you are explicitly *ignoring* the client supplied credentials.
Remus Rusanu
Copy paste mistake! fixed. Actual code was written by ImpersonationOption.Required parameter.
Ahmadreza
Is the COM server in-proc local or out-of-proc remote?
Remus Rusanu
And what apartment model? The impersonation token does not flow between threads, and incompatible apartments use threads to host the COM object.
Remus Rusanu