952 lines
32 KiB
C++
952 lines
32 KiB
C++
|
#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;
|
||
|
LPTSTR p, rest, token;
|
||
|
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 = E_FAIL;
|
||
|
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 = E_FAIL;
|
||
|
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 = E_FAIL;
|
||
|
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 = E_FAIL;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// Initialize a new ACL, which only contains 2 aaace
|
||
|
cbACL = sizeof(ACL) +
|
||
|
(sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pAdminsSID) - sizeof(DWORD)) +
|
||
|
(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 = E_FAIL;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
if (!InitializeAcl(pACLNew, cbACL, ACL_REVISION))
|
||
|
{
|
||
|
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:InitializeAcl FAILED. GetLastError()= 0x%x\n"), GetLastError));
|
||
|
dwRetCode = E_FAIL;
|
||
|
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 = E_FAIL;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
if (!AddAccessAllowedAce(pACLNew,ACL_REVISION,dwAccessForEveryoneAccount,pEveryoneSID))
|
||
|
{
|
||
|
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:AddAccessAllowedAce(pEveryoneSID) FAILED. GetLastError()= 0x%x\n"), GetLastError()));
|
||
|
dwRetCode = E_FAIL;
|
||
|
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 = E_FAIL;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
b = SetSecurityDescriptorOwner(pSD, pAdminsSID, TRUE);
|
||
|
if (!b)
|
||
|
{
|
||
|
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:SetSecurityDescriptorOwner(pAdminsSID) FAILED. GetLastError()= 0x%x\n"), GetLastError()));
|
||
|
dwRetCode = E_FAIL;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
b = SetSecurityDescriptorGroup(pSD, pAdminsSID, TRUE);
|
||
|
if (!b)
|
||
|
{
|
||
|
iisDebugOut((LOG_TYPE_ERROR, _T("SetAdminACL:SetSecurityDescriptorGroup(pAdminsSID) FAILED. GetLastError()= 0x%x\n"), GetLastError()));
|
||
|
dwRetCode = E_FAIL;
|
||
|
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 = E_FAIL;
|
||
|
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 = E_FAIL;
|
||
|
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 = E_FAIL;
|
||
|
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 = E_FAIL;
|
||
|
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;
|
||
|
ACCESS_MASK dwOldMask, dwNewMask, dwExtraMask, dwMask;
|
||
|
|
||
|
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,0x%x,0x%x,0x%x,0x%x\r\n"),
|
||
|
szUserName,
|
||
|
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 = E_FAIL;
|
||
|
|
||
|
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
|
||
|
{
|
||
|
// there was no acl to be found.
|
||
|
}
|
||
|
}
|
||
|
return dwReturn;
|
||
|
}
|
||
|
|
||
|
DWORD AddUserToMetabaseACL(CString csKeyPath, LPTSTR szUserToAdd)
|
||
|
{
|
||
|
DWORD dwReturn = E_FAIL;
|
||
|
|
||
|
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))
|
||
|
{
|
||
|
DWORD AccessMask = (MD_ACR_READ |MD_ACR_WRITE |MD_ACR_RESTRICTED_WRITE |MD_ACR_UNSECURE_PROPS_READ |MD_ACR_ENUM_KEYS |MD_ACR_WRITE_DAC);
|
||
|
PSID principalSID = NULL;
|
||
|
BOOL bWellKnownSID = FALSE;
|
||
|
|
||
|
// 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,AccessMask,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
|
||
|
{
|
||
|
// there was no acl to be 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;
|
||
|
}
|