winrm 2.3.0 → 2.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/lib/winrm/http/response_handler.rb +1 -1
  3. data/lib/winrm/http/transport.rb +2 -2
  4. data/lib/winrm/psrp/message.rb +128 -128
  5. data/lib/winrm/psrp/message_data/error_record.rb +2 -0
  6. data/lib/winrm/psrp/message_data/pipeline_output.rb +1 -1
  7. data/lib/winrm/psrp/message_factory.rb +14 -2
  8. data/lib/winrm/psrp/powershell_output_decoder.rb +142 -142
  9. data/lib/winrm/shells/base.rb +1 -0
  10. data/lib/winrm/shells/power_shell.rb +4 -4
  11. data/lib/winrm/version.rb +1 -1
  12. metadata +16 -90
  13. data/.gitignore +0 -10
  14. data/.rubocop.yml +0 -38
  15. data/.travis.yml +0 -10
  16. data/Gemfile +0 -2
  17. data/Rakefile +0 -33
  18. data/Vagrantfile +0 -6
  19. data/WinrmAppveyor.psm1 +0 -32
  20. data/appveyor.yml +0 -50
  21. data/changelog.md +0 -133
  22. data/preamble +0 -17
  23. data/tests/integration/auth_timeout_spec.rb +0 -17
  24. data/tests/integration/cmd_spec.rb +0 -130
  25. data/tests/integration/config-example.yml +0 -16
  26. data/tests/integration/issue_59_spec.rb +0 -25
  27. data/tests/integration/powershell_spec.rb +0 -164
  28. data/tests/integration/spec_helper.rb +0 -62
  29. data/tests/integration/transport_spec.rb +0 -98
  30. data/tests/integration/wql_spec.rb +0 -33
  31. data/tests/matchers.rb +0 -59
  32. data/tests/spec/configuration_spec.rb +0 -183
  33. data/tests/spec/connection_spec.rb +0 -37
  34. data/tests/spec/exception_spec.rb +0 -49
  35. data/tests/spec/http/transport_factory_spec.rb +0 -66
  36. data/tests/spec/http/transport_spec.rb +0 -43
  37. data/tests/spec/output_spec.rb +0 -128
  38. data/tests/spec/psrp/fragment_spec.rb +0 -60
  39. data/tests/spec/psrp/message_data/base_spec.rb +0 -11
  40. data/tests/spec/psrp/message_data/error_record_spec.rb +0 -39
  41. data/tests/spec/psrp/message_data/pipeline_host_call_spec.rb +0 -23
  42. data/tests/spec/psrp/message_data/pipeline_output_spec.rb +0 -30
  43. data/tests/spec/psrp/message_data/pipeline_state_spec.rb +0 -38
  44. data/tests/spec/psrp/message_data/runspace_pool_host_call_spec.rb +0 -23
  45. data/tests/spec/psrp/message_data/runspacepool_state_spec.rb +0 -14
  46. data/tests/spec/psrp/message_data/session_capability_spec.rb +0 -28
  47. data/tests/spec/psrp/message_data_spec.rb +0 -33
  48. data/tests/spec/psrp/message_defragmenter_spec.rb +0 -45
  49. data/tests/spec/psrp/message_fragmenter_spec.rb +0 -103
  50. data/tests/spec/psrp/powershell_output_decoder_spec.rb +0 -98
  51. data/tests/spec/psrp/psrp_message_spec.rb +0 -73
  52. data/tests/spec/psrp/recieve_response_reader_spec.rb +0 -170
  53. data/tests/spec/psrp/uuid_spec.rb +0 -28
  54. data/tests/spec/response_handler_spec.rb +0 -69
  55. data/tests/spec/shells/base_spec.rb +0 -227
  56. data/tests/spec/shells/cmd_spec.rb +0 -75
  57. data/tests/spec/shells/powershell_spec.rb +0 -221
  58. data/tests/spec/spec_helper.rb +0 -46
  59. data/tests/spec/stubs/clixml/error_record.xml.erb +0 -84
  60. data/tests/spec/stubs/clixml/pipeline_state.xml.erb +0 -88
  61. data/tests/spec/stubs/responses/get_command_output_response.xml.erb +0 -13
  62. data/tests/spec/stubs/responses/get_command_output_response_not_done.xml.erb +0 -10
  63. data/tests/spec/stubs/responses/get_omi_command_output_response.xml.erb +0 -23
  64. data/tests/spec/stubs/responses/get_omi_command_output_response_not_done.xml.erb +0 -24
  65. data/tests/spec/stubs/responses/get_omi_config_response.xml +0 -45
  66. data/tests/spec/stubs/responses/get_omi_powershell_keepalive_response.xml.erb +0 -33
  67. data/tests/spec/stubs/responses/get_powershell_keepalive_response.xml.erb +0 -10
  68. data/tests/spec/stubs/responses/get_powershell_output_response.xml.erb +0 -12
  69. data/tests/spec/stubs/responses/get_powershell_output_response_not_done.xml.erb +0 -9
  70. data/tests/spec/stubs/responses/open_shell_omi.xml +0 -43
  71. data/tests/spec/stubs/responses/open_shell_v1.xml +0 -19
  72. data/tests/spec/stubs/responses/open_shell_v2.xml +0 -20
  73. data/tests/spec/stubs/responses/soap_fault_omi.xml +0 -31
  74. data/tests/spec/stubs/responses/soap_fault_v1.xml +0 -36
  75. data/tests/spec/stubs/responses/soap_fault_v2.xml +0 -42
  76. data/tests/spec/stubs/responses/wmi_error_v2.xml +0 -41
  77. data/tests/spec/wsmv/cleanup_command_spec.rb +0 -20
  78. data/tests/spec/wsmv/close_shell_spec.rb +0 -15
  79. data/tests/spec/wsmv/command_output_decoder_spec.rb +0 -35
  80. data/tests/spec/wsmv/command_output_spec.rb +0 -43
  81. data/tests/spec/wsmv/command_spec.rb +0 -17
  82. data/tests/spec/wsmv/configuration_spec.rb +0 -15
  83. data/tests/spec/wsmv/create_pipeline_spec.rb +0 -30
  84. data/tests/spec/wsmv/create_shell_spec.rb +0 -39
  85. data/tests/spec/wsmv/init_runspace_pool_spec.rb +0 -38
  86. data/tests/spec/wsmv/keep_alive_spec.rb +0 -21
  87. data/tests/spec/wsmv/receive_response_reader_spec.rb +0 -124
  88. data/tests/spec/wsmv/send_data_spec.rb +0 -30
  89. data/tests/spec/wsmv/wql_query_spec.rb +0 -11
  90. data/tests/spec/wsmv/write_stdin_spec.rb +0 -20
  91. data/winrm.gemspec +0 -46
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd8c4887729128df19666c0a4f2b099b088261f5cb60ecb1b2adf52810188710
4
- data.tar.gz: 8711a914b783a6f6a6a5f5f8eb15ad74d4798dcf29242ff4b3b59679858e0c9e
3
+ metadata.gz: 83ddbf7bb422d247c6719bac48f839c8415622056719da00b5a9fc3b36daea43
4
+ data.tar.gz: ff0a22885967f76514207f8742f1c673eb2a3f2ba641b0ab5b8e9f97de2deeec
5
5
  SHA512:
