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
This commit is contained in:
Chris Roberts 2018-04-09 16:52:53 -07:00
parent be1beb80a4
commit ddfd86f3d1
5 changed files with 30 additions and 16 deletions

View File

@ -1,3 +1,5 @@
require "shellwords"
module VagrantPlugins module VagrantPlugins
module CommunicatorWinRM module CommunicatorWinRM
module CommandFilters module CommandFilters
@ -6,14 +8,14 @@ module VagrantPlugins
def filter(command) def filter(command)
# mkdir -p /some/dir # mkdir -p /some/dir
# mkdir /some/dir # mkdir /some/dir
cmd_parts = command.strip.split(/\s+/) cmd_parts = Shellwords.split(command.strip)
dir = cmd_parts.pop dir = cmd_parts.pop
while !dir.nil? && dir.start_with?('-') while !dir.nil? && dir.start_with?('-')
dir = cmd_parts.pop dir = cmd_parts.pop
end end
# This will ignore any -p switches, which are redundant in PowerShell, # This will ignore any -p switches, which are redundant in PowerShell,
# and ambiguous in PowerShell 4+ # and ambiguous in PowerShell 4+
return "mkdir #{dir} -force" return "mkdir \"#{dir}\" -force"
end end
def accept?(command) def accept?(command)

View File

@ -1,3 +1,5 @@
require "shellwords"
module VagrantPlugins module VagrantPlugins
module CommunicatorWinRM module CommunicatorWinRM
module CommandFilters module CommandFilters
@ -9,7 +11,7 @@ module VagrantPlugins
# rm -R -f /some/dir # rm -R -f /some/dir
# rm -f /some/dir # rm -f /some/dir
# rm /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 # Figure out if we need to do this recursively
recurse = false recurse = false
@ -29,9 +31,9 @@ module VagrantPlugins
ret_cmd = '' ret_cmd = ''
if recurse if recurse
ret_cmd = "rm #{dir} -recurse -force" ret_cmd = "rm \"#{dir}\" -recurse -force"
else else
ret_cmd = "rm #{dir} -force" ret_cmd = "rm \"#{dir}\" -force"
end end
return ret_cmd return ret_cmd
end end

View File

@ -1,3 +1,5 @@
require "shellwords"
module VagrantPlugins module VagrantPlugins
module CommunicatorWinRM module CommunicatorWinRM
module CommandFilters module CommandFilters
@ -9,7 +11,7 @@ module VagrantPlugins
# test -L /somelink # test -L /somelink
# test -x /tmp/some.exe # test -x /tmp/some.exe
cmd_parts = command.strip.split(/\s+/) cmd_parts = Shellwords.split(command.strip)
flag = cmd_parts[1] flag = cmd_parts[1]
path = cmd_parts[2] path = cmd_parts[2]

View File

@ -1,12 +1,14 @@
require "shellwords"
module VagrantPlugins module VagrantPlugins
module CommunicatorWinRM module CommunicatorWinRM
module CommandFilters module CommandFilters
# Converts a *nix 'which' command to a PowerShell equivalent # Converts a *nix 'which' command to a PowerShell equivalent
class Which class Which
def filter(command) def filter(command)
executable = command.strip.split(/\s+/)[1] executable = Shellwords.split(command.strip)[1]
return <<-EOH return <<-EOH
$command = [Array](Get-Command #{executable} -errorAction SilentlyContinue) $command = [Array](Get-Command "#{executable}" -errorAction SilentlyContinue)
if ($null -eq $command) { exit 1 } if ($null -eq $command) { exit 1 }
write-host $command[0].Definition write-host $command[0].Definition
exit 0 exit 0

View File

@ -21,7 +21,7 @@ describe VagrantPlugins::CommunicatorWinRM::CommandFilter, unit: true do
it 'filters out which commands' do it 'filters out which commands' do
expect(subject.filter('which ruby')).to include( expect(subject.filter('which ruby')).to include(
'[Array](Get-Command ruby -errorAction SilentlyContinue)') '[Array](Get-Command "ruby" -errorAction SilentlyContinue)')
end end
it 'filters out test -d commands' do 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 it 'filters out rm recurse commands' do
expect(subject.filter('rm -Rf /some/dir')).to eq( 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( 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( 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 end
it 'filters out rm commands' do it 'filters out rm commands' do
expect(subject.filter('rm /some/dir')).to eq( 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( 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 end
it 'filters out mkdir commands' do it 'filters out mkdir commands' do
expect(subject.filter('mkdir /some/dir')).to eq( 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( 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 end
it 'filters out chown commands' do it 'filters out chown commands' do