您的位置:首页 > 其它

Win32安全程序设计:文件夹的权限设置

2008-07-02 20:42 513 查看
最近两天在一家公司做兼职。刚去公司,老板就分配了一个任务。公司里有一个软件,在编辑自己产生的文件后,点击保存,文件就会自动上传到服务器进行备份,并立即删除本地的文件。给我的任务是:在Windows2000下,文件夹的属性中的安全选项卡是用户能够看到的。并且一般的用户都可以通过这个安全编辑对话框来更改文件夹的权限。问题是这样的:如果用户把文件夹的删除权限设置为拒绝,那么本地的文件只能上传到服务器,而本地的文件是删不掉的了。老板希望我想一个办法把文件夹的属性中的安全选项卡屏蔽掉。刚刚面试完,不敢说不会,只好满口答应,向老板保证,我一定会尽力去解决的。

在仔细研究了所面对的问题并上网查找了一些资料后,我觉得可以用一种变通的办法来达到同样的效果。那就是:当用户把删除权限设置为拒绝后,我就会检测到,然后再把它改过来。哈哈。不失为一种解决方案。在对Windows安全系统及编程接口完全不熟悉的情况下,我觉得能做到多少就努力做到多少吧。后来老板也很赞同我的想法。从他和我说话的表情和语气。^_^

下面就是我的代码。当然大量参考了Jeffrey Richter先生的宝书《Programming Server-Side Applications for Microsoft Windows 2000》。这是一本很好的书,可惜市面上已经买不到了。自古红颜多薄命,难道好书也像美人一样?幸好,我有英文电子版,可以解一时之急。讲解Win32安全编程机制的书也不多,这是其中的一本。


#include "stdafx.h"


#include <windows.h>


#include <Aclapi.h>


#include <AccCtrl.h>


#include <Sddl.h>


#include <iostream>


using namespace std;




#define PSIDFromPACE(pACE) ((PSID)(&((pACE)->SidStart)))






typedef union _ACE_UNION...{


ACE_HEADER aceHeader;


ACCESS_ALLOWED_ACE aceAllowed;


ACCESS_DENIED_ACE aceDenied;


SYSTEM_AUDIT_ACE aceAudit;


}*PACE_UNION;




void DumpACL(PACL pACL);


DWORD DelAceAndSetACL(PACL pACL, PSID psid, TCHAR *pszBuf);


void GrantDeleteRight(TCHAR *pszBuf, PSID psid, PACL pOldDACL, PACL *pNewDACL);


ULONG CalculateACLSize(PACL pACLOld, PSID* ppSidArray, int nNumSids, PACE_UNION* ppACEs, int nNumACEs);


PACE_UNION AllocateACE(ULONG bACEType, ULONG bACEFlags, ULONG lAccessMask, PSID pSID);


ULONG GetACEInsertionIndex(PACL pDACL, PACE_UNION pACENew);


BOOL CopyACL( PACL pACLDestination, PACL pACLSource );


int FindACEInACL( PACL pACL, PACE_UNION pACE );


BOOL IsEqualACE( PACE_UNION pACE1, PACE_UNION pACE2 );


LPVOID AllocateTokenInformation(HANDLE hToken, TOKEN_INFORMATION_CLASS tokenClass);






struct...{


BYTE lACEType;


PTSTR pszTypeName;




}aceTypes[6] = ...{




...{ACCESS_ALLOWED_ACE_TYPE, TEXT("ACCESS_ALLOWED_ACE_TYPE")},




...{ACCESS_DENIED_ACE_TYPE, TEXT("ACCESS_DENIED_ACE_TYPE")},




...{SYSTEM_AUDIT_ACE_TYPE, TEXT("SYSTEM_AUDIT_ACE_TYPE")},




...{ACCESS_ALLOWED_OBJECT_ACE_TYPE, TEXT("ACCESS_ALLOWED_OBJECT_ACE_TYPE")},




...{ACCESS_DENIED_OBJECT_ACE_TYPE, TEXT("ACCESS_DENIED_OBJECT_ACE_TYPE")},




...{SYSTEM_AUDIT_OBJECT_ACE_TYPE, TEXT("SYSTEM_AUDIT_OBJECT_ACE_TYPE")}};






