Calling CoInitializeSecurity in a Secure Manner

IIS does not make secure calls to remote computers. If your program implements IMSAdminBaseSink and is executing on a computer other than the computer on which IIS is running, you must set security by calling the COM CoInitializeSecurity function with the dwImpLevel parameter set to RPC_C_AUTHN_LEVEL_NONE.

The CoInitializeSecurity function registers and sets the default security values for the processes that run your application. This function is called exactly once per process, either explicitly or implicitly. It can be called by the client, the server, or both.

The dwImpLevel parameter of CoInitializeSecurity is the default impersonation level. By default, all IUnknown calls are made with this impersonation level, so even security-aware applications should set impersonation levels carefully. The value of the dwImpLevel parameter applies when the process is started by the client. Outgoing calls from the client always use this impersonation level because impersonation is not negotiated. However, incoming calls to the client can be made at any impersonation level.

Example Code

The following example shows you how to use the C++ programming language to call CoInitializeSecurity in a secure manner so that an ABO application can register an event sink for a remote IIS server.

HRESULT 
InitComSecurity(VOID) 
{ 
  HRESULT       hr = NOERROR; 
  DWORD         dwErr; 
  BOOL        fRet; 
  SECURITY_DESCRIPTOR SecurityDesc = {0}; 
  EXPLICIT_ACCESS   ea = {0}; 
  ACL         *pAcl = NULL; 
  PSID        pSidAdmins = NULL; 
  PSID        pSidAuthUser = NULL; 

  // Initialize the security descriptor. 
  fRet = InitializeSecurityDescriptor( &SecurityDesc, SECURITY_DESCRIPTOR_REVISION ); 
  if ( !fRet ) 
  { 
    dwErr = GetLastError(); 
    hr = HRESULT_FROM_WIN32( dwErr ); 
    goto exit; 
  } 

  // Create SID for AuthenticatedUsers. 
  hr = AllocateAndCreateWellKnownSid( WinAuthenticatedUserSid, &pSidAuthUser ); 
  if ( FAILED( hr ) ) 
  { 
    goto exit; 
  } 

  // Create SID for Administrators. 
  hr = AllocateAndCreateWellKnownSid( WinBuiltinAdministratorsSid, &pSidAdmins ); 
  if ( FAILED( hr ) ) 
  { 
    goto exit; 
  } 

  // Setup AuthenticatedUsers for COM access. 
  ea.grfAccessPermissions = COM_RIGHTS_EXECUTE; 
  ea.grfAccessMode = SET_ACCESS; 
  ea.grfInheritance = NO_INHERITANCE; 
  ea.Trustee.pMultipleTrustee = NULL; 
  ea.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 
  ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; 
  ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP; 
  ea.Trustee.ptstrName = (LPSTR)pSidAuthUser; 

  // Create new ACL with this ACE. 
  dwErr = SetEntriesInAcl( 1, &ea, NULL, &pAcl ); 
  if ( dwErr != ERROR_SUCCESS ) 
  { 
    hr = HRESULT_FROM_WIN32( dwErr ); 
    goto exit; 
  } 

  // Set the security descriptor owner to Administrators. 
  fRet = SetSecurityDescriptorOwner( &SecurityDesc, pSidAdmins, FALSE); 
  if ( !fRet ) 
  { 
    dwErr = GetLastError(); 
    hr = HRESULT_FROM_WIN32( dwErr ); 
    goto exit; 
  } 

  // Set the security descriptor group to Administrators. 
  fRet = SetSecurityDescriptorGroup( &SecurityDesc, pSidAdmins, FALSE); 
  if ( !fRet ) 
  { 
    dwErr = GetLastError(); 
    hr = HRESULT_FROM_WIN32( dwErr ); 
    goto exit; 
  } 

  // Set the ACL to the security descriptor. 
  fRet = SetSecurityDescriptorDacl( &SecurityDesc, TRUE, pAcl, FALSE ); 
  if ( !fRet ) 
  { 
    dwErr = GetLastError(); 
    hr = HRESULT_FROM_WIN32( dwErr ); 
    goto exit; 
  } 

  hr = CoInitializeSecurity( &SecurityDesc, 
      -1, 
      NULL, 
      NULL, 
      RPC_C_AUTHN_LEVEL_PKT_PRIVACY, 
      RPC_C_IMP_LEVEL_IDENTIFY, 
      NULL, 
      EOAC_DYNAMIC_CLOAKING | EOAC_DISABLE_AAA | EOAC_NO_CUSTOM_MARSHAL, 
      NULL ); 

exit: 
  if ( pSidAdmins != NULL ) 
  { 
    LocalFree( pSidAdmins ); 
    pSidAdmins = NULL; 
  } 
  if ( pSidAuthUser != NULL ) 
  { 
    LocalFree( pSidAuthUser ); 
    pSidAuthUser = NULL; 
  } 
  if ( pAcl != NULL ) 
  { 
    LocalFree( pAcl ); 
    pAcl = NULL; 
  } 

  return (hr); 
}

See Also