Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1043 lines
36 KiB

#include "stdafx.h"
#include <ole2.h>
#include <aclapi.h>
#include "iadmw.h"
#include "iiscnfg.h"
#include "log.h"
#include "mdkey.h"
#include "dcomperm.h"
#include "other.h"
#include "mdacl.h"
#include <sddl.h> // ConvertSidToStringSid
extern int g_GlobalDebugCrypto;
#ifndef _CHICAGO_
BOOL CleanAdminACL(SECURITY_DESCRIPTOR *pSD)
{
// iisDebugOut((LOG_TYPE_TRACE, _T("CleanAdminACL(): Start.\n")));
BOOL fSetData = FALSE;
BOOL b= FALSE, bDaclPresent = FALSE, bDaclDefaulted = FALSE;;
PACL pDacl = NULL;
LPVOID pAce = NULL;
int i = 0;
ACE_HEADER *pAceHeader;
ACCESS_MASK dwOldMask, dwNewMask, dwExtraMask, dwMask;
dwMask = (MD_ACR_READ |
MD_ACR_WRITE |
MD_ACR_RESTRICTED_WRITE |
MD_ACR_UNSECURE_PROPS_READ |
MD_ACR_ENUM_KEYS |
MD_ACR_WRITE_DAC);
b = GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pDacl, &bDaclDefaulted);
if (NULL == pDacl)
{
return FALSE;
}
if (b) {
//iisDebugOut((LOG_TYPE_TRACE, _T("CleanAdminACL:ACE count: %d\n"), (int)pDacl->AceCount));
for (i=0; i<(int)pDacl->AceCount; i++) {
b = GetAce(pDacl, i, &pAce);
if (b) {
pAceHeader = (ACE_HEADER *)pAce;
switch (pAceHeader->AceType) {
case ACCESS_ALLOWED_ACE_TYPE:
dwOldMask = ((ACCESS_ALLOWED_ACE *)pAce)->Mask;
dwExtraMask = dwOldMask & (~dwMask);
if (dwExtraMask) {
fSetData = TRUE;
dwNewMask = dwOldMask & dwMask;
((ACCESS_ALLOWED_ACE *)pAce)->Mask = dwNewMask;
}
break;
case ACCESS_DENIED_ACE_TYPE:
dwOldMask = ((ACCESS_DENIED_ACE *)pAce)->Mask;
dwExtraMask = dwOldMask & (~dwMask);
if (dwExtraMask) {
fSetData = TRUE;
dwNewMask = dwOldMask & dwMask;
((ACCESS_DENIED_ACE *)pAce)->Mask = dwNewMask;
}
break;
case SYSTEM_AUDIT_ACE_TYPE:
dwOldMask = ((SYSTEM_AUDIT_ACE *)pAce)->Mask;
dwExtraMask = dwOldMask & (~dwMask);
if (dwExtraMask) {
fSetData = TRUE;
dwNewMask = dwOldMask & dwMask;
((SYSTEM_AUDIT_ACE *)pAce)->Mask = dwNewMask;
}
break;
default:
break;
}
} else {
//iisDebugOut((LOG_TYPE_TRACE, _T("CleanAdminACL:GetAce:err=%x\n"), GetLastError()));
}
}
} else {
//iisDebugOut((LOG_TYPE_TRACE, _T("CleanAdminACL:GetSecurityDescriptorDacl:err=%x\n"), GetLastError()));
}
//iisDebugOut_End(_T("CleanAdminACL"),LOG_TYPE_TRACE);
return (fSetData);
}
void FixAdminACL(LPTSTR szKeyPath)
{
// iisDebugOutSafeParams((LOG_TYPE_TRACE, _T("FixAdminACL Path=%1!s!. Start.\n"), szKeyPath));
BOOL bFound = FALSE, b = FALSE;
DWORD attr, uType, dType, cbLen;
CMDKey cmdKey;
BUFFER bufData;
CString csName, csValue;
PBYTE pData;
int BufSize;
SECURITY_DESCRIPTOR *pSD;
cmdKey.OpenNode(szKeyPath);
if ( (METADATA_HANDLE)cmdKey )
{
pData = (PBYTE)(bufData.QueryPtr());
BufSize = bufData.QuerySize();
cbLen = 0;
bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
if (!bFound && (cbLen > 0))
{
if ( ! (bufData.Resize(cbLen)) )
{
cmdKey.Close();
return; // insufficient memory
}
else
{
pData = (PBYTE)(bufData.QueryPtr());
BufSize = cbLen;
cbLen = 0;
bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
}
}
cmdKey.Close();
if (bFound && (dType == BINARY_METADATA))
{
pSD = (SECURITY_DESCRIPTOR *)pData;
b = CleanAdminACL(pSD);
if (b)
{
// need to reset the data
DWORD dwLength = GetSecurityDescriptorLength(pSD);
cmdKey.OpenNode(szKeyPath);
if ( (METADATA_HANDLE)cmdKey )
{
cmdKey.SetData(MD_ADMIN_ACL,METADATA_INHERIT | METADATA_REFERENCE | METADATA_SECURE,IIS_MD_UT_SERVER,BINARY_METADATA,dwLength,(LPBYTE)pSD);
cmdKey.Close();
}
}
}
}
//iisDebugOut_End1(_T("FixAdminACL"),szKeyPath,LOG_TYPE_TRACE);
return;
}
#endif //_CHICAGO_
#ifndef _CHICAGO_
DWORD SetAdminACL(LPCTSTR szKeyPath, DWORD dwAccessForEveryoneAccount)
{
iisDebugOut_Start1(_T("SetAdminACL"), szKeyPath, LOG_TYPE_TRACE);
int iErr=0;
DWORD dwErr=0;
DWORD dwRetCode = ERROR_SUCCESS;
BOOL b = FALSE;
DWORD dwLength = 0;
PSECURITY_DESCRIPTOR pSD = NULL;
PSECURITY_DESCRIPTOR outpSD = NULL;
DWORD cboutpSD = 0;
PACL pACLNew = NULL;
DWORD cbACL = 0;
PSID pAdminsSID = NULL, pEveryoneSID = NULL;
BOOL bWellKnownSID = FALSE;
// Initialize a new security descriptor
pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (!pSD)
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:LocalAlloc FAILED.out of memory. GetLastError()= 0x%x\n"), ERROR_NOT_ENOUGH_MEMORY));
dwRetCode = ERROR_OUTOFMEMORY;
goto Cleanup;
}
iErr = InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
if (iErr == 0)
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:InitializeSecurityDescriptor FAILED. GetLastError()= 0x%x\n"), GetLastError() ));
dwRetCode = GetLastError() != ERROR_SUCCESS ? GetLastError() : ERROR_OUTOFMEMORY;
goto Cleanup;
}
// Get Local Admins Sid
dwErr = GetPrincipalSID (_T("Administrators"), &pAdminsSID, &bWellKnownSID);
if (dwErr != ERROR_SUCCESS)
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:GetPrincipalSID(Administrators) FAILED. Return Code = 0x%x\n"), dwErr));
dwRetCode = dwErr;
goto Cleanup;
}
// Get everyone Sid
dwErr = GetPrincipalSID (_T("Everyone"), &pEveryoneSID, &bWellKnownSID);
if (dwErr != ERROR_SUCCESS)
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:GetPrincipalSID(Everyone) FAILED. Return Code = 0x%x\n"), dwErr));
dwRetCode = dwErr;
goto Cleanup;
}
// Calculate the length needed for the ACL
cbACL = sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pAdminsSID) - sizeof(DWORD));
if ( dwAccessForEveryoneAccount != 0x00 )
{
// Add room for everyone ACL
cbACL += sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pEveryoneSID) - sizeof(DWORD);
}
pACLNew = (PACL) LocalAlloc(LPTR, cbACL);
if ( !pACLNew )
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:pACLNew LocalAlloc(LPTR, FAILED. size = %u GetLastError()= 0x%x\n"), cbACL, GetLastError()));
dwRetCode = ERROR_OUTOFMEMORY;
goto Cleanup;
}
if (!InitializeAcl(pACLNew, cbACL, ACL_REVISION))
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:InitializeAcl FAILED. GetLastError()= 0x%x\n"), GetLastError));
dwRetCode = GetLastError() != ERROR_SUCCESS ? GetLastError() : ERROR_OUTOFMEMORY;
goto Cleanup;
}
if (!AddAccessAllowedAce(pACLNew,ACL_REVISION,(MD_ACR_READ |MD_ACR_WRITE |MD_ACR_RESTRICTED_WRITE |MD_ACR_UNSECURE_PROPS_READ |MD_ACR_ENUM_KEYS |MD_ACR_WRITE_DAC),pAdminsSID))
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:AddAccessAllowedAce(pAdminsSID) FAILED. GetLastError()= 0x%x\n"), GetLastError));
dwRetCode = GetLastError() != ERROR_SUCCESS ? GetLastError() : ERROR_OUTOFMEMORY;
goto Cleanup;
}
if ( dwAccessForEveryoneAccount != 0x00 )
{
if (!AddAccessAllowedAce(pACLNew,ACL_REVISION,dwAccessForEveryoneAccount,pEveryoneSID))
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:AddAccessAllowedAce(pEveryoneSID) FAILED. GetLastError()= 0x%x\n"), GetLastError()));
dwRetCode = GetLastError() != ERROR_SUCCESS ? GetLastError() : ERROR_OUTOFMEMORY;
goto Cleanup;
}
}
// Add the ACL to the security descriptor
b = SetSecurityDescriptorDacl(pSD, TRUE, pACLNew, FALSE);
if (!b)
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:SetSecurityDescriptorDacl(pACLNew) FAILED. GetLastError()= 0x%x\n"), GetLastError()));
dwRetCode = GetLastError() != ERROR_SUCCESS ? GetLastError() : ERROR_OUTOFMEMORY;
goto Cleanup;
}
b = SetSecurityDescriptorOwner(pSD, pAdminsSID, TRUE);
if (!b)
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:SetSecurityDescriptorOwner(pAdminsSID) FAILED. GetLastError()= 0x%x\n"), GetLastError()));
dwRetCode = GetLastError() != ERROR_SUCCESS ? GetLastError() : ERROR_OUTOFMEMORY;
goto Cleanup;
}
b = SetSecurityDescriptorGroup(pSD, pAdminsSID, TRUE);
if (!b)
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:SetSecurityDescriptorGroup(pAdminsSID) FAILED. GetLastError()= 0x%x\n"), GetLastError()));
dwRetCode = GetLastError() != ERROR_SUCCESS ? GetLastError() : ERROR_OUTOFMEMORY;
goto Cleanup;
}
// Security descriptor blob must be self relative
b = MakeSelfRelativeSD(pSD, outpSD, &cboutpSD);
outpSD = (PSECURITY_DESCRIPTOR)GlobalAlloc(GPTR, cboutpSD);
if ( !outpSD )
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:GlobalAlloc FAILED. cboutpSD = %u GetLastError()= 0x%x\n"), cboutpSD, GetLastError()));
dwRetCode = ERROR_OUTOFMEMORY;
goto Cleanup;
}
b = MakeSelfRelativeSD( pSD, outpSD, &cboutpSD );
if (!b)
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:MakeSelfRelativeSD() FAILED. cboutpSD = %u GetLastError()= 0x%x\n"),cboutpSD, GetLastError()));
dwRetCode = GetLastError() != ERROR_SUCCESS ? GetLastError() : ERROR_OUTOFMEMORY;
goto Cleanup;
}
if (outpSD)
{
if (IsValidSecurityDescriptor(outpSD))
{
// Apply the new security descriptor to the metabase
iisDebugOut_Start(_T("SetAdminACL:Write the new security descriptor to the Metabase"),LOG_TYPE_TRACE);
iisDebugOut((LOG_TYPE_TRACE, _T("SetAdminACL: At this point we have already been able to write basic entries to the metabase, so...")));
iisDebugOut((LOG_TYPE_TRACE, _T("SetAdminACL: If this has a problem then there is a problem with setting up encryption for the metabase (Crypto).")));
//DoesAdminACLExist(szKeyPath);
if (g_GlobalDebugCrypto == 2)
{
// if we want to call this over and over...
do
{
dwRetCode = WriteSDtoMetaBase(outpSD, szKeyPath);
if (FAILED(dwRetCode))
{
OutputDebugString(_T("\nCalling WriteSDtoMetaBase again...Set iis!g_GlobalDebugCrypto to 0 to stop looping on failure."));
OutputDebugString(_T("\nSet iis!g_GlobalDebugCrypto to 0 to stop looping on crypto failure.\n"));
}
} while (FAILED(dwRetCode) && g_GlobalDebugCrypto == 2);
}
else
{
dwRetCode = WriteSDtoMetaBase(outpSD, szKeyPath);
}
//DoesAdminACLExist(szKeyPath);
iisDebugOut_End(_T("SetAdminACL:Write the new security descriptor to the Metabase"),LOG_TYPE_TRACE);
}
else
{
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:IsValidSecurityDescriptor.4.SelfRelative(%u) FAILED!"),outpSD));
}
}
if (outpSD){GlobalFree(outpSD);outpSD=NULL;}
Cleanup:
// both of Administrators and Everyone are well-known SIDs, use FreeSid() to free them.
if (pAdminsSID){FreeSid(pAdminsSID);}
if (pEveryoneSID){FreeSid(pEveryoneSID);}
if (pSD){LocalFree((HLOCAL) pSD);}
if (pACLNew){LocalFree((HLOCAL) pACLNew);}
iisDebugOut_End1(_T("SetAdminACL"),szKeyPath,LOG_TYPE_TRACE);
return (dwRetCode);
}
DWORD SetAdminACL_wrap(LPCTSTR szKeyPath, DWORD dwAccessForEveryoneAccount, BOOL bDisplayMsgOnErrFlag)
{
int bFinishedFlag = FALSE;
UINT iMsg = NULL;
DWORD dwReturn = ERROR_SUCCESS;
LogHeapState(FALSE, __FILE__, __LINE__);
do
{
dwReturn = SetAdminACL(szKeyPath, dwAccessForEveryoneAccount);
LogHeapState(FALSE, __FILE__, __LINE__);
if (FAILED(dwReturn))
{
if (bDisplayMsgOnErrFlag == TRUE)
{
iMsg = MyMessageBox( NULL, IDS_RETRY, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND );
switch ( iMsg )
{
case IDIGNORE:
dwReturn = ERROR_SUCCESS;
goto SetAdminACL_wrap_Exit;
case IDABORT:
dwReturn = ERROR_OPERATION_ABORTED;
goto SetAdminACL_wrap_Exit;
case IDRETRY:
break;
default:
break;
}
}
else
{
// return whatever err happened
goto SetAdminACL_wrap_Exit;
}
}
else
{
break;
}
} while ( FAILED(dwReturn) );
SetAdminACL_wrap_Exit:
return dwReturn;
}
#endif
#ifndef _CHICAGO_
DWORD WriteSDtoMetaBase(PSECURITY_DESCRIPTOR outpSD, LPCTSTR szKeyPath)
{
iisDebugOut_Start(_T("WriteSDtoMetaBase"), LOG_TYPE_TRACE);
DWORD dwReturn = ERROR_ACCESS_DENIED;
DWORD dwLength = 0;
DWORD dwMDFlags = 0;
CMDKey cmdKey;
HRESULT hReturn = E_FAIL;
int iSavedFlag = 0;
dwMDFlags = METADATA_INHERIT | METADATA_REFERENCE | METADATA_SECURE,IIS_MD_UT_SERVER,BINARY_METADATA;
iSavedFlag = g_GlobalDebugCrypto;
if (!outpSD)
{
dwReturn = ERROR_INVALID_SECURITY_DESCR;
goto WriteSDtoMetaBase_Exit;
}
// Apply the new security descriptor to the metabase
dwLength = GetSecurityDescriptorLength(outpSD);
// open the metabase
// stick it into the metabase. warning those hoses a lot because
// it uses encryption. rsabase.dll
// Check for special debug flag in metabase to break right before this call!
if (g_GlobalDebugCrypto != 0)
{
// special flag to say... hey "stop setup so that the crypto team can debug they're stuff"
iisDebugOut((LOG_TYPE_TRACE, _T("Breakpoint enabled thru setup (to debug crypto api). look at debugoutput.")));
OutputDebugString(_T("\n\nBreakpoint enabled thru setup (to debug crypto api)"));
OutputDebugString(_T("\n1.in this process:"));
OutputDebugString(_T("\n set breakpoint on admwprox!IcpGetContainerHelper"));
OutputDebugString(_T("\n set breakpoint on advapi32!CryptAcquireContextW"));
OutputDebugString(_T("\n IcpGetKeyHelper will call CryptAcquireContext and try to open an existing key container,"));
OutputDebugString(_T("\n if it doesn't exist it will return NTE_BAD_KEYSET, and IcpGetContainerHelper will try to create the container."));
OutputDebugString(_T("\n2.in the inetinfo process:"));
OutputDebugString(_T("\n set breakpoint on admwprox!IcpGetContainerHelper"));
OutputDebugString(_T("\n set breakpoint on advapi32!CryptAcquireContextW\n"));
}
hReturn = cmdKey.CreateNode(METADATA_MASTER_ROOT_HANDLE, szKeyPath);
if ( (METADATA_HANDLE)cmdKey )
{
TCHAR szErrorString[50];
iisDebugOut((LOG_TYPE_TRACE, _T("WriteSDtoMetaBase:cmdKey():SetData(MD_ADMIN_ACL), dwdata = %d; outpSD = %x, Start\n"), dwLength, (DWORD_PTR) outpSD ));
if (g_GlobalDebugCrypto != 0)
{
OutputDebugString(_T("\nCalling SetData....\n"));
DebugBreak();
}
dwReturn = cmdKey.SetData(MD_ADMIN_ACL,dwMDFlags,IIS_MD_UT_SERVER,BINARY_METADATA,dwLength,(LPBYTE)outpSD);
if (FAILED(dwReturn))
{
iisDebugOut((LOG_TYPE_ERROR, _T("WriteSDtoMetaBase:cmdKey():SetData(MD_ADMIN_ACL), FAILED. Code=0x%x.End.\n"), dwReturn));
if (g_GlobalDebugCrypto != 0)
{
_stprintf(szErrorString, _T("\r\nSetData Failed. code=0x%x\r\n\r\n"), dwReturn);
OutputDebugString(szErrorString);
}
}
else
{
dwReturn = ERROR_SUCCESS;
iisDebugOut((LOG_TYPE_TRACE, _T("WriteSDtoMetaBase:cmdKey():SetData(MD_ADMIN_ACL), Success.End.\n")));
if (g_GlobalDebugCrypto != 0)
{
_stprintf(szErrorString, _T("\r\nSetData Succeeded. code=0x%x\r\n\r\n"), dwReturn);
OutputDebugString(szErrorString);
}
}
cmdKey.Close();
}
else
{
dwReturn = hReturn;
}
WriteSDtoMetaBase_Exit:
g_GlobalDebugCrypto = iSavedFlag;
iisDebugOut((LOG_TYPE_TRACE, _T("WriteSDtoMetaBase:End. Return=0x%x"), dwReturn));
return dwReturn;
}
DWORD WriteSessiontoMetaBase(LPCTSTR szKeyPath)
{
iisDebugOut_Start(_T("WriteSessiontoMetaBase"), LOG_TYPE_TRACE);
DWORD dwReturn = ERROR_ACCESS_DENIED;
CMDKey cmdKey;
HRESULT hReturn = E_FAIL;
hReturn = cmdKey.CreateNode(METADATA_MASTER_ROOT_HANDLE, szKeyPath);
if ( (METADATA_HANDLE)cmdKey )
{
dwReturn = cmdKey.SetData(9999,METADATA_NO_ATTRIBUTES,IIS_MD_UT_SERVER,BINARY_METADATA,0,(LPBYTE)"");
if (FAILED(dwReturn))
{
iisDebugOut((LOG_TYPE_ERROR, _T("WriteSessiontoMetaBase:cmdKey():SetData(), FAILED. Code=0x%x.End.\n"), dwReturn));
}
else
{
dwReturn = ERROR_SUCCESS;
iisDebugOut((LOG_TYPE_TRACE, _T("WriteSessiontoMetaBase:cmdKey():SetData(), Success.End.\n")));
}
cmdKey.Close();
}
else
{
dwReturn = hReturn;
}
iisDebugOut((LOG_TYPE_TRACE, _T("WriteSessiontoMetaBase:End. Return=0x%x"), dwReturn));
return dwReturn;
}
#endif
//----------------------------------------------------------------------------
// Test if the given account name is an account on the local machine or not.
//----------------------------------------------------------------------------
BOOL IsLocalAccount(LPCTSTR pAccnt, DWORD *dwErr )
{
BOOL fIsLocalAccount = FALSE;
CString csDomain, csComputer;
DWORD cbDomain = 0;
PSID pSid = NULL;
DWORD cbSid = 0;
SID_NAME_USE snu;
// get the computer name
cbDomain = _MAX_PATH;
GetComputerName(
csComputer.GetBuffer( cbDomain ), // address of name buffer
&cbDomain // address of size of name buffer
);
csComputer.ReleaseBuffer();
cbDomain = 0;
// have security look up the account name and get the domain name. We dont' care about
// the other stuff it can return, so pass in nulls
BOOL fLookup = LookupAccountName(
NULL, // address of string for system name
pAccnt, // address of string for account name
NULL, // address of security identifier
&cbSid, // address of size of security identifier
NULL,// address of string for referenced domain
&cbDomain, // address of size of domain string
&snu // address of SID-type indicator
);
// check the error - it should be insufficient buffer
*dwErr = GetLastError();
if (*dwErr != ERROR_INSUFFICIENT_BUFFER)
return FALSE;
// allocate the sid
pSid = (PSID) malloc (cbSid);
if (!pSid )
{
*dwErr = GetLastError();
return FALSE;
}
// do the real lookup
fLookup = LookupAccountName (NULL,pAccnt,pSid,&cbSid,csDomain.GetBuffer(cbDomain+2),&cbDomain,&snu);
csDomain.ReleaseBuffer();
// free the pSid we allocated above and set the final error code
*dwErr = GetLastError();
free( pSid );
pSid = NULL;
// compare the domain to the machine name, if it is the same, then set the sub auth
if ( fLookup && (csDomain.CompareNoCase(csComputer) == 0) )
fIsLocalAccount = TRUE;
// return the answer
return fIsLocalAccount;
}
// pDomainUserName can be one of the following:
//
// domainname\username <-- this function returns true
// computername\username <-- this function returns false
// username <-- this function returns false
//
int IsDomainSpecifiedOtherThanLocalMachine(LPCTSTR pDomainUserName)
{
int iReturn = TRUE;
TCHAR szTempDomainUserName[_MAX_PATH];
iisDebugOut_Start1(_T("IsDomainSpecifiedOtherThanLocalMachine"),pDomainUserName);
CString csComputer;
DWORD cbDomain = 0;
// Make a copy to be sure not to move the pointer around.
_tcscpy(szTempDomainUserName, pDomainUserName);
// Check if there is a "\" in there.
LPTSTR pch = NULL;
pch = _tcschr(szTempDomainUserName, _T('\\'));
if (!pch)
{
// no '\' found so, they must be specifying only the username, return false
iReturn = FALSE;
goto IsDomainSpecifiedOtherThanLocalMachine_Exit;
}
// We have at least a '\' in there, so set default return to true.
// let's check if the name is the local computername!
// get the computer name
cbDomain = _MAX_PATH;
if (0 == GetComputerName(csComputer.GetBuffer( cbDomain ),&cbDomain) )
{
// failed to get computername so, let's bail
iReturn = TRUE;
csComputer.ReleaseBuffer();
goto IsDomainSpecifiedOtherThanLocalMachine_Exit;
}
csComputer.ReleaseBuffer();
cbDomain = 0;
// trim off the '\' character to leave just the domain\computername so we can check against it.
*pch = _T('\0');
// Compare the domainname with the computername
// if they match then it's the local system account.
iReturn = TRUE;
iisDebugOut((LOG_TYPE_TRACE, _T("IsDomainSpecifiedOtherThanLocalMachine(): %s -- %s.\n"), szTempDomainUserName, csComputer));
if ( 0 == csComputer.CompareNoCase(szTempDomainUserName) )
{
// The domain name and the computername are the same.
// it is the same place.
iReturn = FALSE;
}
IsDomainSpecifiedOtherThanLocalMachine_Exit:
iisDebugOut((LOG_TYPE_TRACE, _T("IsDomainSpecifiedOtherThanLocalMachine():%s.End.Ret=%d.\n"), pDomainUserName,iReturn));
return iReturn;
}
#ifndef _CHICAGO_
void DumpAdminACL(HANDLE hFile,PSECURITY_DESCRIPTOR pSD)
{
BOOL b= FALSE, bDaclPresent = FALSE, bDaclDefaulted = FALSE;;
PACL pDacl = NULL;
ACCESS_ALLOWED_ACE* pAce;
iisDebugOut((LOG_TYPE_TRACE, _T("DumpAdminACL:Start\n")));
b = GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pDacl, &bDaclDefaulted);
if (NULL == pDacl)
{
iisDebugOut((LOG_TYPE_TRACE, _T("DumpAdminACL:No Security.\n")));
return;
}
if (b)
{
iisDebugOut((LOG_TYPE_TRACE, _T("DumpAdminACL:ACE count: %d\n"), (int)pDacl->AceCount));
// get dacl length
DWORD cbDacl = pDacl->AclSize;
// now check if SID's ACE is there
for (int i = 0; i < pDacl->AceCount; i++)
{
if (!GetAce(pDacl, i, (LPVOID *) &pAce))
{
iisDebugOut((LOG_TYPE_TRACE, _T("DumpAdminACL:GetAce failed with 0x%x\n"),GetLastError()));
}
if (IsValidSid( (PSID) &(pAce->SidStart) ) )
{
LPTSTR pszSid;
LPCTSTR ServerName = NULL; // local machine
DWORD cbName = UNLEN+1;
TCHAR ReferencedDomainName[200];
DWORD cbReferencedDomainName = sizeof(ReferencedDomainName);
SID_NAME_USE sidNameUse = SidTypeUser;
TCHAR szUserName[UNLEN + 1];
// dump out the sid in string format
if (ConvertSidToStringSid( (PSID) &(pAce->SidStart) , &pszSid))
{
_tcscpy(szUserName, _T("(unknown...)"));
if (LookupAccountSid(ServerName, (PSID) &(pAce->SidStart), szUserName, &cbName, ReferencedDomainName, &cbReferencedDomainName, &sidNameUse))
{
// Get the rights for this user.
// pAce->Mask
DWORD dwBytesWritten = 0;
TCHAR szBuf[UNLEN+1 + 20 + 20];
memset(szBuf, 0, _tcslen(szBuf) * sizeof(TCHAR));
/*
typedef struct _ACCESS_ALLOWED_ACE {
ACE_HEADER Header;
ACCESS_MASK Mask;
ULONG SidStart;
} ACCESS_ALLOWED_ACE;
typedef struct _ACE_HEADER {
UCHAR AceType;
UCHAR AceFlags;
USHORT AceSize;
} ACE_HEADER;
typedef ACE_HEADER *PACE_HEADER;
typedef ULONG ACCESS_MASK;
*/
_stprintf(szBuf, _T("%s,%s,0x%x,0x%x,0x%x,0x%x\r\n"),
szUserName,
pszSid,
pAce->Header.AceType,
pAce->Header.AceFlags,
pAce->Header.AceSize,
pAce->Mask
);
if (hFile != NULL && hFile != INVALID_HANDLE_VALUE)
{
if (WriteFile(hFile, szBuf, _tcslen(szBuf) * sizeof(TCHAR), &dwBytesWritten, NULL ) == FALSE )
{iisDebugOut((LOG_TYPE_WARN, _T("WriteFile Failed=0x%x.\n"), GetLastError()));}
}
else
{
// echo to logfile
iisDebugOut((LOG_TYPE_TRACE, _T("DumpAdminACL:Sid[%i]=%s,%s,0x%x,0x%x,0x%x,0x%x\n"),i,
pszSid,
szUserName,
pAce->Header.AceType,
pAce->Header.AceFlags,
pAce->Header.AceSize,
pAce->Mask
));
}
}
else
{
iisDebugOut((LOG_TYPE_TRACE, _T("DumpAdminACL:Sid[%i]=%s='%s'\n"),i,pszSid,szUserName));
}
LocalFree(LocalHandle(pszSid));
}
}
else
{
iisDebugOut((LOG_TYPE_TRACE, _T("DumpAdminACL:IsVAlidSid failed with 0x%x\n"),GetLastError()));
}
}
}
iisDebugOut((LOG_TYPE_TRACE, _T("DumpAdminACL:End\n")));
return;
}
#endif
DWORD MDDumpAdminACL(CString csKeyPath)
{
DWORD dwReturn = ERROR_ACCESS_DENIED;
BOOL bFound = FALSE;
DWORD attr, uType, dType, cbLen;
CMDKey cmdKey;
BUFFER bufData;
PBYTE pData;
int BufSize;
PSECURITY_DESCRIPTOR pOldSd = NULL;
cmdKey.OpenNode(csKeyPath);
if ( (METADATA_HANDLE) cmdKey )
{
pData = (PBYTE)(bufData.QueryPtr());
BufSize = bufData.QuerySize();
cbLen = 0;
bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
if (!bFound)
{
if (cbLen > 0)
{
if ( ! (bufData.Resize(cbLen)) )
{
iisDebugOut((LOG_TYPE_ERROR, _T("MDDumpAdminACL(): cmdKey.GetData. failed to resize to %d.!\n"), cbLen));
}
else
{
pData = (PBYTE)(bufData.QueryPtr());
BufSize = cbLen;
cbLen = 0;
bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
}
}
}
cmdKey.Close();
if (bFound)
{
// dump out the info
// We've got the acl
pOldSd = (PSECURITY_DESCRIPTOR) pData;
if (IsValidSecurityDescriptor(pOldSd))
{
#ifndef _CHICAGO_
DumpAdminACL(INVALID_HANDLE_VALUE,pOldSd);
dwReturn = ERROR_SUCCESS;
#endif
}
}
else
{
dwReturn = ERROR_PATH_NOT_FOUND;
}
}
return dwReturn;
}
// function: AddUserToMetabaseACL_Rec
//
// Add a user to a metabase acl recursively. This will add them
// directly to the location you specify, and then to any other
// location that is a child of it, that has an ACL set
//
DWORD AddUserToMetabaseACL_Rec(CString csKeyPath, LPTSTR szUserToAdd, DWORD dwAccessMask )
{
CMDKey cmdKey;
DWORD dwRet;
CStringList AclList;
POSITION pos;
CString csPath;
CString csFullPath;
CString csNewPath;
dwRet = AddUserToMetabaseACL( csKeyPath, szUserToAdd, dwAccessMask );
if ( dwRet != ERROR_SUCCESS )
{
// Failed, so lets exit
return dwRet;
}
if ( FAILED( cmdKey.OpenNode(csKeyPath) ) ||
FAILED( cmdKey.GetDataPaths( MD_ADMIN_ACL,
BINARY_METADATA,
AclList ) )
)
{
return ERROR_ACCESS_DENIED;
}
// Close Metabase
cmdKey.Close();
pos = AclList.GetHeadPosition();
while ( NULL != pos )
{
csPath = AclList.GetNext( pos );
if ( ( _tcscmp( csPath.GetBuffer(0), _T("/") ) == 0 ) ||
( _tcsnicmp( csPath.GetBuffer(0),
METABASEPATH_SCHEMA,
_tcslen( METABASEPATH_SCHEMA ) ) == 0 )
)
{
// If we are at the root of where we set it, then skip this one,
// since this is already set. Or if we are in the schema, it
// should not be changed
continue;
}
if ( _tcscmp( csKeyPath.GetBuffer(0), _T("/") ) == 0 )
{
// If the root of the acl we are at is the root, then don't
// add '/' to it, since it already starts with a '/'
csFullPath = csPath;
}
else
{
csFullPath = csKeyPath + csPath;
}
dwRet = AddUserToMetabaseACL( csFullPath, szUserToAdd, dwAccessMask );
if ( dwRet != ERROR_SUCCESS )
{
return dwRet;
}
}
return dwRet;
}
DWORD AddUserToMetabaseACL(CString csKeyPath, LPTSTR szUserToAdd, DWORD dwAccessMask )
{
DWORD dwReturn = ERROR_ACCESS_DENIED;
BOOL bFound = FALSE;
DWORD attr, uType, dType, cbLen;
CMDKey cmdKey;
BUFFER bufData;
PBYTE pData;
int BufSize;
PSECURITY_DESCRIPTOR pOldSd = NULL;
PSECURITY_DESCRIPTOR pNewSd = NULL;
cmdKey.OpenNode(csKeyPath);
if ( (METADATA_HANDLE) cmdKey )
{
pData = (PBYTE)(bufData.QueryPtr());
BufSize = bufData.QuerySize();
cbLen = 0;
bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
if (!bFound)
{
if (cbLen > 0)
{
if ( ! (bufData.Resize(cbLen)) )
{
iisDebugOut((LOG_TYPE_ERROR, _T("AddUserToMetabaseACL(): cmdKey.GetData. failed to resize to %d.!\n"), cbLen));
}
else
{
pData = (PBYTE)(bufData.QueryPtr());
BufSize = cbLen;
cbLen = 0;
bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
}
}
}
cmdKey.Close();
if (bFound)
{
// We've got the acl
// so now we want to add a user to it.
pOldSd = (PSECURITY_DESCRIPTOR) pData;
if (IsValidSecurityDescriptor(pOldSd))
{
PSID principalSID = NULL;
BOOL bWellKnownSID = FALSE;
if ( dwAccessMask == 0x00 )
{
// If accessmask is not set, then lets set it
dwAccessMask = ( MD_ACR_READ |
MD_ACR_WRITE |
MD_ACR_RESTRICTED_WRITE |
MD_ACR_UNSECURE_PROPS_READ |
MD_ACR_ENUM_KEYS |
MD_ACR_WRITE_DAC );
}
// Get the SID for the certain string (administrator or everyone or whoever)
dwReturn = GetPrincipalSID(szUserToAdd, &principalSID, &bWellKnownSID);
if (dwReturn != ERROR_SUCCESS)
{
iisDebugOut((LOG_TYPE_WARN, _T("AddUserToMetabaseACL:GetPrincipalSID(%s) FAILED. Error()= 0x%x\n"), szUserToAdd, dwReturn));
return dwReturn;
}
#ifndef _CHICAGO_
if (FALSE == AddUserAccessToSD(pOldSd,principalSID,dwAccessMask,ACCESS_ALLOWED_ACE_TYPE,&pNewSd))
{
iisDebugOut((LOG_TYPE_ERROR, _T("AddUserToMetabaseACL:AddUserAccessToSD FAILED\n")));
return dwReturn;
}
if (pNewSd)
{
// We have a new self relative SD
// lets write it to the metabase.
if (IsValidSecurityDescriptor(pNewSd))
{
dwReturn = WriteSDtoMetaBase(pNewSd, csKeyPath);
}
}
#endif
}
}
else
{
dwReturn = ERROR_PATH_NOT_FOUND;
}
}
if (pNewSd){GlobalFree(pNewSd);}
iisDebugOut((LOG_TYPE_TRACE, _T("AddUserToMetabaseACL():End. Return=0x%x.\n"), dwReturn));
return dwReturn;
}
DWORD DoesAdminACLExist(CString csKeyPath)
{
DWORD dwReturn = FALSE;
BOOL bFound = FALSE;
DWORD attr, uType, dType, cbLen;
CMDKey cmdKey;
BUFFER bufData;
PBYTE pData;
int BufSize;
cmdKey.OpenNode(csKeyPath);
if ( (METADATA_HANDLE) cmdKey )
{
pData = (PBYTE)(bufData.QueryPtr());
BufSize = bufData.QuerySize();
cbLen = 0;
bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
if (bFound)
{
dwReturn = TRUE;
}
else
{
if (cbLen > 0)
{
if ( ! (bufData.Resize(cbLen)) )
{
iisDebugOut((LOG_TYPE_ERROR, _T("DoesAdminACLExist(): cmdKey.GetData. failed to resize to %d.!\n"), cbLen));
}
else
{
pData = (PBYTE)(bufData.QueryPtr());
BufSize = cbLen;
cbLen = 0;
bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
if (bFound)
{
dwReturn = TRUE;
}
}
}
}
cmdKey.Close();
}
if (dwReturn != TRUE)
{
//No the acl Does not exist
}
iisDebugOut((LOG_TYPE_TRACE, _T("DoesAdminACLExist():End. Return=0x%x.\n"), dwReturn));
return dwReturn;
}