6
- metadata.gz: 87eb8b34f189b70da6d6fd21e70142892cd9a8485f952a649229fb8cde0f073796af6ed9eb904e6c6b2f6d270ee901ec3d8ad69c36cd575e0b8def04faf5f9c9
7
- data.tar.gz: eaf8d672f6f53d62029d41452cfeda2f1c9fba0164528ce057376b1ceb8805b5deb5dfd76d320c4f4eac695c66f3ac517460fbe72ca7de1b0a899bacb7cf9c91
6
+ metadata.gz: 854abafdd7d5484bc2611c0bc65d4852c2b2ba84e175185b486b66b9d4ec802ac65ded1b763b734f43d3994d60f7d85b1416fbf13ac0f61120e37c5e335b7488
7
+ data.tar.gz: fe87f65ada719004ae3ccb349517823f103981b1377c7d0c1b70dea755c183be203e99eab72cbfcbf9b05ce0366f069344a21cedebd772931ad85ef8f6212884
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'rexml/document'
15
+ require 'rexml/document' unless defined?(REXML::Document)
16
16
  require_relative '../wsmv/soap'
17
17
 
18
18
  module WinRM
@@ -74,7 +74,7 @@ module WinRM
74
74
  return unless @ssl_peer_fingerprint && !@ssl_peer_fingerprint_verified
75
75
 
76
76
  with_untrusted_ssl_connection do |connection|
77
- connection_cert = connection.peer_cert_chain.last
77
+ connection_cert = connection.peer_cert
78
78
  verify_ssl_fingerprint(connection_cert)
79
79
  end
80
80
  @logger.info("initial ssl fingerprint #{@ssl_peer_fingerprint} verified\n")
@@ -435,7 +435,7 @@ module WinRM
435
435
  str.sub!(%r{^.*Content-Type: application\/octet-stream\r\n(.*)--Encrypted.*$}m, '\1')
436
436
 
437
437
  len = str.unpack('L').first
438
- iov_data = str.unpack("LA#{len}A*")
438
+ iov_data = str.unpack("La#{len}a*")
439
439
  iov0[:buffer].value = iov_data[1]
440
440
  iov1[:buffer].value = iov_data[2]
441
441
 
@@ -1,128 +1,128 @@
1
- # Copyright 2015 Matt Wrock <matt@mattwrock.com>
2
- # Copyright 2016 Shawn Neal <sneal@sneal.net>
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the 'License');
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an 'AS IS' BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- require_relative 'uuid'
17
- require_relative 'message_data'
18
-
19
- module WinRM
20
- # PowerShell Remoting Protcol module
21
- module PSRP
22
- # PowerShell Remoting Protocol base message.
23
- # http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-PSRP%5D.pdf
24
- class Message
25
- include UUID
26
-
27
- # Value of message destination when sent to a client
28
- CLIENT_DESTINATION = 1
29
-
30
- # Value of message destination when sent to a server
31
- SERVER_DESTINATION = 2
32
-
33
- # All known PSRP message types
34
- MESSAGE_TYPES = {
35
- session_capability: 0x00010002,
36
- init_runspacepool: 0x00010004,
37
- public_key: 0x00010005,
38
- encrypted_session_key: 0x00010006,
39
- public_key_request: 0x00010007,
40
- connect_runspacepool: 0x00010008,
41
- runspace_init_data: 0x0002100b,
42
- reset_runspace_state: 0x0002100c,
43
- set_max_runspaces: 0x00021002,
44
- set_min_runspaces: 0x00021003,
45
- runspace_availability: 0x00021004,
46
- runspacepool_state: 0x00021005,
47
- create_pipeline: 0x00021006,
48
- get_available_runspaces: 0x00021007,
49
- user_event: 0x00021008,
50
- application_private_data: 0x00021009,
51
- get_command_metadata: 0x0002100a,
52
- runspacepool_host_call: 0x00021100,
53
- runspacepool_host_response: 0x00021101,
54
- pipeline_input: 0x00041002,
55
- end_of_pipeline_input: 0x00041003,
56
- pipeline_output: 0x00041004,
57
- error_record: 0x00041005,
58
- pipeline_state: 0x00041006,
59
- debug_record: 0x00041007,
60
- verbose_record: 0x00041008,
61
- warning_record: 0x00041009,
62
- progress_record: 0x00041010,
63
- information_record: 0x00041011,
64
- pipeline_host_call: 0x00041100,
65
- pipeline_host_response: 0x00041101
66
- }.freeze
67
-
68
- # Creates a new PSRP message instance
69
- # @param runspace_pool_id [String] The UUID of the remote shell/runspace pool.
70
- # @param pipeline_id [String] The UUID to correlate the command/pipeline response
71
- # @param type [Integer] The PSRP MessageType. This is most commonly
72
- # specified in hex, e.g. 0x00010002.
73
- # @param data [String] The PSRP payload as serialized XML
74
- # @param destination [Integer] The destination for this message - client or server
75
- def initialize(
76
- runspace_pool_id,
77
- type,
78
- data,
79
- pipeline_id = nil,
80
- destination = SERVER_DESTINATION
81
- )
82
- raise 'invalid message type' unless MESSAGE_TYPES.value?(type)
83
-
84
- @data = data
85
- @destination = destination
86
- @type = type
87
- @pipeline_id = pipeline_id
88
- @runspace_pool_id = runspace_pool_id
89
- end
90
-
91
- attr_reader :destination, :type, :runspace_pool_id, :pipeline_id, :data
92
-
93
- # Returns the raw PSRP message bytes ready for transfer to Windows inside a
94
- # WinRM message.
95
- # @return [Array<Byte>] Unencoded raw byte array of the PSRP message.
96
- def bytes
97
- [
98
- int16le(destination),
99
- int16le(type),
100
- uuid_to_windows_guid_bytes(runspace_pool_id),
101
- uuid_to_windows_guid_bytes(pipeline_id),
102
- byte_order_mark,
103
- data_bytes
104
- ].flatten
105
- end
106
-
107
- # Parses the raw data to a MessageData class
108
- # @return [MessageData::Base] MessageData corresponding to this message type
109
- def parsed_data
110
- @parsed_data ||= MessageData.parse(self)
111
- end
112
-
113
- private
114
-
115
- def byte_order_mark
116
- [239, 187, 191]
117
- end
118
-
119
- def data_bytes
120
- @data_bytes ||= data.force_encoding('utf-8').bytes
121
- end
122
-
123
- def int16le(int16)
124
- [int16].pack('N').unpack('C4').reverse
125
- end
126
- end
127
- end
128
- end
1
+ # Copyright 2015 Matt Wrock <matt@mattwrock.com>
2
+ # Copyright 2016 Shawn Neal <sneal@sneal.net>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the 'License');
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an 'AS IS' BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require_relative 'uuid'
17
+ require_relative 'message_data'
18
+
19
+ module WinRM
20
+ # PowerShell Remoting Protcol module
21
+ module PSRP
22
+ # PowerShell Remoting Protocol base message.
23
+ # http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-PSRP%5D.pdf
24
+ class Message
25
+ include UUID
26
+
27
+ # Value of message destination when sent to a client
28
+ CLIENT_DESTINATION = 1
29
+
30
+ # Value of message destination when sent to a server
31
+ SERVER_DESTINATION = 2
32
+
33
+ # All known PSRP message types
34
+ MESSAGE_TYPES = {
35
+ session_capability: 0x00010002,
36
+ init_runspacepool: 0x00010004,
37
+ public_key: 0x00010005,
38
+ encrypted_session_key: 0x00010006,
39
+ public_key_request: 0x00010007,
40
+ connect_runspacepool: 0x00010008,
41
+ runspace_init_data: 0x0002100b,
42
+ reset_runspace_state: 0x0002100c,
43
+ set_max_runspaces: 0x00021002,
44
+ set_min_runspaces: 0x00021003,
45
+ runspace_availability: 0x00021004,
46
+ runspacepool_state: 0x00021005,
47
+ create_pipeline: 0x00021006,
48
+ get_available_runspaces: 0x00021007,
49
+ user_event: 0x00021008,
50
+ application_private_data: 0x00021009,
51
+ get_command_metadata: 0x0002100a,
52
+ runspacepool_host_call: 0x00021100,
53
+ runspacepool_host_response: 0x00021101,
54
+ pipeline_input: 0x00041002,
55
+ end_of_pipeline_input: 0x00041003,
56
+ pipeline_output: 0x00041004,
57
+ error_record: 0x00041005,
58
+ pipeline_state: 0x00041006,
59
+ debug_record: 0x00041007,
60
+ verbose_record: 0x00041008,
61
+ warning_record: 0x00041009,
62
+ progress_record: 0x00041010,
63
+ information_record: 0x00041011,
64
+ pipeline_host_call: 0x00041100,
65
+ pipeline_host_response: 0x00041101
66
+ }.freeze
67
+
68
+ # Creates a new PSRP message instance
69
+ # @param runspace_pool_id [String] The UUID of the remote shell/runspace pool.
70
+ # @param pipeline_id [String] The UUID to correlate the command/pipeline response
71
+ # @param type [Integer] The PSRP MessageType. This is most commonly
72
+ # specified in hex, e.g. 0x00010002.
73
+ # @param data [String] The PSRP payload as serialized XML
74
+ # @param destination [Integer] The destination for this message - client or server
75
+ def initialize(
76
+ runspace_pool_id,
77
+ type,
78
+ data,
79
+ pipeline_id = nil,
80
+ destination = SERVER_DESTINATION
81
+ )
82
+ raise 'invalid message type' unless MESSAGE_TYPES.value?(type)
83
+
84
+ @data = data
85
+ @destination = destination
86
+ @type = type
87
+ @pipeline_id = pipeline_id
88
+ @runspace_pool_id = runspace_pool_id
89
+ end
90
+
91
+ attr_reader :destination, :type, :runspace_pool_id, :pipeline_id, :data
92
+
93
+ # Returns the raw PSRP message bytes ready for transfer to Windows inside a
94
+ # WinRM message.
95
+ # @return [Array<Byte>] Unencoded raw byte array of the PSRP message.
96
+ def bytes
97
+ [
98
+ int16le(destination),
99
+ int16le(type),
100
+ uuid_to_windows_guid_bytes(runspace_pool_id),
101
+ uuid_to_windows_guid_bytes(pipeline_id),
102
+ byte_order_mark,
103
+ data_bytes
104
+ ].flatten
105
+ end
106
+
107
+ # Parses the raw data to a MessageData class
108
+ # @return [MessageData::Base] MessageData corresponding to this message type
109
+ def parsed_data
110
+ @parsed_data ||= MessageData.parse(self)
111
+ end
112
+
113
+ private
114
+
115
+ def byte_order_mark
116
+ [239, 187, 191]
117
+ end
118
+
119
+ def data_bytes
120
+ @data_bytes ||= data.force_encoding('utf-8').bytes
121
+ end
122
+
123
+ def int16le(int16)
124
+ [int16].pack('N').unpack('C4').reverse
125
+ end
126
+ end
127
+ end
128
+ end
@@ -48,6 +48,8 @@ module WinRM
48
48
 
49
49
  def property_hash(prop_name)
50
50
  prop_nodes = REXML::XPath.first(doc, "//*[@N='#{prop_name}']/Props")
51
+ return {} if prop_nodes.nil?
52
+
51
53
  prop_nodes.elements.each_with_object({}) do |node, props|
52
54
  name = node.attributes['N']
53
55
  props[underscore(name).to_sym] = node.text if node.text
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'rexml/document'
15
+ require 'rexml/document' unless defined?(REXML::Document)
16
16
 
17
17
  module WinRM
18
18
  module PSRP
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'erubis'
15
+ require 'erubi'
16
16
  require_relative 'message'
17
17
 
18
18
  module WinRM
@@ -66,7 +66,19 @@ module WinRM
66
66
  "#{File.dirname(__FILE__)}/#{template}.xml.erb"
67
67
  )
68
68
  template = File.read(template_path)
69
- Erubis::Eruby.new(template).result(context)
69
+ case context
70
+ when Hash
71
+ b = binding
72
+ locals = context.collect { |k, _| "#{k} = context[#{k.inspect}]; " }
73
+ b.eval(locals.join)
74
+ when Binding
75
+ b = context
76
+ when NilClass
77
+ b = binding
78
+ else
79
+ raise ArgumentError
80
+ end
81
+ b.eval(Erubi::Engine.new(template).src)
70
82
  end
