diff --git a/lib/puppet/util/windows/user.rb b/lib/puppet/util/windows/user.rb index 61080fb58..6722a0e2e 100644 --- a/lib/puppet/util/windows/user.rb +++ b/lib/puppet/util/windows/user.rb @@ -1,19 +1,44 @@ require 'puppet/util/windows' +require 'win32/security' + module Puppet::Util::Windows::User + include Windows::Security + extend Windows::Security + def admin? - require 'sys/admin' - require 'win32/security' require 'facter' majversion = Facter.value(:kernelmajversion) return false unless majversion # if Vista or later, check for unrestricted process token return Win32::Security.elevated_security? unless majversion.to_f < 6.0 - group = Sys::Admin.get_group("Administrators", :sid => Win32::Security::SID::BuiltinAdministrators) - group and group.members.index(Sys::Admin.get_login) != nil + # otherwise 2003 or less + check_token_membership end module_function :admin? + + def check_token_membership + sid = 0.chr * 80 + size = [80].pack('L') + member = 0.chr * 4 + + unless CreateWellKnownSid(WinBuiltinAdministratorsSid, nil, sid, size) + raise Puppet::Util::Windows::Error.new("Failed to create administrators SID") + end + + unless IsValidSid(sid) + raise Puppet::Util::Windows::Error.new("Invalid SID") + end + + unless CheckTokenMembership(nil, sid, member) + raise Puppet::Util::Windows::Error.new("Failed to check membership") + end + + # Is administrators SID enabled in calling thread's access token? + member.unpack('L')[0] == 1 + end + module_function :check_token_membership end diff --git a/spec/integration/util/windows/user_spec.rb b/spec/integration/util/windows/user_spec.rb index f91c4a0c7..82d065d74 100755 --- a/spec/integration/util/windows/user_spec.rb +++ b/spec/integration/util/windows/user_spec.rb @@ -1,62 +1,59 @@ #!/usr/bin/env ruby -- rspec require 'spec_helper' describe "Puppet::Util::Windows::User", :if => Puppet.features.microsoft_windows? do describe "2003 without UAC" do before :each do Facter.stubs(:value).with(:kernelmajversion).returns("5.2") end - it "should be root if user is a member of the Administrators group" do - Sys::Admin.stubs(:get_login).returns("Administrator") - Sys::Group.stubs(:members).returns(%w[Administrator]) - + it "should be an admin if user's token contains the Administrators SID" do + Puppet::Util::Windows::User.expects(:check_token_membership).returns(true) Win32::Security.expects(:elevated_security?).never + Puppet::Util::Windows::User.should be_admin end - it "should not be root if the process is running as Guest" do - Sys::Admin.stubs(:get_login).returns("Guest") - Sys::Group.stubs(:members).returns([]) - + it "should not be an admin if user's token doesn't contain the Administrators SID" do + Puppet::Util::Windows::User.expects(:check_token_membership).returns(false) Win32::Security.expects(:elevated_security?).never + Puppet::Util::Windows::User.should_not be_admin end - it "should raise an exception if the process fails to open the process token" do - Win32::Security.stubs(:elevated_security?).raises(Win32::Security::Error, "Access denied.") - Sys::Admin.stubs(:get_login).returns("Administrator") - Sys::Group.expects(:members).never + it "should raise an exception if we can't check token membership" do + Puppet::Util::Windows::User.expects(:check_token_membership).raises(Win32::Security::Error, "Access denied.") + Win32::Security.expects(:elevated_security?).never lambda { Puppet::Util::Windows::User.admin? }.should raise_error(Win32::Security::Error, /Access denied./) end end describe "2008 with UAC" do before :each do Facter.stubs(:value).with(:kernelmajversion).returns("6.0") end - it "should be root if user is running with elevated privileges" do + it "should be an admin if user is running with elevated privileges" do Win32::Security.stubs(:elevated_security?).returns(true) - Sys::Admin.expects(:get_login).never + Puppet::Util::Windows::User.expects(:check_token_membership).never Puppet::Util::Windows::User.should be_admin end - it "should not be root if user is not running with elevated privileges" do + it "should not be an admin if user is not running with elevated privileges" do Win32::Security.stubs(:elevated_security?).returns(false) - Sys::Admin.expects(:get_login).never + Puppet::Util::Windows::User.expects(:check_token_membership).never Puppet::Util::Windows::User.should_not be_admin end it "should raise an exception if the process fails to open the process token" do Win32::Security.stubs(:elevated_security?).raises(Win32::Security::Error, "Access denied.") - Sys::Admin.expects(:get_login).never + Puppet::Util::Windows::User.expects(:check_token_membership).never lambda { Puppet::Util::Windows::User.admin? }.should raise_error(Win32::Security::Error, /Access denied./) end end end