struct...{


ULONG lACEFlag;


PTSTR pszFlagName;




}aceFlags[7] = ...{




...{INHERITED_ACE, TEXT("INHERITED_ACE")},




...{CONTAINER_INHERIT_ACE, TEXT("CONTAINER_INHERIT_ACE")},




...{OBJECT_INHERIT_ACE, TEXT("OBJECT_INHERIT_ACE")},




...{INHERIT_ONLY_ACE, TEXT("INHERIT_ONLY_ACE")},




...{NO_PROPAGATE_INHERIT_ACE, TEXT("NO_PROPAGATE_INHERIT_ACE")},




...{FAILED_ACCESS_ACE_FLAG, TEXT("FAILED_ACCESS_ACE_FLAG")},




...{SUCCESSFUL_ACCESS_ACE_FLAG, TEXT("SUCCESSFUL_ACCESS_ACE_FLAG")}};




int _tmain(int argc, _TCHAR* argv[])




...{


SECURITY_ATTRIBUTES sa;


SECURITY_DESCRIPTOR sd;


PSID psid = NULL;




// 获得当前用户的SID和默认的DACL。


HANDLE hToken;




if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))...{


// Error


_tprintf(_T("OpenProcessToken Failed."));


return 1;


}


TOKEN_USER* ptUser = (TOKEN_USER*)AllocateTokenInformation(hToken, TokenUser);




if (ptUser != NULL)...{


psid = ptUser->User.Sid;


}


TOKEN_DEFAULT_DACL* ptDACL = (TOKEN_DEFAULT_DACL*)AllocateTokenInformation(hToken, TokenDefaultDacl);




if (ptDACL != NULL)...{


DumpACL(ptDACL->DefaultDacl);


}




// 初始化sd。使用当前用户的默认DACL。


InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);


SetSecurityDescriptorDacl(&sd, TRUE, ptDACL->DefaultDacl, FALSE);


// 初始化sa。


sa.nLength= sizeof(SECURITY_ATTRIBUTES);


sa.bInheritHandle = FALSE;


sa.lpSecurityDescriptor = &sd;


// 创建一个指定文件夹名和具有上面安全属性的文件夹。


TCHAR szPathBuf[MAX_PATH];


_tprintf(_T("Input the directory: "));


_tscanf(_T("%s"), szPathBuf);


CreateDirectory(szPathBuf, &sa);




DWORD dwRes = 0;


PACL pOldDACL = NULL, pNewDACL = NULL;


PSECURITY_DESCRIPTOR pSD = NULL;


// Get a pointer to the existing DACL.


dwRes = GetNamedSecurityInfo(szPathBuf, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDACL, NULL, &pSD);




if (ERROR_SUCCESS != dwRes) ...{


_tprintf(_T("GetNamedSecurityInfo Error %u "), dwRes);


return 1;


}




DumpACL(pOldDACL);




if (DelAceAndSetACL(pOldDACL, psid, szPathBuf) == ERROR_SUCCESS) ...{


GrantDeleteRight(szPathBuf, psid, pOldDACL, &pNewDACL);


DumpACL(pNewDACL);


}




else ...{


GrantDeleteRight(szPathBuf, psid, pOldDACL, &pNewDACL);


DumpACL(pNewDACL);


}


LocalFree(pSD);




return 0;


}




DWORD DelAceAndSetACL(PACL pACL, PSID psid, TCHAR *pszBuf)




...{


DWORD dwRes = -1;




__try ...{




ACL_SIZE_INFORMATION aclSize = ...{0};


if (!GetAclInformation(pACL, &aclSize, sizeof(aclSize), AclSizeInformation))


__leave;






for (ULONG lIndex = 0; lIndex < aclSize.AceCount; lIndex++) ...{


ACCESS_ALLOWED_ACE* pACE;


if (!GetAce(pACL, lIndex, (PVOID*)&pACE))


__leave;




bool flag16 = false, flag26 = false;


int cnt = 0;


ULONG lIndex2 = (ULONG)1<<31;




while (lIndex2) ...{


++cnt;




if (cnt == 16 && ((pACE->Mask & lIndex2) != 0)) ...{


flag16 = true;


}




if (cnt == 26 && ((pACE->Mask & lIndex2) != 0)) ...{


flag26 = true;


}


lIndex2 >>= 1;


if (flag16 || flag26)


break;


}




if ((flag16 || flag26) && pACE->Header.AceType == ACCESS_DENIED_ACE_TYPE) ...{


::DeleteAce(pACL, lIndex);


--lIndex;


--aclSize.AceCount;




dwRes = SetNamedSecurityInfo(pszBuf, SE_FILE_OBJECT,


DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,


psid, NULL, pACL, NULL);


if (ERROR_SUCCESS != dwRes)


printf("SetNamedSecurityInfo Error %u ", dwRes);




flag16 = flag26 = false;


}


}




}__finally ...{}




return dwRes;


}




