winrm 2.2.3 → 2.3.0

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 (116) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +13 -1
  3. data/.travis.yml +10 -11
  4. data/Gemfile +2 -3
  5. data/README.md +1 -1
  6. data/Rakefile +3 -4
  7. data/appveyor.yml +1 -2
  8. data/bin/rwinrm +90 -97
  9. data/changelog.md +5 -0
  10. data/lib/winrm.rb +3 -5
  11. data/lib/winrm/connection.rb +84 -86
  12. data/lib/winrm/connection_opts.rb +90 -91
  13. data/lib/winrm/exceptions.rb +14 -2
  14. data/lib/winrm/http/response_handler.rb +127 -96
  15. data/lib/winrm/http/transport.rb +462 -427
  16. data/lib/winrm/http/transport_factory.rb +1 -5
  17. data/lib/winrm/output.rb +1 -2
  18. data/lib/winrm/psrp/fragment.rb +0 -2
  19. data/lib/winrm/psrp/message.rb +1 -3
  20. data/lib/winrm/psrp/message_data.rb +0 -2
  21. data/lib/winrm/psrp/message_data/base.rb +0 -2
  22. data/lib/winrm/psrp/message_data/error_record.rb +0 -2
  23. data/lib/winrm/psrp/message_data/pipeline_host_call.rb +0 -2
  24. data/lib/winrm/psrp/message_data/pipeline_output.rb +48 -54
  25. data/lib/winrm/psrp/message_data/pipeline_state.rb +0 -2
  26. data/lib/winrm/psrp/message_data/runspacepool_host_call.rb +0 -2
  27. data/lib/winrm/psrp/message_data/runspacepool_state.rb +0 -2
  28. data/lib/winrm/psrp/message_data/session_capability.rb +0 -2
  29. data/lib/winrm/psrp/message_defragmenter.rb +2 -2
  30. data/lib/winrm/psrp/message_factory.rb +2 -3
  31. data/lib/winrm/psrp/message_fragmenter.rb +1 -3
  32. data/lib/winrm/psrp/powershell_output_decoder.rb +0 -2
  33. data/lib/winrm/psrp/receive_response_reader.rb +3 -5
  34. data/lib/winrm/psrp/uuid.rb +1 -2
  35. data/lib/winrm/shells/base.rb +6 -4
  36. data/lib/winrm/shells/cmd.rb +63 -65
  37. data/lib/winrm/shells/power_shell.rb +207 -202
  38. data/lib/winrm/shells/retryable.rb +44 -45
  39. data/lib/winrm/shells/shell_factory.rb +0 -2
  40. data/lib/winrm/version.rb +1 -3
  41. data/lib/winrm/wsmv/base.rb +0 -2
  42. data/lib/winrm/wsmv/cleanup_command.rb +1 -2
  43. data/lib/winrm/wsmv/close_shell.rb +1 -2
  44. data/lib/winrm/wsmv/command.rb +2 -3
  45. data/lib/winrm/wsmv/command_output.rb +2 -3
  46. data/lib/winrm/wsmv/command_output_decoder.rb +1 -2
  47. data/lib/winrm/wsmv/configuration.rb +0 -2
  48. data/lib/winrm/wsmv/create_pipeline.rb +0 -2
  49. data/lib/winrm/wsmv/create_shell.rb +2 -6
  50. data/lib/winrm/wsmv/header.rb +213 -215
  51. data/lib/winrm/wsmv/init_runspace_pool.rb +96 -95
  52. data/lib/winrm/wsmv/iso8601_duration.rb +0 -2
  53. data/lib/winrm/wsmv/keep_alive.rb +0 -2
  54. data/lib/winrm/wsmv/receive_response_reader.rb +128 -126
  55. data/lib/winrm/wsmv/send_data.rb +0 -2
  56. data/lib/winrm/wsmv/soap.rb +0 -2
  57. data/lib/winrm/wsmv/wql_pull.rb +54 -56
  58. data/lib/winrm/wsmv/wql_query.rb +98 -99
  59. data/lib/winrm/wsmv/write_stdin.rb +0 -2
  60. data/tests/integration/auth_timeout_spec.rb +0 -1
  61. data/tests/integration/cmd_spec.rb +2 -3
  62. data/tests/integration/issue_59_spec.rb +0 -1
  63. data/tests/integration/powershell_spec.rb +4 -5
  64. data/tests/integration/spec_helper.rb +3 -6
  65. data/tests/integration/transport_spec.rb +0 -1
  66. data/tests/integration/wql_spec.rb +33 -34
  67. data/tests/matchers.rb +2 -3
  68. data/tests/spec/configuration_spec.rb +0 -1
  69. data/tests/spec/connection_spec.rb +0 -2
  70. data/tests/spec/exception_spec.rb +0 -1
  71. data/tests/spec/http/transport_factory_spec.rb +1 -3
  72. data/tests/spec/http/transport_spec.rb +0 -1
  73. data/tests/spec/output_spec.rb +4 -3
  74. data/tests/spec/psrp/fragment_spec.rb +0 -2
  75. data/tests/spec/psrp/message_data/base_spec.rb +0 -2
  76. data/tests/spec/psrp/message_data/error_record_spec.rb +0 -2
  77. data/tests/spec/psrp/message_data/pipeline_host_call_spec.rb +0 -2
  78. data/tests/spec/psrp/message_data/pipeline_output_spec.rb +0 -2
  79. data/tests/spec/psrp/message_data/pipeline_state_spec.rb +0 -2
  80. data/tests/spec/psrp/message_data/runspace_pool_host_call_spec.rb +0 -2
  81. data/tests/spec/psrp/message_data/runspacepool_state_spec.rb +0 -2
  82. data/tests/spec/psrp/message_data/session_capability_spec.rb +0 -2
  83. data/tests/spec/psrp/message_data_spec.rb +0 -2
  84. data/tests/spec/psrp/message_defragmenter_spec.rb +0 -2
  85. data/tests/spec/psrp/message_fragmenter_spec.rb +0 -2
  86. data/tests/spec/psrp/powershell_output_decoder_spec.rb +0 -2
  87. data/tests/spec/psrp/psrp_message_spec.rb +10 -7
  88. data/tests/spec/psrp/recieve_response_reader_spec.rb +0 -2
  89. data/tests/spec/psrp/uuid_spec.rb +2 -2
  90. data/tests/spec/response_handler_spec.rb +69 -61
  91. data/tests/spec/shells/base_spec.rb +7 -5
  92. data/tests/spec/shells/cmd_spec.rb +4 -4
  93. data/tests/spec/shells/powershell_spec.rb +221 -175
  94. data/tests/spec/spec_helper.rb +0 -1
  95. data/tests/spec/stubs/responses/get_omi_command_output_response.xml.erb +23 -0
  96. data/tests/spec/stubs/responses/get_omi_command_output_response_not_done.xml.erb +24 -0
  97. data/tests/spec/stubs/responses/get_omi_config_response.xml +45 -0
  98. data/tests/spec/stubs/responses/get_omi_powershell_keepalive_response.xml.erb +33 -0
  99. data/tests/spec/stubs/responses/open_shell_omi.xml +43 -0
  100. data/tests/spec/stubs/responses/soap_fault_omi.xml +31 -0
  101. data/tests/spec/wsmv/cleanup_command_spec.rb +0 -2
  102. data/tests/spec/wsmv/close_shell_spec.rb +0 -2
  103. data/tests/spec/wsmv/command_output_decoder_spec.rb +0 -2
  104. data/tests/spec/wsmv/command_output_spec.rb +1 -3
  105. data/tests/spec/wsmv/command_spec.rb +0 -2
  106. data/tests/spec/wsmv/configuration_spec.rb +0 -2
  107. data/tests/spec/wsmv/create_pipeline_spec.rb +2 -3
  108. data/tests/spec/wsmv/create_shell_spec.rb +6 -5
  109. data/tests/spec/wsmv/init_runspace_pool_spec.rb +38 -36
  110. data/tests/spec/wsmv/keep_alive_spec.rb +4 -4
  111. data/tests/spec/wsmv/receive_response_reader_spec.rb +124 -123
  112. data/tests/spec/wsmv/send_data_spec.rb +4 -4
  113. data/tests/spec/wsmv/wql_query_spec.rb +11 -13
  114. data/tests/spec/wsmv/write_stdin_spec.rb +0 -2
  115. data/winrm.gemspec +11 -12
  116. metadata +73 -67
