/*++ Copyright (c) 1999 Microsoft Corporation Module Name : ooptoken.cpp Abstract: Implementation of the CWamOopTokenInfo object Author: Taylor Weiss ( TaylorW ) 15-Feb-1999 Environment: User Mode - Win32 Project: iis\svcs\wam\object --*/ #include #include "ooptoken.h" /************************ CWamOopTokenInfo ****************************/ CWamOopTokenInfo * CWamOopTokenInfo::ms_pInstance = NULL; HRESULT CWamOopTokenInfo::Create( VOID ) /*++ Routine Description: Create and initialize ms_pInstance. Get the wam and system SIDs. The IWAM_* user sid is obtained from the process token. This only works if we are running OOP. The alternative is to put this in w3svc or infocomm and get the SID from the metabase. The downside to that is the account for the application package is exposed through the com+ UI, so it can be changed without a metabase update. Parameters Return Value HRESULT --*/ { DBG_ASSERT( CWamOopTokenInfo::ms_pInstance == NULL ); HRESULT hr = NOERROR; HANDLE hProcessToken = NULL; LPVOID pvUserBuffer = NULL; PSID pSidSys = NULL; CWamOopTokenInfo * pInstance = NULL; do { BOOL fNoError = FALSE; DWORD cbUserBuffer = 0; // Allocate instance pInstance = new CWamOopTokenInfo(); DBG_ASSERT( pInstance != NULL ); if( !pInstance ) { DBG_ASSERT( pInstance ); hr = E_OUTOFMEMORY; break; } // // Get a SID for the IWAM_* user. // fNoError = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hProcessToken ); if( !fNoError ) { DBG_ASSERT( fNoError ); hr = HRESULT_FROM_WIN32( GetLastError() ); break; } // Get buffer size fNoError = GetTokenInformation( hProcessToken, TokenUser, NULL, 0, &cbUserBuffer ); DBG_ASSERT( fNoError == FALSE ); pvUserBuffer = LocalAlloc( LPTR, cbUserBuffer ); DBG_ASSERT( pvUserBuffer != NULL ); if( !pvUserBuffer ) { DBG_ASSERT( pvUserBuffer ); hr = E_OUTOFMEMORY; break; } // Get user info fNoError = GetTokenInformation( hProcessToken, TokenUser, pvUserBuffer, cbUserBuffer, &cbUserBuffer ); if( !fNoError ) { DBG_ASSERT( fNoError ); hr = HRESULT_FROM_WIN32( GetLastError() ); break; } hr = pInstance->SetIWAMUserSid( ((TOKEN_USER *)pvUserBuffer)->User.Sid ); if( FAILED(hr) ) break; // // Create a SID for the local system // SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; fNoError = AllocateAndInitializeSid( &siaNtAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSidSys ); if( !fNoError ) { DBG_ASSERT( fNoError ); hr = HRESULT_FROM_WIN32( GetLastError() ); break; } hr = pInstance->SetSystemSid( pSidSys ); if( FAILED(hr) ) break; CWamOopTokenInfo::ms_pInstance = pInstance; } while( FALSE ); if( hProcessToken ) { CloseHandle( hProcessToken ); } if( pvUserBuffer ) { LocalFree( pvUserBuffer ); } if( pSidSys ) { FreeSid( pSidSys ); } if( CWamOopTokenInfo::ms_pInstance == NULL ) { // We hit some break, need to dealloc local pointer delete pInstance; } DBG_ASSERT( CWamOopTokenInfo::ms_pInstance != NULL ); DBG_ASSERT( SUCCEEDED(hr) ); return hr; } HRESULT CWamOopTokenInfo::SetIWAMUserSid( PSID pSid ) /*++ Routine Description: Make a local copy of the SID. Called during instance create. Probably should avoid the extra duplication. Parameters pSid - The IWAM_* user sid. Return Value HRESULT --*/ { DBG_ASSERT( pSid ); DBG_ASSERT( m_pIWAMUserSid == NULL ); DBG_ASSERT( m_cbIWAMUserSid == 0 ); HRESULT hr = NOERROR; m_cbIWAMUserSid = GetLengthSid( pSid ); m_pIWAMUserSid = LocalAlloc( LPTR, m_cbIWAMUserSid ); if( m_pIWAMUserSid ) { if( !CopySid( m_cbIWAMUserSid, m_pIWAMUserSid, pSid ) ) { hr = HRESULT_FROM_WIN32( GetLastError() ); } } else { hr = E_OUTOFMEMORY; m_cbIWAMUserSid = 0; } DBG_ASSERT( m_pIWAMUserSid ); DBG_ASSERT( m_cbIWAMUserSid > 0 ); DBG_ASSERT( SUCCEEDED(hr) ); return hr; } HRESULT CWamOopTokenInfo::SetSystemSid( PSID pSid ) /*++ Routine Description: Make a local copy of the SID. Called during instance create. Probably should avoid the extra duplication. Parameters pSid - The system sid. Return Value HRESULT --*/ { DBG_ASSERT( pSid ); DBG_ASSERT( m_pSystemSid == NULL ); DBG_ASSERT( m_cbSystemSid == 0 ); HRESULT hr = NOERROR; m_cbSystemSid = GetLengthSid( pSid ); m_pSystemSid = LocalAlloc( LPTR, m_cbSystemSid ); if( m_pSystemSid ) { if( !CopySid( m_cbSystemSid, m_pSystemSid, pSid ) ) { hr = HRESULT_FROM_WIN32( GetLastError() ); } } else { hr = E_OUTOFMEMORY; m_cbSystemSid = 0; } DBG_ASSERT( m_pSystemSid ); DBG_ASSERT( m_cbSystemSid > 0 ); DBG_ASSERT( SUCCEEDED(hr) ); return hr; } HRESULT CWamOopTokenInfo::ModifyTokenForOop ( HANDLE hThreadToken ) /*++ Routine Description Add the IWAM_* ace to the token. Prameters HANDLE hThreadToken - The token to modify. Return Value HRESULT --*/ { DBG_ASSERT( m_pIWAMUserSid ); DBG_ASSERT( m_pSystemSid ); HRESULT hr = NOERROR; DWORD cbTokenUserBuffer = 0; LPVOID pvTokenUserBuffer = NULL; DWORD cbNewAcl = 0; PACL pNewAcl = NULL; do { BOOL bRet; // // Get the User SID from the token // // Get buffer size bRet = GetTokenInformation( hThreadToken, TokenUser, NULL, 0, &cbTokenUserBuffer ); DBG_ASSERT( bRet == FALSE ); pvTokenUserBuffer = LocalAlloc( LPTR, cbTokenUserBuffer ); if( !pvTokenUserBuffer ) { DBG_ASSERT( pvTokenUserBuffer ); hr = E_OUTOFMEMORY; break; } // Get TokenUser bRet = GetTokenInformation( hThreadToken, TokenUser, pvTokenUserBuffer, cbTokenUserBuffer, &cbTokenUserBuffer ); if( !bRet ) { DBG_ASSERT( bRet ); hr = HRESULT_FROM_WIN32( GetLastError() ); break; } PSID pSidUser = ((TOKEN_USER *)pvTokenUserBuffer)->User.Sid; DBG_ASSERT( pSidUser ); // // Allocate and init our new ACL // cbNewAcl = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSidUser) - sizeof(DWORD) + sizeof(ACCESS_ALLOWED_ACE) + m_cbSystemSid - sizeof(DWORD) + sizeof(ACCESS_ALLOWED_ACE) + m_cbIWAMUserSid - sizeof(DWORD); pNewAcl = (PACL)LocalAlloc( LPTR, cbNewAcl ); if( !pNewAcl ) { DBG_ASSERT( pNewAcl ); hr = E_OUTOFMEMORY; break; } bRet = InitializeAcl( pNewAcl, cbNewAcl, ACL_REVISION ); if( !bRet ) { DBG_ASSERT( bRet ); hr = HRESULT_FROM_WIN32( GetLastError() ); break; } // // Add the aces // bRet = AddAccessAllowedAce( pNewAcl, ACL_REVISION, GENERIC_ALL | STANDARD_RIGHTS_ALL, pSidUser ); if( !bRet ) { DBG_ASSERT( bRet ); hr = HRESULT_FROM_WIN32( GetLastError() ); break; } bRet = AddAccessAllowedAce( pNewAcl, ACL_REVISION, GENERIC_ALL | STANDARD_RIGHTS_ALL, m_pSystemSid ); if( !bRet ) { DBG_ASSERT( bRet ); hr = HRESULT_FROM_WIN32( GetLastError() ); break; } bRet = AddAccessAllowedAce( pNewAcl, ACL_REVISION, GENERIC_ALL | STANDARD_RIGHTS_ALL, m_pIWAMUserSid ); if( !bRet ) { DBG_ASSERT( bRet ); hr = HRESULT_FROM_WIN32( GetLastError() ); break; } // Blast the new DACL into our token TOKEN_DEFAULT_DACL tddNew; tddNew.DefaultDacl = pNewAcl; bRet = SetTokenInformation( hThreadToken, TokenDefaultDacl, &tddNew, cbNewAcl ); if( !bRet ) { DBG_ASSERT( bRet ); hr = HRESULT_FROM_WIN32( GetLastError() ); break; } }while(FALSE); if( pvTokenUserBuffer ) { LocalFree( pvTokenUserBuffer ); } if( pNewAcl ) { LocalFree( pNewAcl ); } DBG_ASSERT( SUCCEEDED(hr) ); return hr; }