diff options
author | Jay Mundrawala <jdmundrawala@gmail.com> | 2015-05-08 13:01:53 -0700 |
---|---|---|
committer | Jay Mundrawala <jdmundrawala@gmail.com> | 2015-05-15 08:51:21 -0700 |
commit | 7f6631c20c71ff23cca265ae844f931cd2bd2776 (patch) | |
tree | 531f098421fb7cd814f8d5c4e47a92404a26bb36 | |
parent | e90ff3c513b8f3dcbb55a769a2aece2fc0e15cd9 (diff) | |
download | chef-7f6631c20c71ff23cca265ae844f931cd2bd2776.tar.gz |
LogonUser uses ffi instead win32-api
-rw-r--r-- | lib/chef/mixin/wstring.rb | 31 | ||||
-rw-r--r-- | lib/chef/util/windows/net_user.rb | 19 | ||||
-rw-r--r-- | lib/chef/win32/api/security.rb | 16 | ||||
-rw-r--r-- | lib/chef/win32/net.rb | 12 | ||||
-rw-r--r-- | lib/chef/win32/security.rb | 15 |
5 files changed, 76 insertions, 17 deletions
diff --git a/lib/chef/mixin/wstring.rb b/lib/chef/mixin/wstring.rb new file mode 100644 index 0000000000..bb6fdf4884 --- /dev/null +++ b/lib/chef/mixin/wstring.rb @@ -0,0 +1,31 @@ +# +# Author:: Jay Mundrawala(<jdm@chef.io>) +# Copyright:: Copyright 2015 Chef Software +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +class Chef + module Mixin + module WideString + def wstring(str) + if str.nil? || str.encoding == Encoding::UTF_16LE + str + else + str.to_wstring + end + end + end + end +end diff --git a/lib/chef/util/windows/net_user.rb b/lib/chef/util/windows/net_user.rb index b98f346f51..26fbe53db6 100644 --- a/lib/chef/util/windows/net_user.rb +++ b/lib/chef/util/windows/net_user.rb @@ -19,6 +19,7 @@ require 'chef/util/windows' require 'chef/exceptions' require 'chef/win32/net' +require 'chef/win32/security' #wrapper around a subset of the NetUser* APIs. #nothing Chef specific, but not complete enough to be its own gem, so util for now. @@ -26,8 +27,7 @@ class Chef::Util::Windows::NetUser < Chef::Util::Windows private NetUser = Chef::ReservedNames::Win32::NetUser - - LogonUser = Windows::API.new('LogonUser', 'SSSLLP', 'I', 'advapi32') + Security = Chef::ReservedNames::Win32::Security USER_INFO_3_TRANSFORM = { name: :usri3_name, @@ -91,18 +91,17 @@ class Chef::Util::Windows::NetUser < Chef::Util::Windows @name = multi_to_wide(username) end - LOGON32_PROVIDER_DEFAULT = 0 - LOGON32_LOGON_NETWORK = 3 + LOGON32_PROVIDER_DEFAULT = Security::LOGON32_PROVIDER_DEFAULT + LOGON32_LOGON_NETWORK = Security::LOGON32_LOGON_NETWORK #XXX for an extra painful alternative, see: http://support.microsoft.com/kb/180548 def validate_credentials(passwd) - token = 0.chr * PTR_SIZE - res = LogonUser.call(@username, nil, passwd, - LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, token) - if res == 0 + begin + token = Security::logon_user(@username, nil, passwd, + LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT) + return true + rescue Chef::Exceptions::Win32APIError return false end - ::Windows::Handle::CloseHandle.call(token.unpack('L')[0]) - return true end def get_info diff --git a/lib/chef/win32/api/security.rb b/lib/chef/win32/api/security.rb index 229f2ace10..95e7f4aab7 100644 --- a/lib/chef/win32/api/security.rb +++ b/lib/chef/win32/api/security.rb @@ -193,6 +193,20 @@ class Chef MAXDWORD = 0xffffffff + # LOGON32 constants for LogonUser + LOGON32_LOGON_INTERACTIVE = 2; + LOGON32_LOGON_NETWORK = 3; + LOGON32_LOGON_BATCH = 4; + LOGON32_LOGON_SERVICE = 5; + LOGON32_LOGON_UNLOCK = 7; + LOGON32_LOGON_NETWORK_CLEARTEXT = 8; + LOGON32_LOGON_NEW_CREDENTIALS = 9; + + LOGON32_PROVIDER_DEFAULT = 0; + LOGON32_PROVIDER_WINNT35 = 1; + LOGON32_PROVIDER_WINNT40 = 2; + LOGON32_PROVIDER_WINNT50 = 3; + ############################################### # Win32 API Bindings ############################################### @@ -405,6 +419,8 @@ class Chef safe_attach_function :SetSecurityDescriptorOwner, [ :pointer, :pointer, :BOOL ], :BOOL safe_attach_function :SetSecurityDescriptorSacl, [ :pointer, :BOOL, :pointer, :BOOL ], :BOOL safe_attach_function :GetTokenInformation, [ :HANDLE, :TOKEN_INFORMATION_CLASS, :pointer, :DWORD, :PDWORD ], :BOOL + safe_attach_function :LogonUserW, [:LPTSTR, :LPTSTR, :LPTSTR, :DWORD, :DWORD, :PHANDLE], :BOOL + end end end diff --git a/lib/chef/win32/net.rb b/lib/chef/win32/net.rb index 41a8517952..0b095db2e9 100644 --- a/lib/chef/win32/net.rb +++ b/lib/chef/win32/net.rb @@ -18,6 +18,8 @@ require 'chef/win32/api/net' require 'chef/win32/error' +require 'chef/mixin/wstring' + class Chef module ReservedNames::Win32 class NetUser @@ -27,6 +29,9 @@ class Chef include Chef::ReservedNames::Win32::API::Net extend Chef::ReservedNames::Win32::API::Net + include Chef::Mixin::WideString + extend Chef::Mixin::WideString + def self.default_user_info_3 ui3 = USER_INFO_3.new.tap do |s| { usri3_name: nil, @@ -208,13 +213,6 @@ END private - def self.wstring(str) - if str.nil? || str.encoding == Encoding::UTF_16LE - str - else - str.to_wstring - end - end end end diff --git a/lib/chef/win32/security.rb b/lib/chef/win32/security.rb index 3902d8caaf..a5a845e55c 100644 --- a/lib/chef/win32/security.rb +++ b/lib/chef/win32/security.rb @@ -22,6 +22,7 @@ require 'chef/win32/memory' require 'chef/win32/process' require 'chef/win32/unicode' require 'chef/win32/security/token' +require 'chef/mixin/wstring' class Chef module ReservedNames::Win32 @@ -31,6 +32,8 @@ class Chef include Chef::ReservedNames::Win32::API::Security extend Chef::ReservedNames::Win32::API::Security extend Chef::ReservedNames::Win32::API::Macros + include Chef::Mixin::WideString + extend Chef::Mixin::WideString def self.access_check(security_descriptor, token, desired_access, generic_mapping) token_handle = token.handle.handle @@ -543,6 +546,18 @@ class Chef success && (elevation_result.read_ulong != 0) end end + + def self.logon_user(username, domain, password, logon_type, logon_provider) + username = wstring(username) + domain = wstring(domain) + password = wstring(password) + + token = FFI::Buffer.new(:pointer) + unless LogonUserW(username, domain, password, logon_type, logon_provider, token) + Chef::ReservedNames::Win32::Error.raise! + end + Token.new(Handle.new(token.read_pointer)) + end end end end |