//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1999-2002. // // File: ADUtils.cpp // // Contents: Classes CWString, CACLDiagComModule, ACE_SAMNAME, helper // methods // // //---------------------------------------------------------------------------- #include "stdafx.h" #include "adutils.h" #include #include #include "dscmn.h" #include "SecDesc.h" void StripQuotes (wstring& str) { size_t qPos = str.find_first_of (L"\"", 0); if ( 0 == qPos ) { str = str.substr (1); qPos = str.find_last_of (L"\""); if ( str.npos != qPos ) str.replace (qPos, 1, 1, 0); } } wstring GetSystemMessage (DWORD dwErr) { wstring message; if ( E_ADS_BAD_PATHNAME == dwErr ) { CWString msg; msg.LoadFromResource (IDS_ADS_BAD_PATHNAME); message = msg; } else { LPVOID pMsgBuf = 0; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPWSTR) &pMsgBuf, 0, NULL ); message = (LPWSTR) pMsgBuf; // Free the buffer. if ( pMsgBuf ) LocalFree (pMsgBuf); } return message; } /* // Attempt to locate a message in a given module. Return the message string // if found, the empty string if not. // // flags - FormatMessage flags to use // // module - module handle of message dll to look in, or 0 to use the system // message table. // // code - message code to look for String getMessageHelper(DWORD flags, HMODULE module, HRESULT code) { ASSERT(code); ASSERT(flags & FORMAT_MESSAGE_ALLOCATE_BUFFER); String message; TCHAR* sys_message = 0; DWORD result = ::FormatMessage( flags, module, static_cast(code), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast(&sys_message), 0, 0); if (result) { ASSERT(sys_message); if (sys_message) { message = sys_message; ASSERT(result == message.length()); Win::LocalFree(sys_message); message.replace(TEXT("\r\n"), TEXT(" ")); } } return message; } // Attempts to locate message strings for various facility codes in the // HRESULT String GetErrorMessage(HRESULT hr) { TRACE_FUNCTION2(GetErrorMessage, String::format("%1!08X!", hr)); ASSERT(FAILED(hr)); if (!FAILED(hr)) { // no messages for success! return String(); } HRESULT code = HRESULT_CODE(hr); if (code == -1) { return String::load(IDS_UNKNOWN_ERROR_CODE); } String message; // default is the system error message table HMODULE module = 0; DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM; int facility = HRESULT_FACILITY(hr); switch (facility) { case FACILITY_WIN32: // 0x7 { // included here: // lanman error codes (in it's own dll) see lmerr.h // dns // winsock // @@ use SafeDLL here? static HMODULE lm_err_res_dll = 0; if (code >= NERR_BASE && code <= MAX_NERR) { // use the net error message resource dll if (lm_err_res_dll == 0) { lm_err_res_dll = Win::LoadLibraryEx( TEXT("netmsg.dll"), LOAD_LIBRARY_AS_DATAFILE); } module = lm_err_res_dll; flags |= FORMAT_MESSAGE_FROM_HMODULE; } break; } case 0x0: { if (code >= 0x5000 && code <= 0x50FF) { // It's an ADSI error. They put the facility code (5) in the // wrong place! // @@ use SafeDLL here? static HMODULE adsi_err_res_dll = 0; // use the net error message resource dll if (adsi_err_res_dll == 0) { adsi_err_res_dll = Win::LoadLibraryEx( TEXT("activeds.dll"), LOAD_LIBRARY_AS_DATAFILE); } module = adsi_err_res_dll; flags |= FORMAT_MESSAGE_FROM_HMODULE; // the message dll expects the entire error code code = hr; } break; } default: { // do nothing break; } } message = getMessageHelper(flags, module, code); if (message.empty()) { message = String::load(IDS_UNKNOWN_ERROR_CODE); } return message; } */ /////////////////////////////////////////////////////////////////////// // wstring helper methods HRESULT wstringFromGUID (wstring& str, REFGUID guid) { HRESULT hr = S_OK; const int BUF_LEN = 128; WCHAR awch[BUF_LEN]; hr = StringFromGUID2(guid, awch, BUF_LEN); if ( SUCCEEDED (hr) ) str = OLE2T(awch); return hr; } bool LoadFromResource(wstring& str, UINT uID) { int nBufferSize = 128; static const int nCountMax = 4; int nCount = 1; bool bRVal = false; bool bDone = true; do { LPWSTR lpszBuffer = new WCHAR[nBufferSize]; if ( lpszBuffer ) { int iRet = ::LoadString(_Module.GetResourceInstance(), uID, lpszBuffer, nBufferSize); if (iRet == 0) { str = L"?"; bDone = true; // not found } if (iRet == nBufferSize-1) // truncation { if (nCount > nCountMax) { // too many reallocations str = lpszBuffer; bRVal = false; // truncation } // try to expand buffer nBufferSize *=2; nCount++; } else { // got it str = lpszBuffer; bRVal = true; bDone = true; } delete [] lpszBuffer; if ( bDone ) break; } else break; } #pragma warning (disable : 4127) while (true); #pragma warning (default : 4127) return bRVal; } bool FormatMessage(wstring& str, UINT nFormatID, ...) { bool bResult = false; // get format string from string table wstring strFormat; if ( LoadFromResource (strFormat, nFormatID) ) { // format message into temporary buffer lpszTemp va_list argList; va_start(argList, nFormatID); PWSTR lpszTemp = 0; if (::FormatMessage (FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, strFormat.c_str (), 0, 0, (PWSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL) { return false; } // assign lpszTemp into the resulting string and free lpszTemp str = lpszTemp; bResult = true; LocalFree(lpszTemp); va_end(argList); } return bResult; } bool FormatMessage(wstring& str, LPCTSTR lpszFormat, ...) { bool bResult = false; // format message into temporary buffer lpszTemp va_list argList; va_start(argList, lpszFormat); LPTSTR lpszTemp; if ( ::FormatMessage (FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL) { return false; //AfxThrowMemoryException(); } // assign lpszTemp into the resulting string and free the temporary str = lpszTemp; bResult = true; LocalFree(lpszTemp); va_end(argList); return bResult; } /////////////////////////////////////////////////////////////////////////////// // CACLDiagComModule CACLDiagComModule::CACLDiagComModule() : m_bDoSchema (false), m_bDoCheckDelegation (false), m_bDoGetEffective (false), m_bDoFixDelegation (false), m_pSecurityDescriptor (0), m_bTabDelimitedOutput (false), m_hPrivToken (0), m_bLogErrors (false) { DWORD dwPriv = SE_SECURITY_PRIVILEGE; m_hPrivToken = EnablePrivileges(&dwPriv, 1); } CACLDiagComModule::~CACLDiagComModule () { if ( m_pSecurityDescriptor ) { LocalFree (m_pSecurityDescriptor); m_pSecurityDescriptor = 0; } ReleasePrivileges(m_hPrivToken); } HRESULT CACLDiagComModule::GetClassFromGUID ( REFGUID rightsGUID, wstring& strClassName, GUID_TYPE* pGuidType) { HRESULT hr = S_OK; CSchemaClassInfo* pInfo = 0; bool bFound = false; // Search for a class for (int nIndex = 0; nIndex < (int) m_classInfoArray.GetCount (); nIndex++) { pInfo = m_classInfoArray[nIndex]; if ( pInfo && IsEqualGUID (*(pInfo->GetSchemaGUID ()), rightsGUID) ) { PCWSTR pszDisplayName = pInfo->GetDisplayName (); strClassName = pszDisplayName ? pszDisplayName : L""; bFound = true; if ( pGuidType ) *pGuidType = GUID_TYPE_CLASS; break; } } // Search for an attribute if ( !bFound ) { for (int nIndex = 0; nIndex < (int) m_attrInfoArray.GetCount (); nIndex++) { pInfo = m_attrInfoArray[nIndex]; if ( pInfo && IsEqualGUID (*(pInfo->GetSchemaGUID ()), rightsGUID) ) { PCWSTR pszDisplayName = pInfo->GetDisplayName (); strClassName = pszDisplayName ? pszDisplayName : L""; bFound = true; if ( pGuidType ) *pGuidType = GUID_TYPE_ATTRIBUTE; break; } } } // Search for a control if ( !bFound ) { hr = GetControlDisplayName (rightsGUID, strClassName); if ( SUCCEEDED (hr) && strClassName.length () ) { if ( pGuidType ) *pGuidType = GUID_TYPE_CONTROL; } else { if ( pGuidType ) *pGuidType = GUID_TYPE_UNKNOWN; strClassName = L"unknown"; } } return hr; } HRESULT CACLDiagComModule::Init() { // Find out if logged-in users is an Administrator BOOL bIsUserAdministrator = FALSE; HRESULT hr = IsUserAdministrator (bIsUserAdministrator); if ( SUCCEEDED (hr) ) { if ( bIsUserAdministrator ) { wstring strObjectDN; LPCWSTR pszLDAP = L"LDAP://"; size_t len = wcslen (pszLDAP); if ( m_strObjectDN.compare (0, len, pszLDAP) ) { strObjectDN = pszLDAP; } strObjectDN += m_strObjectDN; hr = m_adsiObject.Bind (strObjectDN.c_str ()); if ( SUCCEEDED (hr) ) { // Get the class of strObjectDN // enumerate all classes in schema hr = m_adsiObject.QuerySchemaClasses (&m_classInfoArray, false); if ( SUCCEEDED (hr) ) { /* #if DBG // Dump all the class info to the debug window _TRACE (0, L"\n----------------------------------------------------\n"); _TRACE (0, L"-- Classes --\n\n"); for (int nIndex = 0; nIndex < m_classInfoArray.GetCount (); nIndex++) { CSchemaClassInfo* pInfo = m_classInfoArray[nIndex]; if ( pInfo ) { _TRACE (0, L"\t%d\t%s\t%s\n", nIndex, pInfo->GetSchemaIDGUID (), pInfo->GetDisplayName ()); } } _TRACE (0, L"\n----------------------------------------------------\n\n"); #endif // DBG */ // enumerate all attributes in schema hr = m_adsiObject.QuerySchemaClasses (&m_attrInfoArray, true); if ( SUCCEEDED (hr) ) { /* #if DBG // Dump all the attributes info to the debug window _TRACE (0, L"\n----------------------------------------------------\n"); _TRACE (0, L"-- Attributes --\n\n"); for (int nIndex = 0; nIndex < m_attrInfoArray.GetCount (); nIndex++) { CSchemaClassInfo* pInfo = m_attrInfoArray[nIndex]; if ( pInfo ) { _TRACE (0, L"\t%d\t%s\t%s\n", nIndex, pInfo->GetSchemaIDGUID (), pInfo->GetDisplayName ()); } } _TRACE (0, L"\n----------------------------------------------------\n\n"); #endif // DBG */ } wprintf (L"\n"); } } else { wstring str; FormatMessage (str, IDS_INVALID_OBJECT, m_strObjectDN.c_str (), GetSystemMessage (hr).c_str ()); MyWprintf (str.c_str ()); } } else { wstring str; LoadFromResource (str, IDS_USER_MUST_BE_ADMINISTRATOR); MyWprintf (str.c_str ()); } } else { wstring str; FormatMessage (str, IDS_COULD_NOT_VALIDATE_USER_CREDENTIALS, GetSystemMessage (hr).c_str ()); MyWprintf (str.c_str ()); } return hr; } HRESULT CACLDiagComModule::IsUserAdministrator (BOOL & bIsAdministrator) { bIsAdministrator = TRUE; return S_OK; /* _TRACE (1, L"Entering CACLDiagComModule::IsUserAdministrator\n"); HRESULT hr = S_OK; DWORD dwErr = 0; bIsAdministrator = FALSE; if ( IsWindowsNT () ) { DWORD dwInfoBufferSize = 0; PSID psidAdministrators; SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; BOOL bResult = AllocateAndInitializeSid (&siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdministrators); if ( bResult ) { bResult = CheckTokenMembership (0, psidAdministrators, &bIsAdministrator); ASSERT (bResult); if ( !bResult ) { dwErr = GetLastError (); hr = HRESULT_FROM_WIN32 (dwErr); } FreeSid (psidAdministrators); } else { dwErr = GetLastError (); hr = HRESULT_FROM_WIN32 (dwErr); } } _TRACE (-1, L"Leaving CACLDiagComModule::IsUserAdministrator\n"); return hr */ } bool CACLDiagComModule::IsWindowsNT() { OSVERSIONINFO versionInfo; ::ZeroMemory (&versionInfo, sizeof (OSVERSIONINFO)); versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); BOOL bResult = ::GetVersionEx (&versionInfo); ASSERT (bResult); if ( bResult ) { if ( VER_PLATFORM_WIN32_NT == versionInfo.dwPlatformId ) bResult = TRUE; } return bResult ? true : false; } /////////////////////////////////////////////////////////////////////////////// // ACE_SAMNAME BOOL ACE_SAMNAME::operator==(const ACE_SAMNAME& rAceSAMName) const { // Neutralize INHERITED_ACE flag in Header.AceFlags // Consider equivalent if all the mask bits in 'this' are found in rAceSAMName BOOL bResult = FALSE; if ( (m_AceType == rAceSAMName.m_AceType) && ( !this->m_SAMAccountName.compare (rAceSAMName.m_SAMAccountName)) ) { switch (m_AceType) { case ACCESS_ALLOWED_ACE_TYPE: if ( m_pAllowedAce->Mask == rAceSAMName.m_pAllowedAce->Mask && (m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) && m_pAllowedAce->Header.AceSize == rAceSAMName.m_pAllowedAce->Header.AceSize ) { bResult = TRUE; } break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: if ( m_pAllowedObjectAce->Mask == rAceSAMName.m_pAllowedObjectAce->Mask && (m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) && m_pAllowedObjectAce->Header.AceSize == rAceSAMName.m_pAllowedObjectAce->Header.AceSize && ::IsEqualGUID (m_pAllowedObjectAce->ObjectType, rAceSAMName.m_pAllowedObjectAce->ObjectType) ) { bResult = TRUE; } break; case ACCESS_DENIED_ACE_TYPE: if ( m_pDeniedAce->Mask == rAceSAMName.m_pDeniedAce->Mask && (m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) && m_pDeniedAce->Header.AceSize == rAceSAMName.m_pDeniedAce->Header.AceSize ) { bResult = TRUE; } break; case ACCESS_DENIED_OBJECT_ACE_TYPE: if ( m_pDeniedObjectAce->Mask == rAceSAMName.m_pDeniedObjectAce->Mask && (m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) && m_pDeniedObjectAce->Header.AceSize == rAceSAMName.m_pDeniedObjectAce->Header.AceSize && ::IsEqualGUID (m_pDeniedObjectAce->ObjectType, rAceSAMName.m_pDeniedObjectAce->ObjectType) ) { bResult = TRUE; } break; case SYSTEM_AUDIT_OBJECT_ACE_TYPE: if ( m_pSystemAuditObjectAce->Mask == rAceSAMName.m_pSystemAuditObjectAce->Mask && (m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) && m_pSystemAuditObjectAce->Header.AceSize == rAceSAMName.m_pSystemAuditObjectAce->Header.AceSize && ::IsEqualGUID (m_pSystemAuditObjectAce->ObjectType, rAceSAMName.m_pSystemAuditObjectAce->ObjectType) ) { bResult = TRUE; } break; case SYSTEM_AUDIT_ACE_TYPE: if ( m_pSystemAuditAce->Mask == rAceSAMName.m_pSystemAuditAce->Mask && (m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) && m_pSystemAuditAce->Header.AceSize == rAceSAMName.m_pSystemAuditAce->Header.AceSize ) { bResult = TRUE; } break; default: break; } } return bResult; } BOOL ACE_SAMNAME::IsEquivalent (ACE_SAMNAME& rAceSAMName, ACCESS_MASK accessMask) { // Neutralize INHERITED_ACE flag in Header.AceFlags BOOL bResult = FALSE; if ( m_AceType == rAceSAMName.m_AceType ) { switch (m_AceType) { case ACCESS_ALLOWED_ACE_TYPE: if ( (m_pAllowedAce->Mask & accessMask) == (rAceSAMName.m_pAllowedAce->Mask & accessMask) && m_pAllowedAce->SidStart == rAceSAMName.m_pAllowedAce->SidStart && (m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) && m_pAllowedAce->Header.AceSize == rAceSAMName.m_pAllowedAce->Header.AceSize ) { bResult = TRUE; } break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: if ( (m_pAllowedObjectAce->Mask & accessMask) == (rAceSAMName.m_pAllowedObjectAce->Mask & accessMask) && m_pAllowedObjectAce->SidStart == rAceSAMName.m_pAllowedObjectAce->SidStart && (m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) && m_pAllowedObjectAce->Header.AceSize == rAceSAMName.m_pAllowedObjectAce->Header.AceSize && ::IsEqualGUID (m_pAllowedObjectAce->ObjectType, rAceSAMName.m_pAllowedObjectAce->ObjectType) ) { bResult = TRUE; } break; case ACCESS_DENIED_ACE_TYPE: if ( (m_pDeniedAce->Mask & accessMask) == (rAceSAMName.m_pDeniedAce->Mask & accessMask) && m_pDeniedAce->SidStart == rAceSAMName.m_pDeniedAce->SidStart && (m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) && m_pDeniedAce->Header.AceSize == rAceSAMName.m_pDeniedAce->Header.AceSize ) { bResult = TRUE; } break; case ACCESS_DENIED_OBJECT_ACE_TYPE: if ( (m_pDeniedObjectAce->Mask & accessMask) == (rAceSAMName.m_pDeniedObjectAce->Mask & accessMask) && m_pDeniedObjectAce->SidStart == rAceSAMName.m_pDeniedObjectAce->SidStart && (m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) && m_pDeniedObjectAce->Header.AceSize == rAceSAMName.m_pDeniedObjectAce->Header.AceSize && ::IsEqualGUID (m_pDeniedObjectAce->ObjectType, rAceSAMName.m_pDeniedObjectAce->ObjectType) ) { bResult = TRUE; } break; case SYSTEM_AUDIT_OBJECT_ACE_TYPE: if ( (m_pSystemAuditObjectAce->Mask & accessMask) == (rAceSAMName.m_pSystemAuditObjectAce->Mask & accessMask) && m_pSystemAuditObjectAce->SidStart == rAceSAMName.m_pSystemAuditObjectAce->SidStart && (m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) && m_pSystemAuditObjectAce->Header.AceSize == rAceSAMName.m_pSystemAuditObjectAce->Header.AceSize ) { bResult = TRUE; } break; case SYSTEM_AUDIT_ACE_TYPE: if ( (m_pSystemAuditAce->Mask & accessMask) == (rAceSAMName.m_pSystemAuditAce->Mask & accessMask) && m_pSystemAuditAce->SidStart == rAceSAMName.m_pSystemAuditAce->SidStart && (m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) == (rAceSAMName.m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) && m_pSystemAuditAce->Header.AceSize == rAceSAMName.m_pSystemAuditAce->Header.AceSize ) { bResult = TRUE; } break; default: break; } } return bResult; } bool ACE_SAMNAME::IsInherited() const { return (m_pAllowedAce->Header.AceFlags & INHERITED_ACE) ? true : false; } void ACE_SAMNAME::DebugOut() const { #if DBG == 1 wstring strGuidResult; GUID_TYPE guidType = GUID_TYPE_UNKNOWN; _TRACE (0, L"\n"); _TRACE (0, L"Principal Name: %s\n", m_SAMAccountName.c_str ()); switch (m_AceType) { case ACCESS_ALLOWED_ACE_TYPE: _TRACE (0, L"AceType: ACCESS_ALLOWED_ACE_TYPE\n"); _TRACE (0, L"Mask: 0x%x\n", m_pAllowedAce->Mask); _TRACE (0, L"AceFlags: 0x%x\n", m_pAllowedAce->Header.AceFlags); _TRACE (0, L"AceSize: %d bytes\n", m_pAllowedAce->Header.AceSize); break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: _TRACE (0, L"AceType: ACCESS_ALLOWED_OBJECT_ACE_TYPE\n"); _TRACE (0, L"Mask: 0x%x\n", m_pAllowedObjectAce->Mask); _TRACE (0, L"AceFlags: 0x%x\n", m_pAllowedObjectAce->Header.AceFlags); _TRACE (0, L"AceSize: %d bytes\n", m_pAllowedObjectAce->Header.AceSize); _Module.GetClassFromGUID (m_pAllowedObjectAce->ObjectType, strGuidResult, &guidType); break; case ACCESS_DENIED_ACE_TYPE: _TRACE (0, L"AceType: ACCESS_DENIED_ACE_TYPE\n"); _TRACE (0, L"Mask: 0x%x\n", m_pDeniedAce->Mask); _TRACE (0, L"AceFlags: 0x%x\n", m_pDeniedAce->Header.AceFlags); _TRACE (0, L"AceSize: %d bytes\n", m_pDeniedAce->Header.AceSize); break; case ACCESS_DENIED_OBJECT_ACE_TYPE: _TRACE (0, L"AceType: ACCESS_DENIED_OBJECT_ACE_TYPE\n"); _TRACE (0, L"Mask: 0x%x\n", m_pDeniedObjectAce->Mask); _TRACE (0, L"AceFlags: 0x%x\n", m_pDeniedObjectAce->Header.AceFlags); _TRACE (0, L"AceSize: %d bytes\n", m_pDeniedObjectAce->Header.AceSize); _Module.GetClassFromGUID (m_pDeniedObjectAce->ObjectType, strGuidResult, &guidType); break; case SYSTEM_AUDIT_OBJECT_ACE_TYPE: _TRACE (0, L"AceType: SYSTEM_AUDIT_OBJECT_ACE_TYPE\n"); _TRACE (0, L"Mask: 0x%x\n", m_pSystemAuditObjectAce->Mask); _TRACE (0, L"AceFlags: 0x%x\n", m_pSystemAuditObjectAce->Header.AceFlags); _TRACE (0, L"AceSize: %d bytes\n", m_pSystemAuditObjectAce->Header.AceSize); _Module.GetClassFromGUID (m_pSystemAuditObjectAce->ObjectType, strGuidResult, &guidType); break; case SYSTEM_AUDIT_ACE_TYPE: _TRACE (0, L"AceType: SYSTEM_AUDIT_ACE_TYPE\n"); _TRACE (0, L"Mask: 0x%x\n", m_pSystemAuditAce->Mask); _TRACE (0, L"AceFlags: 0x%x\n", m_pSystemAuditAce->Header.AceFlags); _TRACE (0, L"AceSize: %d bytes\n", m_pSystemAuditAce->Header.AceSize); break; } if ( IsObjectAceType (m_pAllowedAce) ) { wstring strGuidType; switch (guidType) { case GUID_TYPE_CLASS: strGuidType = L"GUID_TYPE_CLASS"; break; case GUID_TYPE_ATTRIBUTE: strGuidType = L"GUID_TYPE_ATTRIBUTE"; break; case GUID_TYPE_CONTROL: strGuidType = L"GUID_TYPE_CONTROL"; break; default: #pragma warning (disable : 4127) ASSERT (0); #pragma warning (default : 4127) // fall through case GUID_TYPE_UNKNOWN: strGuidType = L"GUID_TYPE_UNKNOWN"; break; } _TRACE (0, L"ObjectType type: %s\n", strGuidType.c_str ()); _TRACE (0, L"ObjectType value: %s\n", strGuidResult.c_str ()); } _TRACE (0, L"\n"); #endif } /////////////////////////////////////////////////////////////////////////////// HRESULT SetSecurityInfoMask(LPUNKNOWN punk, SECURITY_INFORMATION si) { HRESULT hr = E_INVALIDARG; if (punk) { IADsObjectOptions *pOptions; hr = punk->QueryInterface(IID_IADsObjectOptions, (void**)&pOptions); if (SUCCEEDED(hr)) { VARIANT var; V_VT(&var) = VT_I4; V_I4(&var) = si; hr = pOptions->SetOption(ADS_OPTION_SECURITY_MASK, var); pOptions->Release(); } } return hr; } /////////////////////////////////////////////////////////////////////////////// /******************************************************************* NAME: EnablePrivileges SYNOPSIS: Enables the given privileges in the current token ENTRY: pdwPrivileges - list of privileges to enable RETURNS: On success, the previous thread handle (if present) or NULL On failure, INVALID_HANDLE_VALUE NOTES: The returned handle should be passed to ReleasePrivileges to ensure proper cleanup. Otherwise, if not NULL or INVALID_HANDLE_VALUE it should be closed with CloseHandle. HISTORY: JeffreyS 08-Oct-1996 Created ********************************************************************/ HANDLE EnablePrivileges(PDWORD pdwPrivileges, ULONG cPrivileges) { BOOL fResult; HANDLE hToken; HANDLE hOriginalThreadToken; PTOKEN_PRIVILEGES ptp; ULONG nBufferSize; if (!pdwPrivileges || !cPrivileges) return INVALID_HANDLE_VALUE; // Note that TOKEN_PRIVILEGES includes a single LUID_AND_ATTRIBUTES nBufferSize = sizeof(TOKEN_PRIVILEGES) + (cPrivileges - 1) * sizeof(LUID_AND_ATTRIBUTES); ptp = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, nBufferSize); if (!ptp) return INVALID_HANDLE_VALUE; // // Initialize the Privileges Structure // ptp->PrivilegeCount = cPrivileges; for (ULONG i = 0; i < cPrivileges; i++) { //ptp->Privileges[i].Luid = RtlConvertUlongToLuid(*pdwPrivileges++); ptp->Privileges[i].Luid.LowPart = *pdwPrivileges++; ptp->Privileges[i].Luid.HighPart = 0; ptp->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED; } // // Open the Token // hToken = hOriginalThreadToken = INVALID_HANDLE_VALUE; fResult = OpenThreadToken (GetCurrentThread (), TOKEN_DUPLICATE, FALSE, &hToken); if (fResult) hOriginalThreadToken = hToken; // Remember the thread token else fResult = OpenProcessToken (GetCurrentProcess(), TOKEN_DUPLICATE, &hToken); if (fResult) { HANDLE hNewToken; // // Duplicate that Token // fResult = DuplicateTokenEx(hToken, TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, NULL, // PSECURITY_ATTRIBUTES SecurityImpersonation, // SECURITY_IMPERSONATION_LEVEL TokenImpersonation, // TokenType &hNewToken); // Duplicate token if (fResult) { // // Add new privileges // fResult = AdjustTokenPrivileges(hNewToken, // TokenHandle FALSE, // DisableAllPrivileges ptp, // NewState 0, // BufferLength NULL, // PreviousState NULL); // ReturnLength if (fResult) { // // Begin impersonating with the new token // fResult = SetThreadToken(NULL, hNewToken); } CloseHandle(hNewToken); } } // If something failed, don't return a token if (!fResult) hOriginalThreadToken = INVALID_HANDLE_VALUE; // Close the original token if we aren't returning it if (hOriginalThreadToken == INVALID_HANDLE_VALUE && hToken != INVALID_HANDLE_VALUE) { CloseHandle(hToken); } // If we succeeded, but there was no original thread token, // return NULL to indicate we need to do SetThreadToken(NULL, NULL) // to release privs. if (fResult && hOriginalThreadToken == INVALID_HANDLE_VALUE) hOriginalThreadToken = NULL; LocalFree(ptp); return hOriginalThreadToken; } /******************************************************************* NAME: ReleasePrivileges SYNOPSIS: Resets privileges to the state prior to the corresponding EnablePrivileges call. ENTRY: hToken - result of call to EnablePrivileges RETURNS: nothing HISTORY: JeffreyS 08-Oct-1996 Created ********************************************************************/ BOOL ReleasePrivileges(HANDLE hToken) { BOOL bRVal = FALSE; if (INVALID_HANDLE_VALUE != hToken) { bRVal = SetThreadToken(NULL, hToken); if (hToken) CloseHandle(hToken); } return bRVal; } VOID LocalFreeStringW(LPWSTR* ppString) { if ( ppString && *ppString ) { LocalFree((HLOCAL)*ppString); *ppString = NULL; } } /////////////////////////////////////////////////////////////////////////////// // // Method: GetNameFromSid () // // Purpose: Get the name of the object represented by this Sid // // Inputs: pSid - SID of the object whose name we wish to retrieve // // Outputs: strPrincipalName - name of the object in NameUserPrincipal // pstrFQDN - (optional) name of the object as Fully Qualified DN // HRESULT GetNameFromSid ( PSID pSid, wstring& strPrincipalName, wstring* pstrFQDN, SID_NAME_USE& sne) { ASSERT (IsValidSid (pSid)); if ( !IsValidSid (pSid) ) return E_INVALIDARG; PWSTR pwszName = 0; DWORD cchName = 0; PWSTR pwszDomain = 0; DWORD cchDomain = 0; HRESULT hr = S_OK; BOOL bRVal = ::LookupAccountSid (NULL, // name of local or remote computer pSid, // security identifier pwszName, // account name buffer &cchName, // size of account name buffer, in characters pwszDomain, // domain name &cchDomain, // size of domain name buffer, in characters &sne); // SID type if ( FALSE == bRVal ) { DWORD dwErr = GetLastError (); if ( ERROR_INSUFFICIENT_BUFFER == dwErr ) { ASSERT (0 != cchDomain && 0 != cchName); if ( 0 == cchDomain || 0 == cchName ) return E_UNEXPECTED; pwszName = new WCHAR[cchName]; if ( pwszName ) { pwszDomain = new WCHAR[cchDomain]; if ( pwszDomain ) { if ( ::LookupAccountSid (NULL, // name of local or remote computer pSid, // security identifier pwszName, // account name buffer &cchName, // size of account name buffer pwszDomain, // domain name &cchDomain, // size of domain name buffer &sne) ) // SID type { wstring strSamCompatibleName (pwszDomain); strSamCompatibleName += L"\\"; strSamCompatibleName += pwszName; // Get Principal Name { PWSTR pszTranslatedName = 0; if ( SUCCEEDED (CrackName(const_cast (strSamCompatibleName.c_str ()), &pszTranslatedName, GET_OBJ_UPN, //GET_OBJ_NT4_NAME, 0)) ) { strPrincipalName = pszTranslatedName; LocalFreeStringW(&pszTranslatedName); } else { strPrincipalName = strSamCompatibleName; } } // Get fully qualified DN if ( pstrFQDN ) { PWSTR pszTranslatedName = 0; if ( SUCCEEDED (CrackName(const_cast (strSamCompatibleName.c_str ()), &pszTranslatedName, GET_OBJ_1779_DN, 0)) ) { *pstrFQDN = pszTranslatedName; LocalFreeStringW(&pszTranslatedName); } else { *pstrFQDN = strSamCompatibleName; } } } else { dwErr = GetLastError (); _TRACE (0, L"LookupAccountSid failed: 0x%x\n", dwErr); if ( ERROR_NONE_MAPPED == dwErr ) { PWSTR pszStringSid = 0; if ( ::ConvertSidToStringSid (pSid, &pszStringSid) ) { strPrincipalName = pszStringSid; if ( pstrFQDN ) *pstrFQDN = pszStringSid; ::LocalFree (pszStringSid); } else hr = E_OUTOFMEMORY; } else hr = HRESULT_FROM_WIN32 (dwErr); } delete [] pwszDomain; } else hr = E_OUTOFMEMORY; delete [] pwszName; } else hr = E_OUTOFMEMORY; } else { dwErr = GetLastError (); _TRACE (0, L"LookupAccountSid failed: 0x%x\n", dwErr); if ( ERROR_NONE_MAPPED == dwErr ) { PWSTR pszStringSid = 0; if ( ::ConvertSidToStringSid (pSid, &pszStringSid) ) { strPrincipalName = pszStringSid; if ( pstrFQDN ) *pstrFQDN = pszStringSid; ::LocalFree (pszStringSid); } else hr = E_OUTOFMEMORY; } else hr = HRESULT_FROM_WIN32 (dwErr); } } else { // Huh? How can this API return TRUE with null buffers? hr = E_UNEXPECTED; } return hr; } #define MAX_BUF_SIZE 4096 CHAR AnsiBuf[MAX_BUF_SIZE*3]; /* worst case is DBCS, which */ /* needs more than *2 */ WCHAR ConBuf [MAX_BUF_SIZE]; int FileIsConsole(HANDLE fh) { unsigned htype ; htype = GetFileType(fh); htype &= ~FILE_TYPE_REMOTE; return htype == FILE_TYPE_CHAR; } int MyWriteConsole() { DWORD cch = (DWORD) wcslen(ConBuf); HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); if (FileIsConsole(hOut)) WriteConsole(hOut, ConBuf, cch, &cch, NULL); else { cch = WideCharToMultiByte(CP_OEMCP, 0, ConBuf, (int) cch, AnsiBuf, MAX_BUF_SIZE*3, NULL, NULL); WriteFile(hOut, AnsiBuf, cch, &cch, NULL); } return (int) cch; } int MyWprintf( const wchar_t *fmt, ... ) { va_list args; va_start( args, fmt ); ::ZeroMemory (ConBuf, sizeof (ConBuf)); _vsnwprintf( ConBuf, MAX_BUF_SIZE-1, fmt, args ); va_end( args ); return MyWriteConsole (); }