winrm 2.2.3 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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