//========================================================================== // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved. // //-------------------------------------------------------------------------- #include "FaxSecurity.h" #include //+--------------------------------------------------------------------------- // // function: GiveUsage // // Synopsis: prints the usage of the application // // Arguments: [AppName] - Name of the application whose usage has to be printed // // Returns: void //---------------------------------------------------------------------------- void GiveUsage(LPTSTR AppName) { _tprintf( TEXT("Usage : %s \n \ /s Fax Server Name \n \ /o print/add/delete \n \ /a AccountName E.g. testmachine\\administrator \n \ /d Deny ACE can be 0 or 1. If 1 then Deny \n \ /m AccessMask For permissible values, refer to ReadMe.txt "),AppName); _tprintf( TEXT("Usage : %s /? -- this message\n"),AppName); } //+--------------------------------------------------------------------------- // // function: IsOSVersionCompatible // // Synopsis: finds whether the target OS supports this functionality. // // Arguments: [dwVersion] - Minimum Version of the OS required for the Sample to run. // // Returns: bool - true if the Sample can run on this OS // //---------------------------------------------------------------------------- bool IsOSVersionCompatible(DWORD dwVersion) { OSVERSIONINFOEX osvi; BOOL bOsVersionInfoEx; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi); if( !bOsVersionInfoEx ) { osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) return false; } bOsVersionInfoEx = (osvi.dwMajorVersion >= dwVersion ); return (bOsVersionInfoEx == TRUE); } //+--------------------------------------------------------------------------- // // function: getDWordAccess // // Synopsis: Finds the Access Mask from the User Input // // Arguments: [lptstrAccessMask] - The Access Mask String // // Returns: DWORD - Access Mask to be used // //---------------------------------------------------------------------------- DWORD getDWordAccess(TCHAR* lptstrAccessMask) { _tprintf(_T("Access Mask is %s \n"), lptstrAccessMask); DWORD dwAccess =0 ; if(_tcsicmp(lptstrAccessMask,L"submit_low") == 0) dwAccess = 0x001; if(_tcsicmp(lptstrAccessMask,L"submit_normal") == 0) dwAccess = 0x002; if(_tcsicmp(lptstrAccessMask,L"submit_high") == 0) dwAccess = 0x004; if(_tcsicmp(lptstrAccessMask,L"query_jobs") == 0) dwAccess = 0x008; if(_tcsicmp(lptstrAccessMask,L"manage_jobs") == 0) dwAccess = 0x010; if(_tcsicmp(lptstrAccessMask,L"query_config") == 0) dwAccess = 0x020; if(_tcsicmp(lptstrAccessMask,L"manage_config") == 0) dwAccess = 0x040; if(_tcsicmp(lptstrAccessMask,L"query_archives") == 0) dwAccess = 0x080; if(_tcsicmp(lptstrAccessMask,L"manage_archives") == 0) dwAccess = 0x100; if(_tcsicmp(lptstrAccessMask,L"manage_receive_folder") == 0) dwAccess = 0x0200; _tprintf(_T("Access Mask is %s \n"), lptstrAccessMask); return dwAccess; } //+--------------------------------------------------------------------------- // // function: GetSDParts // // Synopsis: Gets the Security Descriptor parts: DACL and stores it in a global variable // // Arguments: [pFaxSecurity] : FaxSecurity Object // // Returns: HRESULT - S_OK if successful // //---------------------------------------------------------------------------- HRESULT GetSDParts(IFaxSecurity2* pFaxSecurity) { BOOL fFlag; BOOL fDaclPresent = FALSE; BOOL fDaclDefaulted = TRUE; DWORD dwErrorCode = 0; VARIANT vDescriptor; HRESULT hr = S_OK; VariantInit(&vDescriptor); _tprintf(_T("Entering GetSDParts() \n")); //Get the security descriptor from FaxSecurity hr = pFaxSecurity->put_InformationType(DACL_SECURITY_INFORMATION); if(FAILED(hr)) { _tprintf(_T("put_InformationType failed. Error %x \n"), hr); goto Exit; } hr = pFaxSecurity->get_Descriptor(&vDescriptor); if(FAILED(hr)) { _tprintf(_T("get_Descriptor failed. Error %x \n"), hr); goto Exit; } hr = SafeArrayAccessData(vDescriptor.parray, (void **) &g_pSecurityDescriptor); if(FAILED(hr)) { _tprintf(_T("SafeArrayAccessData failed. Error %x \n"), hr); goto Exit; } //Get the DACL fFlag = GetSecurityDescriptorDacl(g_pSecurityDescriptor,&fDaclPresent, &g_pDACL, &fDaclDefaulted); if(fFlag == FALSE) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("GetSecurityDescriptorDacl failed. Error %x \n"), hr); goto Exit; } if (fDaclPresent == FALSE || g_pDACL == NULL) { _tprintf(_T("No DACL was found (all access is denied), or a NULL DACL (unrestricted access) was found.\n")); hr = S_OK; goto Exit; } _tprintf(_T("DACL Found \n")); hr = S_OK; Exit: VariantClear(&vDescriptor); return hr; } //+--------------------------------------------------------------------------- // // function: PrintACEs // // Synopsis: Print the ACEs present in the DACL // // Arguments: None // // Returns: HRESULT - S_OK if successful // //---------------------------------------------------------------------------- HRESULT PrintACEs() { HRESULT hr = S_OK; BYTE bSIDBuffer[SD_LENGTH1] = {0}; PSID pSID = &bSIDBuffer; DWORD dwDomainBufferSize = SD_LENGTH1; LPTSTR lptstrDomainName = NULL; DWORD dwAccNameBufferSize = SD_LENGTH1; LPTSTR lptstrAccName = NULL; SID_NAME_USE eSidType; ACL_SIZE_INFORMATION aclSizeInfo; DWORD dwErrorCode = 0; ACCESS_ALLOWED_ACE* pAce = NULL; _tprintf(_T("Entering PrintACEs ... \n")); //Get ACL info BOOL fFlag = GetAclInformation(g_pDACL, &aclSizeInfo, sizeof(aclSizeInfo),AclSizeInformation); if(fFlag == FALSE) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("GetAclInformation failed. hr = %x \n"), hr); goto Exit; } // Iterate thru the ACE list _tprintf(_T("\n\nACE Count %d \n"), aclSizeInfo.AceCount); for (UINT cAce = 0; cAce < aclSizeInfo.AceCount; cAce++) { if (!GetAce(g_pDACL, cAce, (LPVOID*)&pAce)) { dwErrorCode = GetLastError(); hr =HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("GetAce failed. hr = %x \n"), hr); goto Exit; } dwAccNameBufferSize = SD_LENGTH1; dwDomainBufferSize = SD_LENGTH1; lptstrDomainName = new TCHAR[dwDomainBufferSize]; if (lptstrDomainName == NULL) { hr = E_OUTOFMEMORY; _tprintf(_T("malloc for lptstrDomainName failed. hr = %x \n"), hr); goto Exit; } memset(lptstrDomainName, 0, dwDomainBufferSize*sizeof(TCHAR)); lptstrAccName = new TCHAR[dwAccNameBufferSize]; if (lptstrAccName == NULL) { hr = E_OUTOFMEMORY; _tprintf(_T("malloc for lptstrAccName failed. hr = %x \n"), hr); goto Exit; } memset(lptstrAccName, 0, dwAccNameBufferSize*sizeof(TCHAR)); //Get the AccountNAme from the SID if(!LookupAccountSid(NULL, &pAce->SidStart, lptstrAccName, &dwAccNameBufferSize, lptstrDomainName, &dwDomainBufferSize, &eSidType)) { LPTSTR szSID = NULL; // Convert SID to string. ConvertSidToStringSid(&pAce->SidStart, &szSID); _tprintf(_T("\n Couldn't Resolve to account Name. Printing Account SID %s \n"), szSID); LocalFree(szSID); } else { //Print the ACE info _tprintf(_T("\n\nAccount Name %s \n"), lptstrAccName); } if( pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) { _tprintf(_T("Access Denied Ace \n")); } if( pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { _tprintf(_T("Access Allowed Ace \n")); } _tprintf(_T("Access Mask 0x%x \n"), pAce->Mask); delete lptstrAccName; lptstrAccName = NULL; delete lptstrDomainName; lptstrDomainName = NULL; } Exit: _tprintf(_T("\n\n"), pAce->Mask); if(lptstrAccName) delete lptstrAccName; if(lptstrDomainName) delete lptstrDomainName; return hr; } //+--------------------------------------------------------------------------- // // function: IsAcePresent // // Synopsis: Check for Duplicate Ace // // Arguments: None // // Returns: BOOL - true if duplicate is found // //---------------------------------------------------------------------------- BOOL IsAcePresent(PSID pSID, BOOL bDeny, DWORD dwAccessMask, UINT iAceCount) { HRESULT hr = S_OK; DWORD dwErrorCode =0; ACCESS_ALLOWED_ACE* pAce = NULL; //Iterate through the Ace List _tprintf(_T("Entering IsAcePresent ...\n")); for (UINT cAce = 0; cAce < iAceCount; cAce++) { if (!GetAce(g_pDACL, cAce, (LPVOID*)&pAce)) { _tprintf(_T("GetAce failed. GetLastError returned: %d\n"), dwErrorCode); dwErrorCode = GetLastError(); hr =HRESULT_FROM_WIN32(dwErrorCode); goto Exit; } if (EqualSid((PSID)&pAce->SidStart, pSID)) { if(pAce->Mask & dwAccessMask) { if((bDeny && (pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE))|| (!bDeny && (pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE))) { //found one _tprintf(_T("Found Duplicate ACE \n")); return TRUE; } } } } Exit: return FALSE; } //+--------------------------------------------------------------------------- // // function: PrintACEsFax // // Synopsis: Prints the Fax ACEs // // Arguments: [pFaxSecurity] : FaxSecurity Object // // Returns: BOOL - true if successful // //---------------------------------------------------------------------------- bool PrintACEsFax(IFaxSecurity2* pFaxSecurity) { bool bRetVal = false; //Get the SD Parts and from the DACL print the ACEs HRESULT hr = S_OK; hr = GetSDParts(pFaxSecurity); if(FAILED(hr)) { _tprintf(_T("GetSDParts failed. Error %x \n"), hr); bRetVal = false; goto Exit; } hr = PrintACEs(); if(FAILED(hr)) { _tprintf(_T("PrintACEs failed. Error %x \n"), hr); bRetVal = false; goto Exit; } bRetVal = true; Exit: return bRetVal; } //+--------------------------------------------------------------------------- // // function: DelAce // // Synopsis: Delete the ACE from the DACL // // Arguments: [bDeny] - is it a Deny Ace? // [lptstrAccName] : Account from where to delete the ACE // [dwAccessMask] : The Access Mask to delete // // Returns: HRESULT S_OK if successful //---------------------------------------------------------------------------- HRESULT DelAce(BOOL bDeny, LPTSTR lptstrAccName, DWORD dwAccessMask) { HRESULT hr = S_OK; BYTE bSIDBuffer[SD_LENGTH1] = {0}; PSID pSID = &bSIDBuffer; DWORD dwSIDBufferSize = SD_LENGTH1; DWORD dwDomainBufferSize = SD_LENGTH1; LPTSTR lptstrDomainName = NULL; SID_NAME_USE eSidType; ACL_SIZE_INFORMATION aclSizeInfo; DWORD dwErrorCode = 0; ACCESS_ALLOWED_ACE* pAce = NULL; bool bFound = false; _tprintf(_T("Entering DelAce ...\n")); //Get Acl Info BOOL fFlag = GetAclInformation(g_pDACL, &aclSizeInfo, sizeof(aclSizeInfo),AclSizeInformation); if(fFlag == FALSE) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("GetAclInformation failed. hr = %x \n"), hr); goto Exit; } lptstrDomainName = new TCHAR[dwDomainBufferSize]; if (lptstrDomainName == NULL) { hr = E_OUTOFMEMORY; _tprintf(_T("malloc for lptstrDomainName failed. hr = %x \n"), hr); goto Exit; } memset(lptstrDomainName, 0, dwDomainBufferSize*sizeof(TCHAR)); //Get SID from AccountName if(!LookupAccountName(NULL, lptstrAccName, pSID, &dwSIDBufferSize, lptstrDomainName, &dwDomainBufferSize, &eSidType)) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("LookupAccountName failed for Account name %s\\%s. hr = %x \n"), lptstrDomainName, lptstrAccName, hr); goto Exit; } //Is valid SID? if (IsValidSid(pSID) == FALSE) { _tprintf(_T("The SID for %s is invalid. \n"),lptstrAccName); hr = MQ_ERROR; goto Exit; } // Iterate thru the ACE list to get the correct ACE for (UINT cAce = 0; cAce < aclSizeInfo.AceCount; cAce++) { if (!GetAce(g_pDACL, cAce, (LPVOID*)&pAce)) { dwErrorCode = GetLastError(); hr =HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("GetAce failed. hr = %x \n"), hr); goto Exit; } //Compare the ACE SID with the account SID if (EqualSid((PSID)&pAce->SidStart, pSID)) { //Match the Access Mask if(pAce->Mask & dwAccessMask) { //Compare the ACE type if((bDeny && (pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE))|| (!bDeny && (pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE))) { _tprintf(_T("Found the Ace. Now Deleting \n")); //Found the correct ACE. Delete it. if (DeleteAce(g_pDACL, cAce ) == FALSE) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("DeleteAce failed. hr = %x \n"), hr); goto Exit; } bFound = true; break; } } } } if(bFound == false) _tprintf(_T("Couldn't find ACE to delete \n")); Exit: if(lptstrDomainName) delete lptstrDomainName; return hr; } //+--------------------------------------------------------------------------- // // function: CreateNewSD // // Synopsis: Create a NEW SD using the New DACL // // Arguments: None // // Returns: HRESULT S_OK if successful //---------------------------------------------------------------------------- HRESULT CreateNewSD() { DWORD dwErrorCode = 0; HRESULT hr = S_OK; PSECURITY_DESCRIPTOR pSDNew = NULL; _tprintf(_T("Entering CreateNewSD...\n")); pSDNew = new SECURITY_DESCRIPTOR; if (pSDNew == NULL) { hr = E_OUTOFMEMORY; _tprintf(_T("new for new Security Descriptor failed. hr = %x \n"), hr); goto Exit; } //Initialize the new SD if (!InitializeSecurityDescriptor(pSDNew, SECURITY_DESCRIPTOR_REVISION)) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("InitializeSecurityDescriptor failed. hr = %x \n"), hr); goto Exit; } //Set the new DACL if(!SetSecurityDescriptorDacl(pSDNew,true,g_pDACL,false)) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("SetSecurityDescriptorDacl failed. hr = %x \n"), hr); goto Exit; } //Is Valid SD? if(!IsValidSecurityDescriptor(pSDNew)) { _tprintf(_T("SecurityDescriptor not valid failed. \n ")); goto Exit; } SECURITY_DESCRIPTOR_CONTROL sdControl = NULL; DWORD dwRevision = NULL; //Check if the SD is relative or absolute if(!GetSecurityDescriptorControl(pSDNew, &sdControl, &dwRevision)) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("GetSecurityDescriptorControl failed. hr = %x \n"), hr); goto Exit; } if( sdControl& SE_SELF_RELATIVE ) { _tprintf(_T("Security Descriptor is relative \n")); g_pSecurityDescriptorNew = pSDNew; } else { //if absolute convert to relative _tprintf(_T("Security Descriptor is aboslute. Converting to relative. \n")); PSECURITY_DESCRIPTOR pSDRelative = g_bSecurityDescriptor; g_dwLength = SD_LENGTH; //convert to relative MakeSelfRelativeSD(pSDNew, &g_bSecurityDescriptor, &g_dwLength); //verify if it is relative? GetSecurityDescriptorControl(&g_bSecurityDescriptor, &sdControl, &dwRevision); if(sdControl & SE_SELF_RELATIVE ) { _tprintf(_T("Security Descriptor is relative. \n")); } else { _tprintf(_T("Security Descriptor is absolute.\n")); } //is valid SD? if(!IsValidSecurityDescriptor(pSDRelative)) { _tprintf(_T("SecurityDescriptor not valid failed. \n")); goto Exit; } if(pSDNew) delete pSDNew; g_pSecurityDescriptorNew = pSDRelative; } Exit: if((hr != S_OK) && pSDNew) delete pSDNew; return hr; } //+--------------------------------------------------------------------------- // // function: CopyRemainingACL // // Synopsis: Copies the old ACEs from FaxSecurity object to the new SD // // Arguments: [pDest] : destination PACL // [pSrc] : source PACL // // Returns: HRESULT S_OK if successful //+---------------------------------------------------------------------------- HRESULT CopyRemainingACL(PACL pDest, PACL pSrc) { HRESULT hr = S_OK; ACL_SIZE_INFORMATION aclSizeInfo; LPVOID pAce; _tprintf(_T("Entering CopyRemainingACL ...\n")); if (pSrc == NULL) { _tprintf(_T("Source is NULL \n")); return hr; } if (pDest == NULL) return E_POINTER; if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) return HRESULT_FROM_WIN32(GetLastError()); // Copy all of the ACEs to the new ACL for (UINT i = 0; i < aclSizeInfo.AceCount; i++) { if (!GetAce(pSrc, i, &pAce)) { hr = HRESULT_FROM_WIN32(GetLastError()); break; } if (!AddAce(pDest, ACL_REVISION, MAXDWORD, pAce, ((PACE_HEADER)pAce)->AceSize)) { hr = HRESULT_FROM_WIN32(GetLastError()); break; } } return hr; } //+--------------------------------------------------------------------------- // // function: DeleteAceFax // // Synopsis: Delete the ACE from the SD. Calls DelAce to delete from DACL // // Arguments: [pFaxSecurity] : FaxSecurity Object // [bDeny] - is it a Deny Ace? // [lptstrAccName] : Account from where to delete the ACE // [dwAccessMask] : The Access Mask to delete // // Returns: BOOL True if successful //---------------------------------------------------------------------------- bool DeleteAceFax(IFaxSecurity2* pFaxSecurity,BOOL bDeny, LPTSTR lptstrAccName, DWORD dwAccessMask) { //Get the SD parts, delete the ACE and create new DACL and then create SD from it HRESULT hr = S_OK; bool bRetVal = false; _tprintf(_T(" Entering DeleteAceFax ...\n")); hr = GetSDParts(pFaxSecurity); if(FAILED(hr)) { _tprintf(_T("GetSDParts failed. Error %x \n"), hr); bRetVal = false; goto Exit; } hr = DelAce(bDeny, lptstrAccName, dwAccessMask); if(FAILED(hr)) { _tprintf(_T("DelAce failed. Error %x \n"), hr); bRetVal = false; goto Exit; } hr = CreateNewSD(); if(FAILED(hr)) { _tprintf(_T("CreateNewSD failed. Error %x \n"), hr); bRetVal = false; goto Exit; } bRetVal = true; Exit: return bRetVal; } //+--------------------------------------------------------------------------- // // function: AddDenyAce // // Synopsis: Add Deny ACE and then copy the old ACEs to the DACL // // Arguments: [lptstrAccName] : Account from where to delete the ACE // [dwAccessMask] : The Access Mask to delete // // Returns: HRESULT S_OK if successful //---------------------------------------------------------------------------- HRESULT AddDenyAce(LPTSTR lptstrAccName, DWORD dwAccessMask) { HRESULT hr = S_OK; BYTE bSIDBuffer[SD_LENGTH1] = {0}; PSID pSID = &bSIDBuffer; DWORD dwSIDBufferSize = SD_LENGTH1; DWORD dwDomainBufferSize = SD_LENGTH1; LPTSTR lptstrDomainName = NULL; SID_NAME_USE eSidType; ACL_SIZE_INFORMATION aclSizeInfo; DWORD dwErrorCode = 0; PACL pNewACL = NULL; _tprintf(_T("Entering AddDenyAce...\n")); //Get ACL Info BOOL fFlag = GetAclInformation(g_pDACL, &aclSizeInfo, sizeof(aclSizeInfo),AclSizeInformation); if(fFlag == FALSE) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("GetAclInformation failed. hr = %x \n"), hr); goto Exit; } lptstrDomainName = new TCHAR[dwDomainBufferSize]; if (lptstrDomainName == NULL) { hr = E_OUTOFMEMORY; _tprintf(_T("malloc for lptstrDomainName failed. hr = %x \n"), hr); goto Exit; } memset(lptstrDomainName, 0, dwDomainBufferSize*sizeof(TCHAR)); //Get the SID for the account name if(!LookupAccountName(NULL, lptstrAccName, pSID, &dwSIDBufferSize, lptstrDomainName, &dwDomainBufferSize, &eSidType)) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("LookupAccountName failed for Account name %s\\%s. hr = %x \n"), lptstrDomainName, lptstrAccName, hr); goto Exit; } if (IsValidSid(pSID) == FALSE) { hr = MQ_ERROR; _tprintf(_T("The SID for %s is invalid. hr = %x \n"),lptstrAccName, hr); goto Exit; } //Check Duplicate ACE if(IsAcePresent(pSID, true, dwAccessMask, aclSizeInfo.AceCount)) { hr = S_OK; _tprintf(_T("The ACE is already present. hr = %x \n"), hr); goto Exit; } //Allocate memory for new ACL int aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(pSID) - sizeof(DWORD); pNewACL = (PACL) new BYTE[aclSize]; if (pNewACL == NULL) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("malloc for new ACL failed. hr = %x \n"), hr); goto Exit; } if (!InitializeAcl(pNewACL, aclSize, ACL_REVISION)) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("InitializeAcl failed. hr = %x \n"), hr); goto Exit; } //Add access denied ace if(!AddAccessDeniedAce(pNewACL, ACL_REVISION , dwAccessMask, pSID)) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("AddAccessDeniedAce failed. hr = %x \n"), hr); goto Exit; } //copy the remaining from the old ACL hr = CopyRemainingACL(pNewACL, g_pDACL); if(hr != S_OK) { _tprintf(_T("CopyRemainingACL failed. HRESULT returned: %x \n"), hr); goto Exit; } g_pDACL = pNewACL; Exit: if((hr != S_OK) && pNewACL) free(pNewACL); if(lptstrDomainName) delete lptstrDomainName; return hr; } //+--------------------------------------------------------------------------- // // function: AddAllowAce // // Synopsis: Add Allow ACE and then copy the old ACEs to the DACL // // Arguments: [lptstrAccName] : Account from where to delete the ACE // [dwAccessMask] : The Access Mask to delete // // Returns: HRESULT S_OK if successful //---------------------------------------------------------------------------- HRESULT AddAllowAce(LPTSTR lptstrAccName, DWORD dwAccessMask) { HRESULT hr = S_OK; BYTE bSIDBuffer[SD_LENGTH1] = {0}; PSID pSID = &bSIDBuffer; DWORD dwSIDBufferSize = SD_LENGTH1; DWORD dwDomainBufferSize = SD_LENGTH1; LPTSTR lptstrDomainName = NULL; SID_NAME_USE eSidType; ACL_SIZE_INFORMATION aclSizeInfo; DWORD dwErrorCode = 0; _tprintf(_T("Entering AddAllowAce...\n")); //Get Acl Info BOOL fFlag = GetAclInformation(g_pDACL, &aclSizeInfo, sizeof(aclSizeInfo),AclSizeInformation); if(fFlag == FALSE) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("GetAclInformation failed. hr = %x \n"), hr); goto Exit; } lptstrDomainName = new TCHAR[dwDomainBufferSize]; if (lptstrDomainName == NULL) { hr = E_OUTOFMEMORY; _tprintf(_T("malloc for lptstrDomainName failed. hr = %x \n"), hr); goto Exit; } memset(lptstrDomainName, 0, dwDomainBufferSize*sizeof(TCHAR)); //Get the SID from the acc name if(!LookupAccountName(NULL, lptstrAccName, pSID, &dwSIDBufferSize, lptstrDomainName, &dwDomainBufferSize, &eSidType)) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("LookupAccountName failed for Account name %s\\%s. hr = %x \n"), lptstrDomainName, lptstrAccName, hr); goto Exit; } if (IsValidSid(pSID) == FALSE) { _tprintf(L"The SID for %s is invalid.\n", lptstrAccName); hr = MQ_ERROR; _tprintf(_T("IsValidSid failed. hr = %x \n"), hr); goto Exit; } //Check Duplicate ACE if(IsAcePresent(pSID, false, dwAccessMask, aclSizeInfo.AceCount)) { hr = S_OK; _tprintf(_T("The ACE is already present. hr = %x \n"), hr); goto Exit; } //allocate memory for new ACL PACL pNewACL = NULL; int aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSID) - sizeof(DWORD); pNewACL = (PACL) new BYTE[aclSize]; if (pNewACL == NULL) { hr = E_OUTOFMEMORY; _tprintf(_T("malloc for new ACL failed. hr = %x \n"), hr); goto Exit; } if (!InitializeAcl(pNewACL, aclSize, ACL_REVISION)) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("InitializeAcl failed. hr = %x \n"), hr); goto Exit; } //add access allowed ace if(!AddAccessAllowedAce(pNewACL, ACL_REVISION , dwAccessMask, pSID)) { dwErrorCode = GetLastError(); hr = HRESULT_FROM_WIN32(dwErrorCode); _tprintf(_T("AddAccessAllowedAce failed. hr = %x \n"), hr); goto Exit; } //copy the remaining ACEs from the old ACL hr = CopyRemainingACL(pNewACL, g_pDACL); if(hr != S_OK) { _tprintf(_T("CopyRemainingACL failed. hr = %x\n"), hr); goto Exit; } g_pDACL = pNewACL; Exit: if((hr != S_OK) && pNewACL) free(pNewACL); delete lptstrDomainName; return hr; } //+--------------------------------------------------------------------------- // // function: AddAllowAceFax // // Synopsis: Add Allow Ace // // Arguments: [pFaxSecurity] : FaxSecurity Object // [lptstrAccName] : Account from where to delete the ACE // [dwAccessMask] : The Access Mask to delete // // Returns: bool true if successful //---------------------------------------------------------------------------- bool AddAllowAceFax(IFaxSecurity2* pFaxSecurity, LPTSTR lptstrAccName, DWORD dwAccessMask) { //Get the SD parts, create new DACL and then create SD from it HRESULT hr = S_OK; bool bRetVal = false; _tprintf(_T("Entering AddAllowAceFax ...\n")); hr = GetSDParts(pFaxSecurity); if(FAILED(hr)) { _tprintf(_T("GetSDParts failed. Error %x \n"), hr); bRetVal = false; goto Exit; } hr = AddAllowAce(lptstrAccName, dwAccessMask); if(FAILED(hr)) { _tprintf(_T("AddAllowAce failed. Error %x \n"), hr); bRetVal = false; goto Exit; } hr = CreateNewSD(); if(FAILED(hr)) { _tprintf(_T("CreateNewSD failed. Error %x \n"), hr); bRetVal = false; goto Exit; } bRetVal = false; Exit: return bRetVal; } //+--------------------------------------------------------------------------- // // function: AddDenyAceFax // // Synopsis: Add Deny Ace // // Arguments: [pFaxSecurity] : FaxSecurity Object // [lptstrAccName] : Account from where to delete the ACE // [dwAccessMask] : The Access Mask to delete // // Returns: bool: true if successful //---------------------------------------------------------------------------- bool AddDenyAceFax(IFaxSecurity2* pFaxSecurity, LPTSTR lptstrAccName, DWORD dwAccessMask) { //Get the SD parts, create new DACL and then create SD from it HRESULT hr = S_OK; bool bRetVal = false; hr = GetSDParts(pFaxSecurity); if(FAILED(hr)) { _tprintf(_T("GetSDParts failed. Error %x \n"), hr); bRetVal = false; goto Exit; } hr = AddDenyAce(lptstrAccName, dwAccessMask); if(FAILED(hr)) { _tprintf(_T("AddDenyAce failed. Error %x \n"), hr); bRetVal = false; goto Exit; } hr = CreateNewSD(); if(FAILED(hr)) { _tprintf(_T("CreateNewSD failed. Error %x \n"), hr); bRetVal = false; goto Exit; } bRetVal = true; Exit: return bRetVal; } //+--------------------------------------------------------------------------- // // function: SetFaxSecurity // // Synopsis: Set the Fax Security Object // // Arguments: [pFaxSecurity] : FaxSecurity Object // // Returns: bool true if successful //---------------------------------------------------------------------------- bool SetFaxSecurity(IFaxSecurity2* pFaxSecurity) { HRESULT hr = S_OK; //Cnvert to Byte array BYTE* pbDataSD = (BYTE*) &g_bSecurityDescriptor; SAFEARRAY *pSafeArray; //Create a VARIANT object from SD pSafeArray = SafeArrayCreateVector(VT_UI1, 0, g_dwLength); if (pSafeArray == NULL) { hr = E_OUTOFMEMORY; _tprintf(_T("SafeArrayCreateVector failed. hr = %x \n"), hr); goto Exit; } //get Access to the elements of the Safe Array BYTE *pbElement; hr = SafeArrayAccessData(pSafeArray, (void **) &pbElement); if (FAILED(hr)) { //Failed to access safearray hr = E_FAIL; SafeArrayDestroy(pSafeArray); _tprintf(_T("SafeArrayAccessData failed. hr = %x \n"), hr); goto Exit; } // Fill the Safe Array with the bytes from pbDataSD memcpy(pbElement, pbDataSD, g_dwLength); hr = SafeArrayUnaccessData(pSafeArray); if (FAILED(hr)) { //Failed to unaccess safearray hr = E_FAIL; SafeArrayDestroy(pSafeArray); _tprintf(_T("SafeArrayUnaccessData failed. hr = %x \n"), hr); goto Exit; } VARIANT pvarNewSD; VariantInit(&pvarNewSD); pvarNewSD.vt = VT_UI1 | VT_ARRAY; pvarNewSD.parray = pSafeArray; //Set the new SD hr = pFaxSecurity->put_InformationType(DACL_SECURITY_INFORMATION); if(FAILED(hr)) { _tprintf(_T("put_InformationType failed. hr = %x \n"), hr); goto Exit; } hr = pFaxSecurity->put_Descriptor(pvarNewSD); if(FAILED(hr)) { _tprintf(_T("put_Descriptor failed. hr = %x \n"), hr); goto Exit; } hr = pFaxSecurity->Save(); if(FAILED(hr)) { _tprintf(_T("g_pFaxSecurity->Save failed. hr = %x \n"), hr); goto Exit; } Exit: VariantClear(&pvarNewSD); return (hr == S_OK); } int __cdecl _tmain(int argc, _TCHAR* argv[]) { HRESULT hr = S_OK; bool bRetVal = true; TCHAR* lptstrServerName = NULL; TCHAR* lptstrOption = NULL; TCHAR* lptstrAccessMask = NULL; TCHAR* lptstrDeny = NULL; TCHAR* lptstrAccName = NULL; BSTR bstrServerName = NULL; BOOL bDeny = TRUE; DWORD dwAccessMask = 0; bool bConnected = false; size_t argSize = 0; bool bVersion = IsOSVersionCompatible(VISTA); //Check is OS is Vista if(bVersion == false) { _tprintf(_T("OS Version does not support this feature")); bRetVal = false; goto Exit1; } //introducing an artifical scope here so that the COM objects are destroyed before CoInitialize is called { //COM objects IFaxServer2* pFaxServer =NULL; IFaxSecurity2* pFaxSecurity =NULL; int argcount = 0; int count = 0; #ifdef UNICODE argv = CommandLineToArgvW( GetCommandLine(), &argc ); #else argv = argvA; #endif if (argc == 1) { _tprintf( TEXT("Missing args.\n") ); GiveUsage(argv[0]); bRetVal = false; goto Exit; } // check for commandline switches for (argcount=1; argcountConnect(bstrServerName); if(FAILED(hr)) { _tprintf(_T("Connect failed. Error 0x%x \n"), hr); bRetVal = false; goto Exit; } bConnected = true; FAX_SERVER_APIVERSION_ENUM enumFaxAPIVersion; hr = pFaxServer->get_APIVersion(&enumFaxAPIVersion); if(FAILED(hr)) { //get_APIVersion failed. _tprintf(_T("get_APIVersion failed. Error 0x%x \n"), hr); bRetVal = false; goto Exit; } if (enumFaxAPIVersion < fsAPI_VERSION_3) { bRetVal = false; _tprintf(_T("OS Version does not support this feature")); goto Exit; } hr = pFaxServer->get_Security2(&pFaxSecurity); if(FAILED(hr)) { _tprintf(_T("get_Security failed. Error %x \n"), hr); bRetVal = false; goto Exit; } if(_tcscmp(_T("print"), CharLower(lptstrOption)) == 0) { //print aces bRetVal = PrintACEsFax(pFaxSecurity); if(bRetVal == false) { _tprintf(_T("PrintACEsFax Failed")); goto Exit; } _tprintf(_T("\n \nDone with printing of ACE \n")); } if(_tcscmp(_T("add"), CharLower(lptstrOption)) == 0) { //Add the appropiate ACE and create a new SD if(bDeny) { bRetVal = AddDenyAceFax(pFaxSecurity, lptstrAccName,dwAccessMask); if(bRetVal == false) { _tprintf(_T("AddDenyAceFax Failed")); goto Exit; } } else { bRetVal = AddAllowAceFax(pFaxSecurity, lptstrAccName,dwAccessMask); if(bRetVal == false) { _tprintf(_T("AddAllowAceFax Failed")); goto Exit; } } if(bRetVal == true ) { //Set the FaxSecurity with new SD bRetVal = SetFaxSecurity(pFaxSecurity); if(bRetVal == false) { _tprintf(_T("SetFaxSecurity Failed")); goto Exit; } } _tprintf(_T("\n \n Done with addition of ACE \n")); } if(_tcscmp(_T("delete"), CharLower(lptstrOption)) == 0) { //Delete the appropiate ACE and create a new SD bRetVal = DeleteAceFax(pFaxSecurity, bDeny, lptstrAccName, dwAccessMask); if(bRetVal == false) { _tprintf(_T("DeleteAceFax Failed")); goto Exit; } if(bRetVal == true) { //Set the FaxSecurity with new SD bRetVal = SetFaxSecurity(pFaxSecurity); if(bRetVal == false) { _tprintf(_T("SetFaxSecurity Failed")); goto Exit; } } _tprintf(_T("\n \n Done with deletion of ACE \n")); } Exit: if(bConnected) { pFaxServer->Disconnect(); } if(lptstrServerName) free(lptstrServerName); if(lptstrOption) free(lptstrOption); if(lptstrAccessMask) free(lptstrAccessMask); if(lptstrAccName) free(lptstrAccName); if(lptstrDeny) free(lptstrDeny); } CoUninitialize(); Exit1: return bRetVal; }