@@ -1,202 +1,207 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Copyright 2016 Shawn Neal <sneal@sneal.net>
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- require 'securerandom'
18
- require_relative 'base'
19
- require_relative '../psrp/message_fragmenter'
20
- require_relative '../psrp/receive_response_reader'
21
- require_relative '../wsmv/configuration'
22
- require_relative '../wsmv/create_pipeline'
23
- require_relative '../wsmv/send_data'
24
- require_relative '../wsmv/init_runspace_pool'
25
- require_relative '../wsmv/keep_alive'
26
-
27
- module WinRM
28
- module Shells
29
- # Proxy to a remote PowerShell instance
30
- class Powershell < Base
31
- include WinRM::WSMV::SOAP
32
-
33
- class << self
34
- def finalize(connection_opts, transport, shell_id)
35
- proc { Powershell.close_shell(connection_opts, transport, shell_id) }
36
- end
37
-
38
- def close_shell(connection_opts, transport, shell_id)
39
- msg = WinRM::WSMV::CloseShell.new(
40
- connection_opts,
41
- shell_id: shell_id,
42
- shell_uri: WinRM::WSMV::Header::RESOURCE_URI_POWERSHELL
43
- )
44
- transport.send_request(msg.build)
45
- end
46
- end
47
-
48
- # Create a new powershell shell
49
- # @param connection_opts [ConnectionOpts] The WinRM connection options
50
- # @param transport [HttpTransport] The WinRM SOAP transport
51
- # @param logger [Logger] The logger to log diagnostic messages to
52
- def initialize(connection_opts, transport, logger)
53
- super
54
- @shell_uri = WinRM::WSMV::Header::RESOURCE_URI_POWERSHELL
55
- end
56
-
57
- # Runs the specified command
58
- # @param command [String] The powershell script to run
59
- # @param block [&block] The optional callback for any realtime output
60
- # @yield [Message] PSRP Message in response
61
- # @yieldreturn [Array<Message>] All messages in response
62
- def send_pipeline_command(command, &block)
63
- with_command_shell(command) do |shell, cmd|
64
- response_reader.read_message(command_output_message(shell, cmd), true, &block)
65
- end
66
- end
67
-
68
- # calculate the maimum fragment size so that they will be as large as possible yet
69
- # no greater than the max_envelope_size_kb on the end point. To calculate this
70
- # threshold, we:
71
- # - determine the maximum number of bytes accepted on the endpoint
72
- # - subtract the non-fragment characters in the SOAP envelope
73
- # - determine the number of bytes that could be base64 encded to the above length
74
- # - subtract the fragment header bytes (ids, length, etc)
75
- def max_fragment_blob_size
76
- @max_fragment_blob_size ||= begin
77
- fragment_header_length = 21
78
-
79
- begin
80
- max_fragment_bytes = (max_envelope_size_kb * 1024) - empty_pipeline_envelope.length
81
- base64_deflated(max_fragment_bytes) - fragment_header_length
82
- rescue WinRMWSManFault => e
83
- # A non administrator user will encounter an access denied
84
- # error attempting to query winrm configuration.
85
- # we will assin a small default and adjust to a protocol
86
- # appropriate max length when that info is available
87
- raise unless e.fault_code == '5'
88
- WinRM::PSRP::MessageFragmenter::DEFAULT_BLOB_LENGTH
89
- end
90
- end
91
- end
92
-
93
- protected
94
-
95
- def response_reader
96
- @response_reader ||= WinRM::PSRP::ReceiveResponseReader.new(transport, logger)
97
- end
98
-
99
- def send_command(command, _arguments)
100
- command_id = SecureRandom.uuid.to_s.upcase
101
- command += "\r\nif (!$?) { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }"
102
- message = PSRP::MessageFactory.create_pipeline_message(@runspace_id, command_id, command)
103
- fragmenter.fragment(message) do |fragment|
104
- command_args = [connection_opts, shell_id, command_id, fragment]
105
- if fragment.start_fragment
106
- resp_doc = transport.send_request(WinRM::WSMV::CreatePipeline.new(*command_args).build)
107
- command_id = REXML::XPath.first(resp_doc, "//#{NS_WIN_SHELL}:CommandId").text
108
- else
109
- transport.send_request(WinRM::WSMV::SendData.new(*command_args).build)
110
- end
111
- end
112
-
113
- logger.debug("[WinRM] Command created for #{command} with id: #{command_id}")
114
- command_id
115
- end
116
-
117
- def open_shell
118
- @runspace_id = SecureRandom.uuid.to_s.upcase
119
- runspace_msg = WinRM::WSMV::InitRunspacePool.new(
120
- connection_opts,
121
- @runspace_id,
122
- open_shell_payload(@runspace_id)
123
- )
124
- resp_doc = transport.send_request(runspace_msg.build)
125
- shell_id = REXML::XPath.first(resp_doc, "//*[@Name='ShellId']").text
126
- wait_for_running(shell_id)
127
- shell_id
128
- end
129
-
130
- def out_streams
131
- %w(stdout)
132
- end
133
-
134
- private
135
-
136
- def base64_deflated(inflated_length)
137
- inflated_length / 4 * 3
138
- end
139
-
140
- def empty_pipeline_envelope
141
- WinRM::WSMV::CreatePipeline.new(
142
- connection_opts,
143
- '00000000-0000-0000-0000-000000000000',
144
- '00000000-0000-0000-0000-000000000000'
145
- ).build
146
- end
147
-
148
- def max_envelope_size_kb
149
- @max_envelope_size_kb ||= begin
150
- config_msg = WinRM::WSMV::Configuration.new(connection_opts)
151
- msg = config_msg.build
152
- resp_doc = transport.send_request(msg)
153
- REXML::XPath.first(resp_doc, "//#{NS_WSMAN_CONF}:MaxEnvelopeSizekb").text.to_i
154
- end
155
- end
156
-
157
- def open_shell_payload(shell_id)
158
- [
159
- WinRM::PSRP::MessageFactory.session_capability_message(shell_id),
160
- WinRM::PSRP::MessageFactory.init_runspace_pool_message(shell_id)
161
- ].map do |message|
162
- fragmenter.fragment(message).bytes
163
- end.flatten
164
- end
165
-
166
- def wait_for_running(shell_id)
167
- state = WinRM::PSRP::MessageData::RunspacepoolState::OPENING
168
- keepalive_msg = WinRM::WSMV::KeepAlive.new(connection_opts, shell_id)
169
-
170
- # 2 is "openned". if we start issuing commands while in "openning" the runspace
171
- # seems to hang
172
- until state == WinRM::PSRP::MessageData::RunspacepoolState::OPENED
173
- response_reader.read_message(keepalive_msg) do |message|
174
- logger.debug("[WinRM] polling for pipeline state. message: #{message.inspect}")
175
- parsed = message.parsed_data
176
- case parsed
177
- when WinRM::PSRP::MessageData::RunspacepoolState
178
- state = parsed.runspace_state
179
- when WinRM::PSRP::MessageData::SessionCapability
180
- # if the user lacks admin privileges, we cannot query the MaxEnvelopeSizeKB
181
- # on the server and will assign to a "best effort" default based on protocol version
182
- if fragmenter.max_blob_length == WinRM::PSRP::MessageFragmenter::DEFAULT_BLOB_LENGTH
183
- fragmenter.max_blob_length = default_protocol_envelope_size(parsed.protocol_version)
184
- end
185
- end
186
- end
187
- end
188
- end
189
-
190
- # Powershell v2.0 has a protocol version of 2.1
191
- # which defaults to a 150 MaxEnvelopeSizeKB
192
- # later versions default to 500
193
- def default_protocol_envelope_size(protocol_version)
194
- protocol_version > '2.1' ? 512000 : 153600
195
- end
196
-
197
- def fragmenter
198
- @fragmenter ||= WinRM::PSRP::MessageFragmenter.new(max_fragment_blob_size)
199
- end
200
- end
201
- end
202
- end
1
+ # Copyright 2016 Shawn Neal <sneal@sneal.net>
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 'securerandom'
16
+ require_relative 'base'
17
+ require_relative '../psrp/message_fragmenter'
18
+ require_relative '../psrp/receive_response_reader'
19
+ require_relative '../wsmv/configuration'
20
+ require_relative '../wsmv/create_pipeline'
21
+ require_relative '../wsmv/send_data'
22
+ require_relative '../wsmv/init_runspace_pool'
23
+ require_relative '../wsmv/keep_alive'
24
+
25
+ module WinRM
26
+ module Shells
27
+ # Proxy to a remote PowerShell instance
28
+ class Powershell < Base
29
+ include WinRM::WSMV::SOAP
30
+
31
+ class << self
32
+ def finalize(connection_opts, transport, shell_id)
33
+ proc { Powershell.close_shell(connection_opts, transport, shell_id) }
34
+ end
35
+
36
+ def close_shell(connection_opts, transport, shell_id)
37
+ msg = WinRM::WSMV::CloseShell.new(
38
+ connection_opts,
39
+ shell_id: shell_id,
40
+ shell_uri: WinRM::WSMV::Header::RESOURCE_URI_POWERSHELL
41
+ )
42
+ transport.send_request(msg.build)
43
+ end
44
+ end
45
+
46
+ # Create a new powershell shell
47
+ # @param connection_opts [ConnectionOpts] The WinRM connection options
48
+ # @param transport [HttpTransport] The WinRM SOAP transport
49
+ # @param logger [Logger] The logger to log diagnostic messages to
50
+ def initialize(connection_opts, transport, logger)
51
+ super
52
+ @shell_uri = WinRM::WSMV::Header::RESOURCE_URI_POWERSHELL
53
+ end
54
+
55
+ # Runs the specified command
56
+ # @param command [String] The powershell script to run
57
+ # @param block [&block] The optional callback for any realtime output
58
+ # @yield [Message] PSRP Message in response
59
+ # @yieldreturn [Array<Message>] All messages in response
60
+ def send_pipeline_command(command, &block)
61
+ with_command_shell(command) do |shell, cmd|
62
+ response_reader.read_message(command_output_message(shell, cmd), true, &block)
63
+ end
64
+ end
65
+
66
+ # calculate the maimum fragment size so that they will be as large as possible yet
67
+ # no greater than the max_envelope_size_kb on the end point. To calculate this
68
+ # threshold, we:
69
+ # - determine the maximum number of bytes accepted on the endpoint
70
+ # - subtract the non-fragment characters in the SOAP envelope
71
+ # - determine the number of bytes that could be base64 encded to the above length
72
+ # - subtract the fragment header bytes (ids, length, etc)
73
+ def max_fragment_blob_size
74
+ @max_fragment_blob_size ||= begin
75
+ fragment_header_length = 21
76
+
77
+ begin
78
+ max_fragment_bytes = (max_envelope_size_kb * 1024) - empty_pipeline_envelope.length
79
+ base64_deflated(max_fragment_bytes) - fragment_header_length
80
+ rescue WinRMWSManFault => e
81
+ # A non administrator user will encounter an access denied
82
+ # error attempting to query winrm configuration.
83
+ # we will assin a small default and adjust to a protocol
84
+ # appropriate max length when that info is available
85
+ raise unless e.fault_code == '5'
86
+
87
+ WinRM::PSRP::MessageFragmenter::DEFAULT_BLOB_LENGTH
88
+ rescue WinRMSoapFault
89
+ WinRM::PSRP::MessageFragmenter::DEFAULT_BLOB_LENGTH
90
+ end
91
+ end
92
+ end
93
+
94
+ protected
95
+
96
+ def response_reader
97
+ @response_reader ||= WinRM::PSRP::ReceiveResponseReader.new(transport, logger)
98
+ end
99
+
100
+ def send_command(command, _arguments)
101
+ command_id = SecureRandom.uuid.to_s.upcase
102
+ command += "\r\nif (!$?) { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }"
103
+ message = PSRP::MessageFactory.create_pipeline_message(@runspace_id, command_id, command)
104
+ fragmenter.fragment(message) do |fragment|
105
+ command_args = [connection_opts, shell_id, command_id, fragment]
106
+ if fragment.start_fragment
107
+ resp_doc = transport.send_request(WinRM::WSMV::CreatePipeline.new(*command_args).build)
108
+ command_id = REXML::XPath.first(resp_doc, "//*[local-name() = 'CommandId']").text
109
+ else
110
+ transport.send_request(WinRM::WSMV::SendData.new(*command_args).build)
111
+ end
112
+ end
113
+
114
+ logger.debug("[WinRM] Command created for #{command} with id: #{command_id}")
115
+ command_id
116
+ end
117
+
118
+ def open_shell
119
+ @runspace_id = SecureRandom.uuid.to_s.upcase
120
+ runspace_msg = WinRM::WSMV::InitRunspacePool.new(
121
+ connection_opts,
122
+ @runspace_id,
123
+ open_shell_payload(@runspace_id)
124
+ )
125
+ resp_doc = transport.send_request(runspace_msg.build)
126
+ shell_id = REXML::XPath.first(resp_doc, "//*[@Name='ShellId']").text
127
+ wait_for_running(shell_id)
128
+ shell_id
129
+ end
130
+
131
+ def out_streams
132
+ %w[stdout]
133
+ end
134
+
135
+ private
136
+
137
+ def base64_deflated(inflated_length)
138
+ inflated_length / 4 * 3
139
+ end
140
+
141
+ def empty_pipeline_envelope
142
+ WinRM::WSMV::CreatePipeline.new(
143
+ connection_opts,
144
+ '00000000-0000-0000-0000-000000000000',
145
+ '00000000-0000-0000-0000-000000000000'
146
+ ).build
147
+ end
148
+
149
+ def max_envelope_size_kb
150
+ # rubocop:disable Layout/RescueEnsureAlignment
151
+ @max_envelope_size_kb ||= begin
152
+ config_msg = WinRM::WSMV::Configuration.new(connection_opts)
153
+ msg = config_msg.build
154
+ resp_doc = transport.send_request(msg)
155
+ REXML::XPath.first(resp_doc, "//*[local-name() = 'MaxEnvelopeSizekb']").text.to_i
156
+ ensure
157
+ logger.debug("[WinRM] Endpoint doesn't support config request for MaxEnvelopsizekb")
158
+ end
159
+ # rubocop:enable Layout/RescueEnsureAlignment
160
+ end
161
+
162
+ def open_shell_payload(shell_id)
163
+ [
164
+ WinRM::PSRP::MessageFactory.session_capability_message(shell_id),
165
+ WinRM::PSRP::MessageFactory.init_runspace_pool_message(shell_id)
166
+ ].map do |message|
167
+ fragmenter.fragment(message).bytes
168
+ end.flatten
169
+ end
170
+
171
+ def wait_for_running(shell_id)
172
+ state = WinRM::PSRP::MessageData::RunspacepoolState::OPENING
173
+ keepalive_msg = WinRM::WSMV::KeepAlive.new(connection_opts, shell_id)
174
+
175
+ # 2 is "openned". if we start issuing commands while in "openning" the runspace
176
+ # seems to hang
177
+ until state == WinRM::PSRP::MessageData::RunspacepoolState::OPENED
178
+ response_reader.read_message(keepalive_msg) do |message|
179
+ logger.debug("[WinRM] polling for pipeline state. message: #{message.inspect}")
180
+ parsed = message.parsed_data
181
+ case parsed
182
+ when WinRM::PSRP::MessageData::RunspacepoolState
183
+ state = parsed.runspace_state
184
+ when WinRM::PSRP::MessageData::SessionCapability
185
+ # if the user lacks admin privileges, we cannot query the MaxEnvelopeSizeKB
186
+ # on the server and will assign to a "best effort" default based on protocol version
187
+ if fragmenter.max_blob_length == WinRM::PSRP::MessageFragmenter::DEFAULT_BLOB_LENGTH
188
+ fragmenter.max_blob_length = default_protocol_envelope_size(parsed.protocol_version)
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ # Powershell v2.0 has a protocol version of 2.1
196
+ # which defaults to a 150 MaxEnvelopeSizeKB
197
+ # later versions default to 500
198
+ def default_protocol_envelope_size(protocol_version)
199
+ protocol_version > '2.1' ? 512000 : 153600
200
+ end
201
+
202
+ def fragmenter
203
+ @fragmenter ||= WinRM::PSRP::MessageFragmenter.new(max_fragment_blob_size)
204
+ end
205
+ end
206
+ end
207
+ end
@@ -1,45 +1,44 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Copyright 2016 Shawn Neal <sneal@sneal.net>
4
- # Copyright 2015 Matt Wrock <matt@mattwrock.com>
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
-
18
- require_relative '../exceptions'
19
-
20
- module WinRM
21
- module Shells
22
- # Shell mixin for retrying an operation
23
- module Retryable
24
- RETRYABLE_EXCEPTIONS = lambda do
25
- [
26
- Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
27
- Errno::ECONNRESET, Errno::ENETUNREACH, Errno::EHOSTUNREACH, ::WinRM::WinRMWSManFault,
28
- ::WinRM::WinRMHTTPTransportError, ::WinRM::WinRMAuthorizationError,
29
- HTTPClient::KeepAliveDisconnected, HTTPClient::ConnectTimeoutError
30
- ].freeze
31
- end
32
-
33
- # Retries the operation a specified number of times with a delay between
34
- # @param retries [Integer] The number of times to retry
35
- # @param delay [Integer] The number of seconds to wait between retry attempts
36
- def retryable(retries, delay)
37
- yield
38
- rescue *RETRYABLE_EXCEPTIONS.call
39
- raise unless (retries -= 1) > 0
40
- sleep(delay)
41
- retry
42
- end
43
- end
44
- end
45
- end
1
+ # Copyright 2016 Shawn Neal <sneal@sneal.net>
2
+ # Copyright 2015 Matt Wrock <matt@mattwrock.com>
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 '../exceptions'
17
+
18
+ module WinRM
19
+ module Shells
20
+ # Shell mixin for retrying an operation
21
+ module Retryable
22
+ RETRYABLE_EXCEPTIONS = lambda do
23
+ [
24
+ Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
25
+ Errno::ECONNRESET, Errno::ENETUNREACH, Errno::EHOSTUNREACH, ::WinRM::WinRMWSManFault,
26
+ ::WinRM::WinRMHTTPTransportError, ::WinRM::WinRMAuthorizationError,
27
+ HTTPClient::KeepAliveDisconnected, HTTPClient::ConnectTimeoutError
28
+ ].freeze
29
+ end
30
+
31
+ # Retries the operation a specified number of times with a delay between
32
+ # @param retries [Integer] The number of times to retry
33
+ # @param delay [Integer] The number of seconds to wait between retry attempts
34
+ def retryable(retries, delay)
35
+ yield
36
+ rescue *RETRYABLE_EXCEPTIONS.call
37
+ raise unless (retries -= 1) > 0
38
+
39
+ sleep(delay)
40
+ retry
41
+ end
42
+ end
43
+ end
44
+ end