windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/wam/object/ooptoken.cpp
2020-09-26 16:20:57 +08:00

437 lines
10 KiB
C++

/*++
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 <isapip.hxx>
#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;
}