How to Add an Access-Allowed ACE to a FileLast reviewed: January 21, 1997Article ID: Q102102 |
The information in this article applies to:
SUMMARYThis article explains the process of adding an access-allowed (or access-denied) access control entry (ACE) to a file. Adding an access-allowed ACE to a file's access control list (ACL) provides a means of granting or denying (using an access-denied ACE) access to the file to a particular user or group. In most cases, the file's ACL will not have enough free space to add an additional ACE, and therefore it is usually necessary to create a new ACL and copy the file's existing ACEs over to it. Once the ACEs are copied over and the access-allowed ACE is also added, the new ACL can be applied to the file's security descriptor (SD). This process is explained in detail in the section below. Sample code is provided at the end of this article. Access can be granted or denied to objects other than files by substituting GetKernelObjectSecurity(), GetUserObjectSecurity() or GetPrivateObjectSecurity() for GetFileSecurity().
MORE INFORMATIONAt the end of this article is sample code that defines a function named AddAccessRights(), which adds an access-allowed ACE to the specified file allowing the specified access. Steps 1-17 in the comments of the sample code are discussed in detail below:
Sample Code
#define SD_SIZE (65536 + SECURITY_DESCRIPTOR_MIN_LENGTH)BOOL AddAccessRights(CHAR *pFileName, DWORD dwAcessMask) { // SID variables UCHAR psnuType[2048]; UCHAR lpszDomain[2048]; DWORD dwDomainLength = 250; UCHAR UserSID[1024]; DWORD dwSIDBufSize=1024; // User name variables UCHAR lpszUserName[250]; DWORD dwUserNameLength = 250; // File SD variables UCHAR ucSDbuf[SD_SIZE]; PSECURITY_DESCRIPTOR pFileSD=(PSECURITY_DESCRIPTOR)ucSDbuf; DWORD dwSDLengthNeeded; // ACL variables PACL pACL; BOOL bDaclPresent; BOOL bDaclDefaulted; ACL_SIZE_INFORMATION AclInfo; // New ACL variables PACL pNewACL; DWORD dwNewACLSize; // New SD variables UCHAR NewSD[SECURITY_DESCRIPTOR_MIN_LENGTH]; PSECURITY_DESCRIPTOR psdNewSD=(PSECURITY_DESCRIPTOR)NewSD; // Temporary ACE PVOID pTempAce; UINT CurrentAceIndex; // STEP 1: Get the logged on user name if(!GetUserName(lpszUserName,&dwUserNameLength)) { printf("Error %d:GetUserName\n",GetLastError()); return(FALSE); } // STEP 2: Get SID for current user if (!LookupAccountName((LPSTR) NULL, lpszUserName, UserSID, &dwSIDBufSize, lpszDomain, &dwDomainLength, (PSID_NAME_USE)psnuType)) { printf("Error %d:LookupAccountName\n",GetLastError()); return(FALSE); } // STEP 3: Get security descriptor (SD) for file if(!GetFileSecurity(pFileName, (SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION), pFileSD, SD_SIZE, (LPDWORD)&dwSDLengthNeeded)) { printf("Error %d:GetFileSecurity\n",GetLastError()); return(FALSE); } // STEP 4: Initialize new SD if(!InitializeSecurityDescriptor(psdNewSD,SECURITY_DESCRIPTOR_REVISION)) { printf("Error %d:InitializeSecurityDescriptor\n",GetLastError()); return(FALSE); } // STEP 5: Get DACL from SD if (!GetSecurityDescriptorDacl(pFileSD, &bDaclPresent, &pACL, &bDaclDefaulted)) { printf("Error %d:GetSecurityDescriptorDacl\n",GetLastError()); return(FALSE); } // STEP 6: Get file ACL size information if(!GetAclInformation(pACL,&AclInfo,sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) { printf("Error %d:GetAclInformation\n",GetLastError()); return(FALSE); } // STEP 7: Compute size needed for the new ACL dwNewACLSize = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(UserSID) - sizeof(DWORD); // STEP 8: Allocate memory for new ACL pNewACL = (PACL)LocalAlloc(LPTR, dwNewACLSize); // STEP 9: Initialize the new ACL if(!InitializeAcl(pNewACL, dwNewACLSize, ACL_REVISION2)) { printf("Error %d:InitializeAcl\n",GetLastError()); LocalFree((HLOCAL) pNewACL); return(FALSE); } // STEP 10: If DACL is present, copy it to a new DACL if(bDaclPresent) // only copy if DACL was present { // STEP 11: Copy the file's ACEs to our new ACL if(AclInfo.AceCount) { for(CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++) { // STEP 12: Get an ACE if(!GetAce(pACL,CurrentAceIndex,&pTempAce)) { printf("Error %d: GetAce\n",GetLastError()); LocalFree((HLOCAL) pNewACL); return(FALSE); } // STEP 13: Add the ACE to the new ACL if(!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize)) { printf("Error %d:AddAce\n",GetLastError()); LocalFree((HLOCAL) pNewACL); return(FALSE); } } } } // STEP 14: Add the access-allowed ACE to the new DACL if(!AddAccessAllowedAce(pNewACL,ACL_REVISION2,dwAcessMask, &UserSID)) { printf("Error %d:AddAccessAllowedAce",GetLastError()); LocalFree((HLOCAL) pNewACL); return(FALSE); } // STEP 15: Set our new DACL to the file SD if (!SetSecurityDescriptorDacl(psdNewSD, TRUE, pNewACL, FALSE)) { printf("Error %d:SetSecurityDescriptorDacl",GetLastError()); LocalFree((HLOCAL) pNewACL); return(FALSE); } // STEP 16: Set the SD to the File if (!SetFileSecurity(pFileName, DACL_SECURITY_INFORMATION,psdNewSD)) { printf("Error %d:SetFileSecurity\n",GetLastError()); LocalFree((HLOCAL) pNewACL); return(FALSE); } // STEP 17: Free the memory allocated for the new ACL LocalFree((HLOCAL) pNewACL); return(TRUE);} NOTE: Security descriptors have two possible formats: self-relative and absolute. GetFileSecurity() returns an SD in self-relative format, but SetFileSecurity() expects and absolute SD. This is one reason that the code must create a new SD and copy the information, instead of simply modifying the SD from GetFileSecurity() and passing it to SetFileSecurity(). It is possible to call MakeAbsoluteSD() to do the conversion, but there may not be enough room in the current ACL anyway, as mentioned above.
|
KBCategory: kbprg
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |