From d2b2e0093973ca8ad75e0f35a460caada623cc78 Mon Sep 17 00:00:00 2001 From: Paulo Bittencourt Date: Sun, 3 Nov 2013 22:18:37 -0500 Subject: [PATCH 1/3] elevate privileges in Windows host if necessary --- lib/vagrant-hostmanager/hosts_file.rb | 59 +++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/lib/vagrant-hostmanager/hosts_file.rb b/lib/vagrant-hostmanager/hosts_file.rb index 25ffb70..d7a2e58 100644 --- a/lib/vagrant-hostmanager/hosts_file.rb +++ b/lib/vagrant-hostmanager/hosts_file.rb @@ -34,19 +34,23 @@ module VagrantPlugins def update_host # copy and modify hosts file on host with Vagrant-managed entries file = @global_env.tmp_path.join('hosts.local') - # add a "if windows..." - hosts_location = '/etc/hosts' - copy_cmd = 'sudo cp' - # handles the windows hosts file... - if ENV['SystemRoot'] != nil + + if WindowsSupport.windows? + # lazily include windows Module + class << self + include WindowsSupport unless include? WindowsSupport + end + hosts_location = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts" - copy_cmd = 'cp' + copy_proc = Proc.new { windows_copy_file(file, hosts_location) } + else + hosts_location = '/etc/hosts' + copy_proc = Proc.new { `sudo cp #{file} #{hosts_location}` } end + FileUtils.cp(hosts_location, file) update_file(file) - - # copy modified file using sudo for permission - `#{copy_cmd} #{file} #{hosts_location}` + copy_proc.call end private @@ -122,6 +126,43 @@ module VagrantPlugins @global_env.active_machines end end + + ## Windows support for copying files, requesting elevated privileges if necessary + module WindowsSupport + def self.windows? + ENV['OS'] === 'Windows_NT' + end + + require 'win32ole' if windows? + + def windows_copy_file(source, dest) + begin + # First, try Ruby copy + FileUtils.cp(source, dest) + rescue Errno::EACCES + # Access denied, try with elevated privileges + windows_copy_file_elevated(source, dest) + end + end + + private + + def windows_copy_file_elevated(source, dest) + # copy command only supports backslashes as separators + source, dest = [source, dest].map { |s| s.to_s.gsub(/\//, '\\') } + + # run 'cmd /C copy ...' with elevated privilege, minimized + copy_cmd = "copy \"#{source}\" \"#{dest}\"" + WIN32OLE.new('Shell.Application').ShellExecute('cmd', "/C #{copy_cmd}", nil, 'runas', 7) + + # Unfortunately, ShellExecute does not give us a status code, + # and it is non-blocking so we can't reliably compare the file contents + # to see if they were copied. + # + # If the user rejects the UAC prompt, vagrant will silently continue + # without updating the hostsfile. + end + end end end end From 3edc923b2286247b55b972cc2f2ba8a8f03fac53 Mon Sep 17 00:00:00 2001 From: Paulo Bittencourt Date: Mon, 18 Nov 2013 12:34:16 -0500 Subject: [PATCH 2/3] use rbconfig for detecting Windows --- lib/vagrant-hostmanager/hosts_file.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/vagrant-hostmanager/hosts_file.rb b/lib/vagrant-hostmanager/hosts_file.rb index d7a2e58..71b4e05 100644 --- a/lib/vagrant-hostmanager/hosts_file.rb +++ b/lib/vagrant-hostmanager/hosts_file.rb @@ -129,8 +129,10 @@ module VagrantPlugins ## Windows support for copying files, requesting elevated privileges if necessary module WindowsSupport + require 'rbconfig' + def self.windows? - ENV['OS'] === 'Windows_NT' + RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ end require 'win32ole' if windows? From 1caa3c373bbee70b43f2a5f1f44f92728e3ba969 Mon Sep 17 00:00:00 2001 From: Paulo Bittencourt Date: Wed, 20 Nov 2013 23:04:37 -0500 Subject: [PATCH 3/3] update README with Windows support information --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 57f4e8d..db196e4 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,22 @@ config.hostmanager.ip_resolver = proc do |vm| end ``` +Windows support +--------------- + +Hostmanager will detect Windows guests and hosts and use the appropriate +path for the ```hosts``` file: ```%WINDIR%\System32\drivers\etc\hosts``` + +By default on a Windows host, the ```hosts``` file is not writable without +elevated privileges. If hostmanager detects that it cannot overwrite the file, +it will attempt to do so with elevated privileges, causing the +[UAC](http://en.wikipedia.org/wiki/User_Account_Control) prompt to appear. + +### UAC limitations + +Due to limitations caused by UAC, cancelling out of the UAC prompt will not cause any +visible errors, however the ```hosts``` file will not be updated. + Contribute ---------- Contributions are welcome.