#include "stdafx.h" #include #include #include "iadmw.h" #include "iiscnfg.h" #include "log.h" #include "mdkey.h" #include "dcomperm.h" #include "other.h" #include "mdacl.h" #include // 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; }