void GrantDeleteRight(TCHAR *pszBuf, PSID psid, PACL pOldDACL, PACL *pNewDACL)




...{


PSID psidArray[1];


psidArray[0] = psid;




// Get the size of the new ACL


ULONG lACLSize = CalculateACLSize(pOldDACL, psidArray, 1, NULL, 1);




if (lACLSize == 0)...{


// Error


}


// Allocate memory for the ACL


*pNewDACL = (PACL)HeapAlloc(GetProcessHeap(), 0, lACLSize);




if (pNewDACL == NULL) ...{


// Error


}


// Initialize the ACL




if (!InitializeAcl(*pNewDACL, lACLSize, ACL_REVISION))...{


// Error


}


PACE_UNION pNewACE = AllocateACE(


ACCESS_ALLOWED_ACE_TYPE,


NULL,


GENERIC_ALL | FILE_DELETE_CHILD | DELETE,


psid


);




// 如果ACL中有相同的ACE则返回。


if (FindACEInACL(*pNewDACL, pNewACE) != -1)


return;




CopyACL(*pNewDACL, pOldDACL);


// Get location for new ACE


ULONG lIndex = GetACEInsertionIndex(*pNewDACL, pNewACE);


// Add the new ACE


if (!AddAce(*pNewDACL, ACL_REVISION, lIndex, pNewACE, pNewACE->aceHeader.AceSize))


printf("Error!");




DWORD dwRes = SetNamedSecurityInfo(pszBuf, SE_FILE_OBJECT,


DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,


psid, NULL, *pNewDACL, NULL);


if (ERROR_SUCCESS != dwRes)


printf("SetNamedSecurityInfo Error %u ", dwRes);


}






void DumpACL(PACL pACL)...{




__try...{




if (pACL == NULL)...{


_tprintf(TEXT("NULL DACL "));


__leave;


}






ACL_SIZE_INFORMATION aclSize = ...{0};


if (!GetAclInformation(pACL, &aclSize, sizeof(aclSize), AclSizeInformation))


__leave;


_tprintf(TEXT("ACL ACE count: %d "), aclSize.AceCount);






for (ULONG lIndex = 0;lIndex < aclSize.AceCount;lIndex++)...{


ACCESS_ALLOWED_ACE* pACE;


if (!GetAce(pACL, lIndex, (PVOID*)&pACE))


__leave;




_tprintf(TEXT(" ACE #%d "), lIndex);




ULONG lIndex2 = 6;


PTSTR pszString = TEXT("Unknown ACE Type");




while (lIndex2--)...{




if(pACE->Header.AceType == aceTypes[lIndex2].lACEType) ...{


pszString = aceTypes[lIndex2].pszTypeName;


}


}


_tprintf(TEXT(" ACE Type = %s "), pszString);




_tprintf(TEXT(" ACE Flags = "));


lIndex2 = 7;




while (lIndex2--) ...{


if ((pACE->Header.AceFlags & aceFlags[lIndex2].lACEFlag)


!= 0)


_tprintf(TEXT(" %s "),


aceFlags[lIndex2].pszFlagName);


}




_tprintf(TEXT(" ACE Mask (32->0) = "));


lIndex2 = (ULONG)1<<31;




while (lIndex2) ...{


_tprintf(((pACE->Mask & lIndex2) != 0)?TEXT("1"):TEXT("0"));


lIndex2>>=1;


}




TCHAR szName[1024];


TCHAR szDom[1024];


PSID pSID = PSIDFromPACE(pACE);


SID_NAME_USE sidUse;


ULONG lLen1 = 1024, lLen2 = 1024;


if (!LookupAccountSid(NULL, pSID, szName, &lLen1, szDom, &lLen2, &sidUse))


lstrcpy(szName, TEXT("Unknown"));


PTSTR pszSID;


if (!ConvertSidToStringSid(pSID, &pszSID))


__leave;


_tprintf(TEXT(" ACE SID = %s (%s) "), pszSID, szName);


LocalFree(pszSID);


}




}__finally...{}


}