71
83
  end
72
84
  end
@@ -1,142 +1,142 @@
1
- # Copyright 2016 Matt Wrock <matt@mattwrock.com>
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- require 'base64'
16
- require_relative 'message'
17
- require_relative 'message_data/pipeline_state'
18
-
19
- module WinRM
20
- module PSRP
21
- # Handles decoding a raw powershell output response
22
- class PowershellOutputDecoder
23
- # rubocop:disable Metrics/CyclomaticComplexity
24
- # Decode the raw SOAP output into decoded PSRP message,
25
- # Removes BOM and replaces encoded line endings
26
- # @param raw_output [String] The raw encoded output
27
- # @return [String] The decoded output
28
- def decode(message)
29
- case message.type
30
- when WinRM::PSRP::Message::MESSAGE_TYPES[:pipeline_output]
31
- decode_pipeline_output(message)
32
- when WinRM::PSRP::Message::MESSAGE_TYPES[:runspacepool_host_call]
33
- decode_host_call(message)
34
- when WinRM::PSRP::Message::MESSAGE_TYPES[:pipeline_host_call]
35
- decode_host_call(message)
36
- when WinRM::PSRP::Message::MESSAGE_TYPES[:error_record]
37
- decode_error_record(message)
38
- when WinRM::PSRP::Message::MESSAGE_TYPES[:pipeline_state]
39
- if message.parsed_data.pipeline_state == WinRM::PSRP::MessageData::PipelineState::FAILED
40
- decode_error_record(message)
41
- end
42
- end
43
- end
44
- # rubocop:enable Metrics/CyclomaticComplexity
45
-
46
- protected
47
-
48
- def decode_pipeline_output(message)
49
- message.parsed_data.output
50
- end
51
-
52
- def decode_host_call(message)
53
- text = begin
54
- case message.parsed_data.method_identifier
55
- when /WriteLine/, 'WriteErrorLine'
56
- "#{message.parsed_data.method_parameters[:s]}\r\n"
57
- when 'WriteDebugLine'
58
- "Debug: #{message.parsed_data.method_parameters[:s]}\r\n"
59
- when 'WriteWarningLine'
60
- "Warning: #{message.parsed_data.method_parameters[:s]}\r\n"
61
- when 'WriteVerboseLine'
62
- "Verbose: #{message.parsed_data.method_parameters[:s]}\r\n"
63
- when /Write[1-2]/
64
- message.parsed_data.method_parameters[:s]
65
- end
66
- end
67
-
68
- hex_decode(text)
69
- end
70
-
71
- def decode_error_record(message)
72
- parsed = message.parsed_data
73
- text = begin
74
- if message.type == WinRM::PSRP::Message::MESSAGE_TYPES[:pipeline_state]
75
- render_exception_as_error_record(parsed.exception_as_error_record)
76
- else
77
- case parsed.fully_qualified_error_id
78
- when 'Microsoft.PowerShell.Commands.WriteErrorException'
79
- render_write_error_exception(parsed)
80
- when 'NativeCommandError'
81
- render_native_command_error(parsed)
82
- when 'NativeCommandErrorMessage'
83
- parsed.exception[:message]
84
- else
85
- render_exception(parsed)
86
- end
87
- end
88
- end
89
-
90
- hex_decode(text)
91
- end
92
-
93
- def render_write_error_exception(parsed)
94
- <<EOH
95
- #{parsed.invocation_info[:line]} : #{parsed.exception[:message]}
96
- + CategoryInfo : #{parsed.error_category_message}
97
- + FullyQualifiedErrorId : #{parsed.fully_qualified_error_id}
98
- EOH
99
- end
100
-
101
- def render_exception(parsed)
102
- <<EOH
103
- #{parsed.exception[:message]}
104
- #{parsed.invocation_info[:position_message]}
105
- + CategoryInfo : #{parsed.error_category_message}
106
- + FullyQualifiedErrorId : #{parsed.fully_qualified_error_id}
107
- EOH
108
- end
109
-
110
- def render_native_command_error(parsed)
111
- <<EOH
112
- #{parsed.invocation_info[:my_command]} : #{parsed.exception[:message]}
113
- + CategoryInfo : #{parsed.error_category_message}
114
- + FullyQualifiedErrorId : #{parsed.fully_qualified_error_id}
115
- EOH
116
- end
117
-
118
- def render_exception_as_error_record(parsed)
119
- <<EOH
120
- #{parsed.exception[:message]}
121
- + CategoryInfo : #{parsed.error_category_message}
122
- + FullyQualifiedErrorId : #{parsed.fully_qualified_error_id}
123
- EOH
124
- end
125
-
126
- private
127
-
128
- def hex_decode(text)
129
- return unless text
130
-
131
- text.gsub(/_x(\h\h\h\h)_/) do
132
- decoded_text = Regexp.last_match[1].hex.chr.force_encoding('utf-8')
133
- if decoded_text.respond_to?(:scrub)
134
- decoded_text.scrub
135
- else
136
- decoded_text.encode('utf-16', invalid: :replace, undef: :replace).encode('utf-8')
137
- end
138
- end
139
- end
140
- end
141
- end
142
- end
1
+ # Copyright 2016 Matt Wrock <matt@mattwrock.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'base64' unless defined?(Base64)
16
+ require_relative 'message'
17
+ require_relative 'message_data/pipeline_state'
18
+
19
+ module WinRM
20
+ module PSRP
21
+ # Handles decoding a raw powershell output response
22
+ class PowershellOutputDecoder
23
+ # rubocop:disable Metrics/CyclomaticComplexity
24
+ # Decode the raw SOAP output into decoded PSRP message,
25
+ # Removes BOM and replaces encoded line endings
26
+ # @param raw_output [String] The raw encoded output
27
+ # @return [String] The decoded output
28
+ def decode(message)
29
+ case message.type
30
+ when WinRM::PSRP::Message::MESSAGE_TYPES[:pipeline_output]
31
+ decode_pipeline_output(message)
32
+ when WinRM::PSRP::Message::MESSAGE_TYPES[:runspacepool_host_call]
33
+ decode_host_call(message)
34
+ when WinRM::PSRP::Message::MESSAGE_TYPES[:pipeline_host_call]
35
+ decode_host_call(message)
36
+ when WinRM::PSRP::Message::MESSAGE_TYPES[:error_record]
37
+ decode_error_record(message)
38
+ when WinRM::PSRP::Message::MESSAGE_TYPES[:pipeline_state]
39
+ if message.parsed_data.pipeline_state == WinRM::PSRP::MessageData::PipelineState::FAILED
40
+ decode_error_record(message)
41
+ end
42
+ end
43
+ end
44
+ # rubocop:enable Metrics/CyclomaticComplexity
45
+
46
+ protected
47
+
48
+ def decode_pipeline_output(message)
49
+ message.parsed_data.output
50
+ end
51
+
52
+ def decode_host_call(message)
53
+ text = begin
54
+ case message.parsed_data.method_identifier
55
+ when /WriteLine/, 'WriteErrorLine'
56
+ "#{message.parsed_data.method_parameters[:s]}\r\n"
57
+ when 'WriteDebugLine'
58
+ "Debug: #{message.parsed_data.method_parameters[:s]}\r\n"
59
+ when 'WriteWarningLine'
60
+ "Warning: #{message.parsed_data.method_parameters[:s]}\r\n"
61
+ when 'WriteVerboseLine'
62
+ "Verbose: #{message.parsed_data.method_parameters[:s]}\r\n"
63
+ when /Write[1-2]/
64
+ message.parsed_data.method_parameters[:s]
65
+ end
66
+ end
67
+
68
+ hex_decode(text)
69
+ end
70
+
71
+ def decode_error_record(message)
72
+ parsed = message.parsed_data
73
+ text = begin
74
+ if message.type == WinRM::PSRP::Message::MESSAGE_TYPES[:pipeline_state]
75
+ render_exception_as_error_record(parsed.exception_as_error_record)
76
+ else
77
+ case parsed.fully_qualified_error_id
78
+ when 'Microsoft.PowerShell.Commands.WriteErrorException'
79
+ render_write_error_exception(parsed)
80
+ when 'NativeCommandError'
81
+ render_native_command_error(parsed)
82
+ when 'NativeCommandErrorMessage'
83
+ parsed.exception[:message]
84
+ else
85
+ render_exception(parsed)
86
+ end
87
+ end
88
+ end
89
+
90
+ hex_decode(text)
91
+ end
92
+
93
+ def render_write_error_exception(parsed)
94
+ <<EOH
95
+ #{parsed.invocation_info[:line]} : #{parsed.exception[:message]}
96
+ + CategoryInfo : #{parsed.error_category_message}
97
+ + FullyQualifiedErrorId : #{parsed.fully_qualified_error_id}
98
+ EOH
99
+ end
100
+
101
+ def render_exception(parsed)
102
+ <<EOH
103
+ #{parsed.exception[:message]}
104
+ #{parsed.invocation_info[:position_message]}
105
+ + CategoryInfo : #{parsed.error_category_message}
106
+ + FullyQualifiedErrorId : #{parsed.fully_qualified_error_id}
107
+ EOH
108
+ end
109
+
110
+ def render_native_command_error(parsed)
111
+ <<EOH
112
+ #{parsed.invocation_info[:my_command]} : #{parsed.exception[:message]}
113
+ + CategoryInfo : #{parsed.error_category_message}
114
+ + FullyQualifiedErrorId : #{parsed.fully_qualified_error_id}
115
+ EOH
116
+ end
117
+
118
+ def render_exception_as_error_record(parsed)
119
+ <<EOH
120
+ #{parsed.exception[:message]}
121
+ + CategoryInfo : #{parsed.error_category_message}
122
+ + FullyQualifiedErrorId : #{parsed.fully_qualified_error_id}
123
+ EOH
124
+ end
125
+
126
+ private
127
+
128
+ def hex_decode(text)
129
+ return unless text
130
+
131
+ text.gsub(/_x(\h\h\h\h)_/) do
132
+ decoded_text = Regexp.last_match[1].hex.chr.force_encoding('utf-8')
133
+ if decoded_text.respond_to?(:scrub)
134
+ decoded_text.scrub
135
+ else
136
+ decoded_text.encode('utf-16', invalid: :replace, undef: :replace).encode('utf-8')
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end