diff --git a/lib/puppet/util/windows/access_control_entry.rb b/lib/puppet/util/windows/access_control_entry.rb index f4d4e6df0..5cd052dae 100644 --- a/lib/puppet/util/windows/access_control_entry.rb +++ b/lib/puppet/util/windows/access_control_entry.rb @@ -1,55 +1,84 @@ # Windows Access Control Entry # # Represents an access control entry, which grants or denies a subject, # identified by a SID, rights to a securable object. # # @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa374868(v=vs.85).aspx # @api private class Puppet::Util::Windows::AccessControlEntry + require 'puppet/util/windows/security' + include Puppet::Util::Windows::SID + attr_accessor :sid attr_reader :mask, :flags, :type OBJECT_INHERIT_ACE = 0x1 CONTAINER_INHERIT_ACE = 0x2 NO_PROPAGATE_INHERIT_ACE = 0x4 INHERIT_ONLY_ACE = 0x8 INHERITED_ACE = 0x10 ACCESS_ALLOWED_ACE_TYPE = 0x0 ACCESS_DENIED_ACE_TYPE = 0x1 def initialize(sid, mask, flags = 0, type = ACCESS_ALLOWED_ACE_TYPE) @sid = sid @mask = mask @flags = flags @type = type end # Returns true if this ACE is inherited from a parent. If false, # then the ACE is set directly on the object to which it refers. # # @return [Boolean] true if the ACE is inherited def inherited? (@flags & INHERITED_ACE) == INHERITED_ACE end # Returns true if this ACE only applies to children of the object. # If false, it applies to the object. # # @return [Boolean] true if the ACE only applies to children and # not the object itself. def inherit_only? (@flags & INHERIT_ONLY_ACE) == INHERIT_ONLY_ACE end + # Returns true if this ACE applies to child directories. + # + # @return [Boolean] true if the ACE applies to child direcories + def container_inherit? + (@flags & CONTAINER_INHERIT_ACE) == CONTAINER_INHERIT_ACE + end + + # Returns true if this ACE applies to child files. + # + # @return [Boolean] true if the ACE applies to child files. + def object_inherit? + (@flags & OBJECT_INHERIT_ACE) == OBJECT_INHERIT_ACE + end + + def inspect + inheritance = "" + inheritance << '(I)' if inherited? + inheritance << '(OI)' if object_inherit? + inheritance << '(CI)' if container_inherit? + inheritance << '(IO)' if inherit_only? + + left = "#{sid_to_name(sid)}:#{inheritance}" + left = left.ljust(45) + "#{left} 0x#{mask.to_s(16)}" + end + # Returns true if this ACE is equal to +other+ def ==(other) self.class == other.class && sid == other.sid && mask == other.mask && flags == other.flags && type == other.type end alias eql? == end diff --git a/lib/puppet/util/windows/access_control_list.rb b/lib/puppet/util/windows/access_control_list.rb index 3e86ed2a3..7d60b3292 100644 --- a/lib/puppet/util/windows/access_control_list.rb +++ b/lib/puppet/util/windows/access_control_list.rb @@ -1,82 +1,90 @@ # Windows Access Control List # # Represents a list of access control entries (ACEs). # # @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa374872(v=vs.85).aspx # @api private class Puppet::Util::Windows::AccessControlList include Enumerable ACCESS_ALLOWED_ACE_TYPE = 0x0 ACCESS_DENIED_ACE_TYPE = 0x1 # Construct an ACL. # # @param acl [Enumerable] A list of aces to copy from. def initialize(acl = nil) if acl @aces = acl.map(&:dup) else @aces = [] end end # Enumerate each ACE in the list. # # @yieldparam ace [Hash] the ace def each @aces.each {|ace| yield ace} end # Allow the +sid+ to access a resource with the specified access +mask+. # # @param sid [String] The SID that the ACE is granting access to # @param mask [int] The access mask granted to the SID # @param flags [int] The flags assigned to the ACE, e.g. +INHERIT_ONLY_ACE+ def allow(sid, mask, flags = 0) @aces << Puppet::Util::Windows::AccessControlEntry.new(sid, mask, flags, ACCESS_ALLOWED_ACE_TYPE) end # Deny the +sid+ access to a resource with the specified access +mask+. # # @param sid [String] The SID that the ACE is denying access to # @param mask [int] The access mask denied to the SID # @param flags [int] The flags assigned to the ACE, e.g. +INHERIT_ONLY_ACE+ def deny(sid, mask, flags = 0) @aces << Puppet::Util::Windows::AccessControlEntry.new(sid, mask, flags, ACCESS_DENIED_ACE_TYPE) end # Reassign all ACEs currently assigned to +old_sid+ to +new_sid+ instead. # If an ACE is inherited or is not assigned to +old_sid+, then it will # be copied as-is to the new ACL, preserving its order within the ACL. # # @param old_sid [String] The old SID, e.g. 'S-1-5-18' # @param new_sid [String] The new SID # @return [AccessControlList] The copied ACL. def reassign!(old_sid, new_sid) new_aces = [] prepend_needed = false @aces.each do |ace| new_ace = ace.dup if ace.sid == old_sid && ! ace.inherited? new_ace.sid = new_sid prepend_needed = old_sid == Win32::Security::SID::LocalSystem end new_aces << new_ace end if prepend_needed mask = Windows::Security::STANDARD_RIGHTS_ALL | Windows::Security::SPECIFIC_RIGHTS_ALL ace = Puppet::Util::Windows::AccessControlEntry.new( Win32::Security::SID::LocalSystem, mask) new_aces.unshift(ace) end @aces = new_aces end + + def inspect + str = "" + @aces.each do |ace| + str << " #{ace.inspect}\n" + end + str + end end diff --git a/lib/puppet/util/windows/security_descriptor.rb b/lib/puppet/util/windows/security_descriptor.rb index 32c357cf3..9c95cee6d 100644 --- a/lib/puppet/util/windows/security_descriptor.rb +++ b/lib/puppet/util/windows/security_descriptor.rb @@ -1,50 +1,62 @@ # Windows Security Descriptor # # Represents a security descriptor that can be applied to any Windows securable # object, e.g. file, registry key, service, etc. It consists of an owner, group, # flags, DACL, and SACL. The SACL is not currently supported, though it has the # same layout as a DACL. # # @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa379563(v=vs.85).aspx # @api private class Puppet::Util::Windows::SecurityDescriptor + require 'puppet/util/windows/security' + include Puppet::Util::Windows::SID + attr_reader :owner, :group, :dacl attr_accessor :protect # Construct a security descriptor # # @param owner [String] The SID of the owner, e.g. 'S-1-5-18' # @param group [String] The SID of the group # @param dacl [AccessControlList] The ACL specifying the rights granted to # each user for accessing the object that the security descriptor refers to. # @param protect [Boolean] If true, then inheritable access control # entries will be blocked, and not applied to the object. def initialize(owner, group, dacl, protect = false) @owner = owner @group = group @dacl = dacl @protect = protect end # Set the owner. Non-inherited access control entries assigned to the # current owner will be assigned to the new owner. # # @param new_owner [String] The SID of the new owner, e.g. 'S-1-5-18' def owner=(new_owner) if @owner != new_owner @dacl.reassign!(@owner, new_owner) @owner = new_owner end end # Set the group. Non-inherited access control entries assigned to the # current group will be assigned to the new group. # # @param new_group [String] The SID of the new group, e.g. 'S-1-0-0' def group=(new_group) if @group != new_group @dacl.reassign!(@group, new_group) @group = new_group end end + + def inspect + str = sid_to_name(owner) + str << "\n" + str << sid_to_name(group) + str << "\n" + str << @dacl.inspect + str + end end