Created
May 28, 2015 15:37
-
-
Save Mazwak/19f1176a95c0b10f9a89 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/winrm/winrm_service.rb b/lib/winrm/winrm_service.rb | |
index 0882832..d2978e2 100644 | |
--- a/lib/winrm/winrm_service.rb | |
+++ b/lib/winrm/winrm_service.rb | |
@@ -55,7 +55,7 @@ module WinRM | |
end | |
# Operation timeout. | |
- # | |
+ # | |
# Unless specified the client receive timeout will be 10s + the operation | |
# timeout. | |
# | |
@@ -150,22 +150,22 @@ module WinRM | |
"#{NS_WSMAN_DMTF}:Option" => [consolemode, skipcmd], | |
:attributes! => {"#{NS_WSMAN_DMTF}:Option" => {'Name' => ['WINRS_CONSOLEMODE_STDIN','WINRS_SKIP_CMD_SHELL']}}} | |
} | |
- body = { "#{NS_WIN_SHELL}:Command" => "\"#{command}\"", "#{NS_WIN_SHELL}:Arguments" => arguments} | |
+ | |
+ if command.index(" ") then | |
+ raise "Command should not contain spaces" | |
+ end | |
+ body = { "#{NS_WIN_SHELL}:Command" => "#{command}", "#{NS_WIN_SHELL}:Arguments" => arguments} | |
builder = Builder::XmlMarkup.new | |
builder.instruct!(:xml, :encoding => 'UTF-8') | |
builder.tag! :env, :Envelope, namespaces do |env| | |
env.tag!(:env, :Header) { |h| h << Gyoku.xml(merge_headers(header,resource_uri_cmd,action_command,h_opts,selector_shell_id(shell_id))) } | |
env.tag!(:env, :Body) do |env_body| | |
- env_body.tag!("#{NS_WIN_SHELL}:CommandLine") { |cl| cl << Gyoku.xml(body) } | |
+ env_body.tag!("#{NS_WIN_SHELL}:CommandLine") { |cl| cl << Gyoku.xml(body).gsub(''', "'") } | |
end | |
end | |
- # Grab the command element and unescape any single quotes - issue 69 | |
xml = builder.target! | |
- escaped_cmd = /<#{NS_WIN_SHELL}:Command>(.+)<\/#{NS_WIN_SHELL}:Command>/m.match(xml)[1] | |
- xml[escaped_cmd] = escaped_cmd.gsub(/'/, "'") | |
- | |
resp_doc = send_message(xml) | |
command_id = REXML::XPath.first(resp_doc, "//#{NS_WIN_SHELL}:CommandId").text | |
@@ -289,6 +289,25 @@ module WinRM | |
true | |
end | |
+ # Splits a command string into an array | |
+ # @param [String] command with arguments | |
+ # @return [Array <String>] [command, arg1, arg2, …] | |
+ def shell_split(line) | |
+ words = [] | |
+ field = '' | |
+ line.gsub!(/\^(['"])/, '\\\\\1') | |
+ line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do | |
+ |word, sq, dq, esc, garbage, sep| | |
+ raise ArgumentError, "Unmatched double quote: #{line.inspect}" if garbage | |
+ field << (word || sq || (dq || esc).gsub(/\\(.)/, '\\1')) | |
+ if sep | |
+ words << field.gsub(/(['"])/, '^\1') | |
+ field = '' | |
+ end | |
+ end | |
+ words | |
+ end | |
+ | |
# Run a CMD command | |
# @param [String] command The command to run on the remote system | |
# @param [Array <String>] arguments arguments to the command | |
@@ -297,6 +316,10 @@ module WinRM | |
def run_cmd(command, arguments = [], &block) | |
command_output = nil | |
open_shell do |shell_id| | |
+ if command.index(" ") then | |
+ warn "WinRS::run_cmd: Passing the command as one big string is discouraged" | |
+ command, *arguments = shell_split(command).concat(arguments) | |
+ end | |
run_command(shell_id, command, arguments) do |command_id| | |
command_output = get_command_output(shell_id, command_id, &block) | |
end | |
@@ -336,14 +359,14 @@ module WinRM | |
builder.tag! :env, :Envelope, namespaces do |env| | |
env.tag!(:env, :Header) { |h| h << Gyoku.xml(merge_headers(header,resource_uri_wmi,action_enumerate)) } | |
env.tag!(:env, :Body) do |env_body| | |
- env_body.tag!("#{NS_ENUM}:Enumerate") { |en| en << Gyoku.xml(body) } | |
+ env_body.tag!("#{NS_ENUM}:Enumerate") { |en| en << Gyoku.xml(body).gsub(''', "'") } | |
end | |
end | |
resp = send_message(builder.target!) | |
parser = Nori.new(:parser => :rexml, :advanced_typecasting => false, :convert_tags_to => lambda { |tag| tag.snakecase.to_sym }, :strip_namespaces => true) | |
hresp = parser.parse(resp.to_s)[:envelope][:body] | |
- | |
+ | |
# Normalize items so the type always has an array even if it's just a single item. | |
items = {} | |
if hresp[:enumerate_response][:items] | |
@@ -416,7 +439,7 @@ module WinRM | |
rescue WinRMWSManFault => e | |
# If no output is available before the wsman:OperationTimeout expires, | |
# the server MUST return a WSManFault with the Code attribute equal to | |
- # 2150858793. When the client receives this fault, it SHOULD issue | |
+ # 2150858793. When the client receives this fault, it SHOULD issue | |
# another Receive request. | |
# http://msdn.microsoft.com/en-us/library/cc251676.aspx | |
if e.fault_code == '2150858793' | |
@@ -429,7 +452,7 @@ module WinRM | |
def send_message(message) | |
@xfer.send_request(message) | |
end | |
- | |
+ | |
# Helper methods for SOAP Headers | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment