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

 最近两天在一家公司做兼职。刚去公司,老板就分配了一个任务。公司里有一个软件,在编辑自己产生的文件后,点击保存,文件就会自动上传到服务器进行备份,并立即删除本地的文件。给我的任务是:在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); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值