Issue with ASP.NET client, COM Interop, and Identity impersonation

From: Anil Krishnamurthy (akrishnamurthy_at_nospam.air-worldwide.com)
Date: 10/01/04

  • Next message: SteveK: "question about System.String, CString, PCSTR, etc, etc"
    Date: Fri, 1 Oct 2004 16:29:51 -0400
    
    

    We have an ASP.NET application that uses COM objects through Interop. The
    web application requires access to network and database resources and hence,
    needs to impersonate a domain account. The problem is that even when it is
    configured to run under a certain identity through Web.config, the
    impersonation is not carried through to COM library. Consequently, the code
    in COM object runs under a local account and any code that needs to access
    network will not work correctly.

    ASP.NET
    {Web app} -------------Interop --------------->{COM Library}
    (Domain\NetworkUser)
    (LocalHost\IUSR_MachineName)

    We tried to solve the problem by impersonating the caller in COM library.
    Instead of using CoImpersonateClient(), which is required for every method,
    we tried using a different approach so that impersonation is in effect
    beyond function call. It was implemented as follows:

    HRESULT CClientImpersonator::Impersonate()
    {
        BOOL bOk = FALSE;
        HRESULT hr = E_FAIL;
        DWORD dwErr = 0;

        // try to impersonate the client
        hr = ::CoImpersonateClient();
        if ( SUCCEEDED( hr ) )
        {
            HANDLE hToken = NULL;
            HANDLE hDupToken = NULL;

            // get the thread's impersonation token
            bOk = ::OpenThreadToken( ::GetCurrentThread(), TOKEN_ALL_ACCESS,
    TRUE, &hToken );
            if ( TRUE == bOk )
            {
                // dup it
                bOk = ::DuplicateTokenEx( hToken, TOKEN_ALL_ACCESS, NULL,
    SecurityImpersonation, TokenImpersonation, &hDupToken );
                if ( TRUE == bOk )
                {
                    // switch back the identity
                    hr = ::CoRevertToSelf();
                    if ( SUCCEEDED(hr) )
                    {
                        // now impersonate the same identity so it 'sticks'
    beyond function call level
                        bOk = ::ImpersonateLoggedOnUser( hDupToken );
                        if ( FALSE == bOk )
                        {
                            hr = HRESULT_FROM_WIN32( ::GetLastError() );
                            ATLTRACE( "ImpersonateLoggedOnUser() failed.
    GetLastError() returned %8x.\n", hr );
                        }
                    }
                    else
                    {
                        ATLTRACE( "CoRevertToSelf() failed. Error code %8x.\n",
    hr );
                    }
                }
                else
                {
                    hr = HRESULT_FROM_WIN32( ::GetLastError() );
                    ATLTRACE( "DuplicateTokenEx() failed. GetLastError()
    returned %8x.\n", hr );
                }
            }
            else
            {
                hr = HRESULT_FROM_WIN32( ::GetLastError() );
                ATLTRACE( "OpenThreadToken() failed. GetLastError() returned
    %8x.\n", hr );
            }

            ::CloseHandle( hDupToken );
            ::CloseHandle( hToken );
        }
        else
        {
            if ( hr != RPC_E_CALL_COMPLETE )
                ATLTRACE( "CoImpersonateClient() failed. Error code: %8x.\n",
    hr );
            else
                hr = S_FALSE; // ignore the failure when the context is not
    available
        }
        return hr;
    }

    Unfortunately, the solution does not seem to work on all machines. In cases
    where it does not work, the behavior is as follows: Instantiation of COM
    object succeeds but attempt to invoke any method or access any property on
    the same object fails. The error is reported as
    "System.InvalidCastException. QueryInterface for interface <Interface name>
    failed"

    Any ideas?

    Thanks


  • Next message: SteveK: "question about System.String, CString, PCSTR, etc, etc"

    Relevant Pages


    Loading