From ddfd86f3d1c9d674cdd086bb48759920f83bb293 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 9 Apr 2018 16:52:53 -0700 Subject: [PATCH] Split with shellwords and quote paths in command filter This uses shellwords to split the command in the command filter inside the winrm communicator. Using shellwords properly handles things like quoted paths. Path arguments are also quoted to prevent issues with paths that include spaces. Fixes #9390 --- .../winrm/command_filters/mkdir.rb | 6 +++-- .../communicators/winrm/command_filters/rm.rb | 8 ++++--- .../winrm/command_filters/test.rb | 4 +++- .../winrm/command_filters/which.rb | 6 +++-- .../winrm/command_filter_test.rb | 22 ++++++++++++------- 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/plugins/communicators/winrm/command_filters/mkdir.rb b/plugins/communicators/winrm/command_filters/mkdir.rb index 9d399c2f3..d14ccbc23 100644 --- a/plugins/communicators/winrm/command_filters/mkdir.rb +++ b/plugins/communicators/winrm/command_filters/mkdir.rb @@ -1,3 +1,5 @@ +require "shellwords" + module VagrantPlugins module CommunicatorWinRM module CommandFilters @@ -6,14 +8,14 @@ module VagrantPlugins def filter(command) # mkdir -p /some/dir # mkdir /some/dir - cmd_parts = command.strip.split(/\s+/) + cmd_parts = Shellwords.split(command.strip) dir = cmd_parts.pop while !dir.nil? && dir.start_with?('-') dir = cmd_parts.pop end # This will ignore any -p switches, which are redundant in PowerShell, # and ambiguous in PowerShell 4+ - return "mkdir #{dir} -force" + return "mkdir \"#{dir}\" -force" end def accept?(command) diff --git a/plugins/communicators/winrm/command_filters/rm.rb b/plugins/communicators/winrm/command_filters/rm.rb index 8ef79f148..9133febf6 100644 --- a/plugins/communicators/winrm/command_filters/rm.rb +++ b/plugins/communicators/winrm/command_filters/rm.rb @@ -1,3 +1,5 @@ +require "shellwords" + module VagrantPlugins module CommunicatorWinRM module CommandFilters @@ -9,7 +11,7 @@ module VagrantPlugins # rm -R -f /some/dir # rm -f /some/dir # rm /some/dir - cmd_parts = command.strip.split(/\s+/) + cmd_parts = Shellwords.split(command.strip) # Figure out if we need to do this recursively recurse = false @@ -29,9 +31,9 @@ module VagrantPlugins ret_cmd = '' if recurse - ret_cmd = "rm #{dir} -recurse -force" + ret_cmd = "rm \"#{dir}\" -recurse -force" else - ret_cmd = "rm #{dir} -force" + ret_cmd = "rm \"#{dir}\" -force" end return ret_cmd end diff --git a/plugins/communicators/winrm/command_filters/test.rb b/plugins/communicators/winrm/command_filters/test.rb index bee71505d..58b7fbf0d 100644 --- a/plugins/communicators/winrm/command_filters/test.rb +++ b/plugins/communicators/winrm/command_filters/test.rb @@ -1,3 +1,5 @@ +require "shellwords" + module VagrantPlugins module CommunicatorWinRM module CommandFilters @@ -9,7 +11,7 @@ module VagrantPlugins # test -L /somelink # test -x /tmp/some.exe - cmd_parts = command.strip.split(/\s+/) + cmd_parts = Shellwords.split(command.strip) flag = cmd_parts[1] path = cmd_parts[2] diff --git a/plugins/communicators/winrm/command_filters/which.rb b/plugins/communicators/winrm/command_filters/which.rb index 2cc23a993..1d7a12bdc 100644 --- a/plugins/communicators/winrm/command_filters/which.rb +++ b/plugins/communicators/winrm/command_filters/which.rb @@ -1,12 +1,14 @@ +require "shellwords" + module VagrantPlugins module CommunicatorWinRM module CommandFilters # Converts a *nix 'which' command to a PowerShell equivalent class Which def filter(command) - executable = command.strip.split(/\s+/)[1] + executable = Shellwords.split(command.strip)[1] return <<-EOH - $command = [Array](Get-Command #{executable} -errorAction SilentlyContinue) + $command = [Array](Get-Command "#{executable}" -errorAction SilentlyContinue) if ($null -eq $command) { exit 1 } write-host $command[0].Definition exit 0 diff --git a/test/unit/plugins/communicators/winrm/command_filter_test.rb b/test/unit/plugins/communicators/winrm/command_filter_test.rb index 251defc7b..0bd6e7ba8 100644 --- a/test/unit/plugins/communicators/winrm/command_filter_test.rb +++ b/test/unit/plugins/communicators/winrm/command_filter_test.rb @@ -21,7 +21,7 @@ describe VagrantPlugins::CommunicatorWinRM::CommandFilter, unit: true do it 'filters out which commands' do expect(subject.filter('which ruby')).to include( - '[Array](Get-Command ruby -errorAction SilentlyContinue)') + '[Array](Get-Command "ruby" -errorAction SilentlyContinue)') end it 'filters out test -d commands' do @@ -54,25 +54,31 @@ describe VagrantPlugins::CommunicatorWinRM::CommandFilter, unit: true do it 'filters out rm recurse commands' do expect(subject.filter('rm -Rf /some/dir')).to eq( - "rm /some/dir -recurse -force") + "rm \"/some/dir\" -recurse -force") expect(subject.filter('rm -fr /some/dir')).to eq( - "rm /some/dir -recurse -force") + "rm \"/some/dir\" -recurse -force") expect(subject.filter('rm -r /some/dir')).to eq( - "rm /some/dir -recurse -force") + "rm \"/some/dir\" -recurse -force") + expect(subject.filter('rm -r "/some/dir"')).to eq( + "rm \"/some/dir\" -recurse -force") end it 'filters out rm commands' do expect(subject.filter('rm /some/dir')).to eq( - "rm /some/dir -force") + "rm \"/some/dir\" -force") expect(subject.filter('rm -f /some/dir')).to eq( - "rm /some/dir -force") + "rm \"/some/dir\" -force") + expect(subject.filter('rm -f "/some/dir"')).to eq( + "rm \"/some/dir\" -force") end it 'filters out mkdir commands' do expect(subject.filter('mkdir /some/dir')).to eq( - "mkdir /some/dir -force") + "mkdir \"/some/dir\" -force") expect(subject.filter('mkdir -p /some/dir')).to eq( - "mkdir /some/dir -force") + "mkdir \"/some/dir\" -force") + expect(subject.filter('mkdir "/some/dir"')).to eq( + "mkdir \"/some/dir\" -force") end it 'filters out chown commands' do