summaryrefslogtreecommitdiff
path: root/lib/chef/win32
diff options
context:
space:
mode:
authorDan Bjorge <dbjorge@gmail.com>2015-04-23 00:24:24 -0700
committerDan Bjorge <dbjorge@gmail.com>2015-04-23 00:24:24 -0700
commit6f42327a590025e078de9cdfd3191f14a0980776 (patch)
treec1b8c0d416e7d3a5a84e0b6f1ec5981d66f4f93c /lib/chef/win32
parent44d70ba0f1b38bc3e1170ae978ad5e9a11679df3 (diff)
downloadchef-6f42327a590025e078de9cdfd3191f14a0980776.tar.gz
securable_resource functional specs compare default creation permissions against actual defaults on Windows
Diffstat (limited to 'lib/chef/win32')
-rw-r--r--lib/chef/win32/api/security.rb8
-rw-r--r--lib/chef/win32/security.rb38
-rw-r--r--lib/chef/win32/security/sid.rb16
3 files changed, 60 insertions, 2 deletions
diff --git a/lib/chef/win32/api/security.rb b/lib/chef/win32/api/security.rb
index 229f2ace10..281e0b2271 100644
--- a/lib/chef/win32/api/security.rb
+++ b/lib/chef/win32/api/security.rb
@@ -270,6 +270,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 3902d8caaf..1833d362a1 100644
--- a/lib/chef/win32/security.rb
+++ b/lib/chef/win32/security.rb
@@ -270,6 +270,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)
@@ -415,6 +445,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)
@@ -513,7 +547,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
@@ -533,7 +567,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..7f461fd766 100644
--- a/lib/chef/win32/security/sid.rb
+++ b/lib/chef/win32/security/sid.rb
@@ -203,6 +203,22 @@ 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 is generally the same as current_user
+ 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