# TWAPI example # Protect a file from being accessed by a particular user # Usage example: tclsh protectfilefromuser.example FILENAME USER package require twapi if {$argc != 2} { puts stderr "Usage: [info nameofexecutable] FILENAME USER" exit } # Path to the file set path [lindex $argv 0] # Get the SID for the user set sid [twapi::map_account_to_sid [lindex $argv 1]] # Get the security descriptor for the file set secd [twapi::get_resource_security_descriptor file $path] # Get the DACL (discretionary access control list) in the security descriptor set dacl [twapi::get_security_descriptor_dacl $secd] # Get the ACEs (access control entries) within the DACL set aces [twapi::get_acl_aces $dacl] # Create a new list of ACES with just the deny ACE for our new DACL set new_aces [list [twapi::new_ace deny $sid generic_all]] # Now go through the existing ACE's one at a time. # If the ACE's SID is the one we want to deny, discard it as # we will be creating a new ACE for it. If the ACE is for a different # SID, we keep it as it is. Note that since we are adding a DENY ACE, # discarding ACE's that match the SID of interest is not strictly necessary # since the DENY ACE will always land up at the front of the list. But # discarding it is cleaner. foreach ace $aces { # Skip existing ACE's for this SID if {[string equal -nocase $sid [twapi::get_ace_sid $ace]]} { continue } lappend new_aces $ace } # Sort the ACE's in the Windows approved order. This example is a simple # case, but for more complex cases you would need to be aware of what # this approved order is when building ACE's else you might not get # what you expect! We could also leave off the sorting and Windows will # keep the exact order we specified but Windows tools which expect the # "approved" order get confused. set new_aces [twapi::sort_aces $new_aces] # Now create a new DACL based on these new ACES set new_dacl [twapi::new_acl] set new_dacl [twapi::set_acl_aces $new_dacl $new_aces] # Modify the security descriptor with the new DACL set secd [twapi::set_security_descriptor_dacl $secd $new_dacl] # Now finally set the actual resource security descriptor dacl. Again, the # -protect_dacl is not strictly necessary since we have added a deny all # ACE, any inherited ACE's will not override the deny. twapi::set_resource_security_descriptor file $path $secd -dacl -protect_dacl # All done exit 0