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. |