diff options
author | Thom May <thom@may.lt> | 2015-05-20 19:06:01 +0100 |
---|---|---|
committer | Thom May <thom@may.lt> | 2015-05-20 19:06:01 +0100 |
commit | 1bb229a122c5b3a6abb66fa5c2c422f6fbb6121d (patch) | |
tree | 35627136aea8bdad1944e3924f7ed7a3832de157 /lib/chef/win32 | |
parent | af098d1f1a7f7fd4a8ce84ab36e69453b9c145aa (diff) | |
parent | 505ccd35d931d69bef1f3c62e15d2fcc77762775 (diff) | |
download | chef-1bb229a122c5b3a6abb66fa5c2c422f6fbb6121d.tar.gz |
Merge pull request #3267 from dbjorge/issue-3266
#3266 Fix bad Windows securable_resource functional spec assumptions for default file owners/groups
Diffstat (limited to 'lib/chef/win32')
-rw-r--r-- | lib/chef/win32/api/security.rb | 8 | ||||
-rw-r--r-- | lib/chef/win32/security.rb | 38 | ||||
-rw-r--r-- | lib/chef/win32/security/sid.rb | 17 |
3 files changed, 61 insertions, 2 deletions
diff --git a/lib/chef/win32/api/security.rb b/lib/chef/win32/api/security.rb index 95e7f4aab7..4c352a3554 100644 --- a/lib/chef/win32/api/security.rb +++ b/lib/chef/win32/api/security.rb @@ -284,6 +284,14 @@ class Chef :MaxTokenInfoClass ] + class TOKEN_OWNER < FFI::Struct + layout :Owner, :pointer + end + + class TOKEN_PRIMARY_GROUP < FFI::Struct + layout :PrimaryGroup, :pointer + end + # https://msdn.microsoft.com/en-us/library/windows/desktop/aa379572%28v=vs.85%29.aspx SECURITY_IMPERSONATION_LEVEL = enum :SECURITY_IMPERSONATION_LEVEL, [ :SecurityAnonymous, diff --git a/lib/chef/win32/security.rb b/lib/chef/win32/security.rb index a5a845e55c..5c83180bc0 100644 --- a/lib/chef/win32/security.rb +++ b/lib/chef/win32/security.rb @@ -273,6 +273,36 @@ class Chef [ present.read_char != 0, acl.null? ? nil : ACL.new(acl, security_descriptor), defaulted.read_char != 0 ] end + def self.get_token_information_owner(token) + owner_result_size = FFI::MemoryPointer.new(:ulong) + if GetTokenInformation(token.handle.handle, :TokenOwner, nil, 0, owner_result_size) + raise "Expected ERROR_INSUFFICIENT_BUFFER from GetTokenInformation, and got no error!" + elsif FFI::LastError.error != ERROR_INSUFFICIENT_BUFFER + Chef::ReservedNames::Win32::Error.raise! + end + owner_result_storage = FFI::MemoryPointer.new owner_result_size.read_ulong + unless GetTokenInformation(token.handle.handle, :TokenOwner, owner_result_storage, owner_result_size.read_ulong, owner_result_size) + Chef::ReservedNames::Win32::Error.raise! + end + owner_result = TOKEN_OWNER.new owner_result_storage + SID.new(owner_result[:Owner], owner_result_storage) + end + + def self.get_token_information_primary_group(token) + group_result_size = FFI::MemoryPointer.new(:ulong) + if GetTokenInformation(token.handle.handle, :TokenPrimaryGroup, nil, 0, group_result_size) + raise "Expected ERROR_INSUFFICIENT_BUFFER from GetTokenInformation, and got no error!" + elsif FFI::LastError.error != ERROR_INSUFFICIENT_BUFFER + Chef::ReservedNames::Win32::Error.raise! + end + group_result_storage = FFI::MemoryPointer.new group_result_size.read_ulong + unless GetTokenInformation(token.handle.handle, :TokenPrimaryGroup, group_result_storage, group_result_size.read_ulong, group_result_size) + Chef::ReservedNames::Win32::Error.raise! + end + group_result = TOKEN_PRIMARY_GROUP.new group_result_storage + SID.new(group_result[:PrimaryGroup], group_result_storage) + end + def self.initialize_acl(acl_size) acl = FFI::MemoryPointer.new acl_size unless InitializeAcl(acl, acl_size, ACL_REVISION) @@ -418,6 +448,10 @@ class Chef [ SecurityDescriptor.new(absolute_sd), SID.new(owner), SID.new(group), ACL.new(dacl), ACL.new(sacl) ] end + def self.open_current_process_token(desired_access = TOKEN_READ) + open_process_token(Chef::ReservedNames::Win32::Process.get_current_process, desired_access) + end + def self.open_process_token(process, desired_access) process = process.handle if process.respond_to?(:handle) process = process.handle if process.respond_to?(:handle) @@ -516,7 +550,7 @@ class Chef def self.with_privileges(*privilege_names) # Set privileges - token = open_process_token(Chef::ReservedNames::Win32::Process.get_current_process, TOKEN_READ | TOKEN_ADJUST_PRIVILEGES) + token = open_current_process_token(TOKEN_READ | TOKEN_ADJUST_PRIVILEGES) old_privileges = token.enable_privileges(*privilege_names) # Let the caller do their privileged stuff @@ -536,7 +570,7 @@ class Chef true else - process_token = open_process_token(Chef::ReservedNames::Win32::Process.get_current_process, TOKEN_READ) + process_token = open_current_process_token(TOKEN_READ) elevation_result = FFI::Buffer.new(:ulong) elevation_result_size = FFI::MemoryPointer.new(:uint32) success = GetTokenInformation(process_token.handle.handle, :TokenElevation, elevation_result, 4, elevation_result_size) diff --git a/lib/chef/win32/security/sid.rb b/lib/chef/win32/security/sid.rb index 8e9407dc80..f8bd934876 100644 --- a/lib/chef/win32/security/sid.rb +++ b/lib/chef/win32/security/sid.rb @@ -203,6 +203,23 @@ class Chef SID.from_account("#{::ENV['USERDOMAIN']}\\#{::ENV['USERNAME']}") end + # See https://technet.microsoft.com/en-us/library/cc961992.aspx + # In practice, this is SID.Administrators if the current_user is an admin (even if not + # running elevated), and is current_user otherwise. On win2k3, it technically can be + # current_user in all cases if a certain group policy is set. + def self.default_security_object_owner + token = Chef::ReservedNames::Win32::Security.open_current_process_token + Chef::ReservedNames::Win32::Security.get_token_information_owner(token) + end + + # See https://technet.microsoft.com/en-us/library/cc961996.aspx + # In practice, this seems to be SID.current_user for Microsoft Accounts, the current + # user's Domain Users group for domain accounts, and SID.None otherwise. + def self.default_security_object_group + token = Chef::ReservedNames::Win32::Security.open_current_process_token + Chef::ReservedNames::Win32::Security.get_token_information_primary_group(token) + end + def self.admin_account_name @admin_account_name ||= begin admin_account_name = nil |