LPVOID AllocateTokenInformation(HANDLE hToken, TOKEN_INFORMATION_CLASS tokenClass)




...{


PVOID pvBuffer = NULL;




__try...{


BOOL fSuccess;


// Initial buffer size


ULONG lSize = 0 ;


do




...{


// Do we have a size yet?


if (lSize != 0)




...{


// Do we already have a buffer?


if (pvBuffer != NULL)


LocalFree(pvBuffer);// Then free it


// Allocate a new buffer


pvBuffer = LocalAlloc(LPTR, lSize) ;


if(pvBuffer == NULL)


__leave;


}




// Try again


fSuccess = GetTokenInformation( hToken, tokenClass,


pvBuffer, lSize, &lSize ) ;


// Still not enough buffer?


}while( !fSuccess && (GetLastError() ==


ERROR_INSUFFICIENT_BUFFER)) ;




// If we failed for some other reason, back out


if(!fSuccess)




...{


if(pvBuffer)


LocalFree(pvBuffer) ;


pvBuffer = NULL;


}




}__finally...{}


// Return locally allocated buffer


return (pvBuffer) ;


}




ULONG CalculateACLSize(PACL pACLOld, PSID* ppSidArray, int nNumSids, PACE_UNION* ppACEs, int nNumACEs)




...{


ULONG lACLSize = 0;






try...{


// If we are including an existing ACL, then find its size




if (pACLOld != NULL)...{


ACL_SIZE_INFORMATION aclSize;




if(!GetAclInformation(pACLOld, &aclSize, sizeof(aclSize), AclSizeInformation))...{


goto leave;


}


lACLSize = aclSize.AclBytesInUse;


}






if (ppSidArray != NULL)...{


// Step through each SID




while (nNumSids--)...{


// If a SID isn't valid, then we bail




if (!IsValidSid(ppSidArray[nNumSids]))...{


lACLSize = 0;


goto leave;


}


// Get the SID's length


lACLSize += GetLengthSid(ppSidArray[nNumSids]);


// Add the ACE structure size, minus the


// size of the SidStart member


lACLSize += sizeof(ACCESS_ALLOWED_ACE) - sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart);


}


}






if (ppACEs != NULL)...{


// Step through each ACE




while (nNumACEs--)...{


// Get the SIDs length


lACLSize += ppACEs[nNumACEs]->aceHeader.AceSize;


}


}


// Add in the ACL structure itself


lACLSize += sizeof(ACL);




leave:;




}catch(...)...{


// An exception means we fail the function


lACLSize = 0;


}


return (lACLSize);


}




BOOL CopyACL( PACL pACLDestination, PACL pACLSource )




...{


BOOL fReturn = FALSE;




try ...{


// Get the number of ACEs in the source ACL


ACL_SIZE_INFORMATION aclSize;




if (!GetAclInformation(pACLSource, &aclSize, sizeof(aclSize), AclSizeInformation))...{


goto leave;


}




// Use GetAce and AddAce to copy the ACEs




for(ULONG lIndex=0;lIndex < aclSize.AceCount;lIndex++)...{


ACE_HEADER* pACE;


if(!GetAce(pACLSource, lIndex, (PVOID*)&pACE))


goto leave;


if(!AddAce(pACLDestination, ACL_REVISION, MAXDWORD,


(PVOID*)pACE, pACE->AceSize))


goto leave;


}


fReturn = TRUE;


leave:;




}catch(...)...{


}


return (fReturn);


}




PACE_UNION AllocateACE(ULONG bACEType, ULONG bACEFlags, ULONG lAccessMask, PSID pSID)




...{


PACE_UNION pReturnACE = NULL;


PBYTE pbBuffer = NULL;




try...{


// Get the offset of the SID in the ACE


ULONG lSIDOffset = (ULONG)(&((ACCESS_ALLOWED_ACE*)0)->SidStart);


// Get the size of the ACE without the SID


ULONG lACEStructSize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart);


// Get the length of the SID


ULONG lSIDSize = GetLengthSid(pSID);




// Allocate a buffer for the ACE


pbBuffer = (PBYTE)LocalAlloc(LPTR, lACEStructSize + lSIDSize);


if (pbBuffer == NULL)


goto leave;




// Copy the SID into the ACE




if(!CopySid(lSIDSize, (PSID)(pbBuffer+lSIDOffset), pSID))...{


goto leave;


}


pReturnACE = (PACE_UNION) pbBuffer;


pReturnACE->aceHeader.AceSize = (USHORT)(lACEStructSize + lSIDSize);


pReturnACE->aceHeader.AceType = (BYTE)bACEType;


pReturnACE->aceHeader.AceFlags = (BYTE)bACEFlags;


pReturnACE->aceAllowed.Mask = lAccessMask;


leave:;




}catch(...)...{}


