Platform SDK: Access Control |
The following example tries to change the DACL of a file object. This will succeed only if the caller has WRITE_DAC access to the object or is the owner of the object. If the initial attempt to change the DACL fails, an administrator can take ownership of the object. To do this, the example enables the SE_TAKE_OWNERSHIP_NAME privilege in the caller's access token, and makes the local system's Administrators group the owner of the object. If the caller is a member of the Administrators group, the code will then be able to change the object's DACL.
To enable and disable privileges, this example uses the SetPrivilege sample function described in Enabling and Disabling Privileges.
BOOL TakeOwnership(LPTSTR lpszOwnFile) { HANDLE hToken; BYTE sidBuffer[100]; PSID pSID = (PSID)&sidBuffer; SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY; DWORD dwRes; // Try to remove the object's DACL. dwRes = SetNamedSecurityInfo( lpszOwnFile, // name of the object SE_FILE_OBJECT, // type of object DACL_SECURITY_INFORMATION, // change only the object's DACL NULL, NULL, // don't change owner or group NULL, // no DACL specified - allows everyone access NULL); // don't change SACL if (dwRes == ERROR_SUCCESS) return TRUE; else if (dwRes != ERROR_ACCESS_DENIED) { printf("First SetNamedSecurityInfo call failed: %u\n", dwRes); return FALSE; } // If the preceding call failed because access was denied, // enable the SE_TAKE_OWNERSHIP_NAME privilege, create a SID for // the Administrators group, take ownership of the object, and // disable the privilege. Then try again to set the object's DACL. // Open a handle to the access token for the calling process. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { printf("OpenProcessToken failed: %u\n", GetLastError()); return FALSE; } // Enable the SE_TAKE_OWNERSHIP_NAME privilege. if (!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE)) { printf("You must be logged on as Administrator.\n"); return FALSE; } // Create a SID for the BUILTIN\Administrators group. if (!AllocateAndInitializeSid(&SIDAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSID)) { printf("AllocateAndInitializeSid error %u\n", GetLastError()); return FALSE; } // Set the owner in the object's security descriptor. dwRes = SetNamedSecurityInfo( lpszOwnFile, // name of the object SE_FILE_OBJECT, // type of object OWNER_SECURITY_INFORMATION, // change only the object's pwner pSID, // SID of Administrator group NULL, NULL, NULL); if (pSID) FreeSid(pSID); if (dwRes != ERROR_SUCCESS) { printf("Could not set owner. Error: %u\n", dwRes); return FALSE; } // Disable the SE_TAKE_OWNERSHIP_NAME privilege. if (!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, FALSE)) { printf("You must be logged on as Administrator.\n"); return FALSE; } // Try again to remove the object's DACL, now that we are the owner. dwRes = SetNamedSecurityInfo( lpszOwnFile, // name of the object SE_FILE_OBJECT, // type of object DACL_SECURITY_INFORMATION, // change only the object's DACL NULL, NULL, // don't change owner or group NULL, // no DACL specified - allows everyone access NULL); // don't change SACL if (dwRes == ERROR_SUCCESS) return TRUE; printf("Second SetNamedSecurityInfo call failed: %u\n", dwRes); return FALSE; }