// Free the buffer in an error case




if (pbBuffer != (PBYTE)pReturnACE)...{


LocalFree(pbBuffer);


}


return (pReturnACE);


}




ULONG GetACEInsertionIndex(PACL pDACL, PACE_UNION pACENew)




...{


ULONG lIndex = (ULONG) -1;






try...{


// ACE types by ACL order




ULONG lFilterType[] = ...{ ACCESS_DENIED_ACE_TYPE,


ACCESS_DENIED_OBJECT_ACE_TYPE,


ACCESS_ALLOWED_ACE_TYPE,


ACCESS_ALLOWED_OBJECT_ACE_TYPE};




// Determine which group the new ACE should belong to


ULONG lNewAceGroup;




for(lNewAceGroup = 0; lNewAceGroup<4 ; lNewAceGroup++)...{


if(pACENew->aceHeader.AceType == lFilterType[lNewAceGroup])


break;


}


// If group == 4, the ACE type is no good


if(lNewAceGroup==4)


goto leave;


// If new ACE is an inherited ACE, then it goes after other ACEs


if((pACENew->aceHeader.AceFlags & INHERITED_ACE) != 0)


lNewAceGroup+=4;




// Get ACE count


ACL_SIZE_INFORMATION aclSize;




if (!GetAclInformation(pDACL, &aclSize, sizeof(aclSize), AclSizeInformation))...{


goto leave;


}




// Iterate through ACEs


lIndex = 0;




for(lIndex = 0;lIndex < aclSize.AceCount;lIndex++)...{


ACE_HEADER* pACE;


if(!GetAce(pDACL, lIndex, (PVOID*)&pACE))


goto leave;




// Get the group of the ACL ACE


ULONG lAceGroup;




for(lAceGroup = 0; lAceGroup<4 ; lAceGroup++)...{


if(pACE->AceType == lFilterType[lAceGroup])


break;


}


// Test for bad ACE




if(lAceGroup==4)...{


lIndex = (ULONG) -1;


goto leave;


}


// Inherited adjustment


if((pACE->AceFlags & INHERITED_ACE) != 0)


lAceGroup+=4;




// If this is the same group, then insertion point found


if(lAceGroup>=lNewAceGroup)


break;


}


leave: ;




}catch(...)...{


}


return (lIndex);


}




BOOL IsEqualACE( PACE_UNION pACE1, PACE_UNION pACE2 )




...{


BOOL fReturn = FALSE;






try ...{


if(pACE1->aceHeader.AceType != pACE2->aceHeader.AceType)


goto leave;




// Get the offset of the SID in the ACE


ULONG lSIDOffset = (ULONG)((&((ACCESS_ALLOWED_ACE*)0)->SidStart));


// Get the size of the ACE without the SID


ULONG lACEStructSize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart);




PBYTE pbACE1 = (PBYTE)pACE1;


PBYTE pbACE2 = (PBYTE)pACE2;


fReturn = TRUE;


while(lACEStructSize--)


fReturn = (fReturn && ((pbACE1[lACEStructSize] == pbACE2[lACEStructSize])));


// Check SIDs


fReturn = fReturn && EqualSid((PSID)(pbACE1+lSIDOffset),


(PSID)(pbACE2+lSIDOffset));


leave:;




}catch(...)...{


}




return (fReturn);


}




int FindACEInACL(PACL pACL, PACE_UNION pACE)




...{


int nACEIndex = -1;






try...{


ACL_SIZE_INFORMATION aclSize;




if (!GetAclInformation(pACL, &aclSize, sizeof(aclSize), AclSizeInformation))...{


goto leave;


}






while (aclSize.AceCount--)...{


PACE_UNION pACETemp;


if(!GetAce(pACL, aclSize.AceCount, (PVOID *)&pACETemp))


goto leave;






if(IsEqualACE(pACETemp, pACE))...{


nACEIndex = (int)aclSize.AceCount;


break;


}


}


leave:;




}catch(...)...{


}


return (nACEIndex);


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: