psrp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/transport.rb ADDED
@@ -0,0 +1,208 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright 2016 Shawn Neal <sneal@sneal.net>
4
+ # Copyright 2016 Sam Oluwalana <soluwalana@gmail.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
+
19
+ require_relative "response_handler"
20
+
21
+ require 'monitor'
22
+
23
+ module PSRP
24
+ module HTTP
25
+
26
+ # straight copy from WinRM
27
+ # NTLM/Negotiate, secure, HTTP transport
28
+ class Negotiate
29
+
30
+ DEFAULT_RECEIVE_TIMEOUT = 3600
31
+
32
+ def initialize(endpoint, user, pass, opts)
33
+ @endpoint = endpoint.is_a?(String) ? URI.parse(endpoint) : endpoint
34
+ @httpcli = HTTPClient.new(agent_name: 'Ruby PSRP Client')
35
+ @httpcli.receive_timeout = DEFAULT_RECEIVE_TIMEOUT
36
+ @logger = Logging.logger[self]
37
+ require 'rubyntlm'
38
+ #p "USING HTTP NEGOTIATE"
39
+
40
+ # Deleting SSPI authentication
41
+ auths = @httpcli.www_auth.instance_variable_get('@authenticator')
42
+ auths.delete_if { |i| i.is_a? HTTPClient::SSPINegotiateAuth }
43
+
44
+ user_parts = user.split('\\')
45
+ if(user_parts.length > 1)
46
+ opts[:domain] = user_parts[0]
47
+ user = user_parts[1]
48
+ end
49
+
50
+ @ntlmcli = Net::NTLM::Client.new(user, pass, opts)
51
+ @retryable = true
52
+ no_ssl_peer_verification! if opts[:no_ssl_peer_verification]
53
+ @ssl_peer_fingerprint = opts[:ssl_peer_fingerprint]
54
+ @httpcli.ssl_config.set_trust_ca(opts[:ca_trust_path]) if opts[:ca_trust_path]
55
+
56
+ end
57
+
58
+ # Disable SSL Peer Verification
59
+ def no_ssl_peer_verification!
60
+ @httpcli.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
61
+ end
62
+
63
+ # SSL Peer Fingerprint Verification prior to connecting
64
+ def ssl_peer_fingerprint_verification!
65
+ return unless @ssl_peer_fingerprint && ! @ssl_peer_fingerprint_verified
66
+
67
+ with_untrusted_ssl_connection do |connection|
68
+ connection_cert = connection.peer_cert_chain.last
69
+ verify_ssl_fingerprint(connection_cert)
70
+ end
71
+ @logger.info("initial ssl fingerprint #{@ssl_peer_fingerprint} verified\n")
72
+ @ssl_peer_fingerprint_verified = true
73
+ no_ssl_peer_verification!
74
+ end
75
+
76
+ # Connect without verification to retrieve untrusted ssl context
77
+ def with_untrusted_ssl_connection
78
+ noverify_peer_context = OpenSSL::SSL::SSLContext.new
79
+ noverify_peer_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
80
+ tcp_connection = TCPSocket.new(@endpoint.host, @endpoint.port)
81
+ begin
82
+ ssl_connection = OpenSSL::SSL::SSLSocket.new(tcp_connection, noverify_peer_context)
83
+ ssl_connection.connect
84
+ yield ssl_connection
85
+ ensure
86
+ tcp_connection.close
87
+ end
88
+ end
89
+
90
+ # compare @ssl_peer_fingerprint to current ssl context
91
+ def verify_ssl_fingerprint(cert)
92
+ return unless @ssl_peer_fingerprint
93
+ conn_fingerprint = OpenSSL::Digest::SHA1.new(cert.to_der).to_s
94
+ return unless @ssl_peer_fingerprint.casecmp(conn_fingerprint) != 0
95
+ fail "ssl fingerprint mismatch!!!!\n"
96
+ end
97
+
98
+ # HTTP Client receive timeout. How long should a remote call wait for a
99
+ # for a response from WinRM?
100
+ def receive_timeout=(sec)
101
+ @httpcli.receive_timeout = sec
102
+ end
103
+
104
+ def receive_timeout
105
+ @httpcli.receive_timeout
106
+ end
107
+
108
+
109
+ def send_request(message, auth_header = nil)
110
+ ssl_peer_fingerprint_verification!
111
+ auth_header = init_auth if @ntlmcli.session.nil?
112
+
113
+ original_length = message.length
114
+
115
+ emessage = @ntlmcli.session.seal_message message
116
+ signature = @ntlmcli.session.sign_message message
117
+ seal = "\x10\x00\x00\x00#{signature}#{emessage}"
118
+
119
+ hdr = {
120
+ "Content-Type" => "multipart/encrypted;protocol=\"application/HTTP-SPNEGO-session-encrypted\";boundary=\"Encrypted Boundary\""
121
+ }
122
+ hdr.merge!(auth_header) if auth_header
123
+
124
+ # p hdr
125
+
126
+ body = [
127
+ "--Encrypted Boundary",
128
+ "Content-Type: application/HTTP-SPNEGO-session-encrypted",
129
+ "OriginalContent: type=application/soap+xml;charset=UTF-8;Length=#{original_length}",
130
+ "--Encrypted Boundary",
131
+ "Content-Type: application/octet-stream",
132
+ "#{seal}--Encrypted Boundary--",
133
+ ""
134
+ ].join("\r\n")
135
+
136
+ @logger.debug("\nOut-Message\n\n")
137
+ doc = REXML::Document.new message
138
+ out = ""
139
+ doc.write(out, 2)
140
+ @logger.debug(out)
141
+ @logger.debug("\n\n")
142
+
143
+ resp = @httpcli.post(@endpoint, body, hdr)
144
+ verify_ssl_fingerprint(resp.peer_cert)
145
+ if resp.status == 401 && @retryable
146
+ @retryable = false
147
+ send_request(message, init_auth)
148
+ else
149
+
150
+
151
+ @retryable = true
152
+ decrypted_body = resp.body.empty? ? '' : decrypt(resp.body)
153
+ handler = PSRP::ResponseHandler.new(decrypted_body, resp.status)
154
+ data = handler.parse_to_xml()
155
+
156
+ @logger.debug("Response data\n\n")
157
+ doc = REXML::Document.new decrypted_body
158
+ out = ""
159
+ doc.write(out, 2)
160
+ @logger.debug(out)
161
+
162
+ data
163
+ end
164
+ end
165
+
166
+ private
167
+
168
+ def decrypt(str)
169
+ str.force_encoding('BINARY')
170
+ str.sub!(/^.*Content-Type: application\/octet-stream\r\n(.*)--Encrypted.*$/m, '\1')
171
+
172
+ signature = str[4..19]
173
+ message = @ntlmcli.session.unseal_message str[20..-1]
174
+ if @ntlmcli.session.verify_signature(signature, message)
175
+ message
176
+ else
177
+ raise PSRP::PSRPError, "Could not verify SOAP message."
178
+ end
179
+ end
180
+
181
+ def init_auth
182
+ auth1 = @ntlmcli.init_context
183
+ hdr = {"Authorization" => "Negotiate #{auth1.encode64}",
184
+ "Content-Type" => "application/soap+xml;charset=UTF-8"
185
+ }
186
+ @logger.debug("Sending HTTP POST for Negotiate Authentication")
187
+ r = @httpcli.post(@endpoint, "", hdr)
188
+ verify_ssl_fingerprint(r.peer_cert)
189
+ itok = r.header["WWW-Authenticate"].pop.split.last
190
+ binding = r.peer_cert.nil? ? nil : Net::NTLM::ChannelBinding.create(r.peer_cert)
191
+ auth3 = @ntlmcli.init_context(itok, binding)
192
+ { "Authorization" => "Negotiate #{auth3.encode64}" }
193
+ end
194
+
195
+ def log_soap_message(message)
196
+ return unless @logger.debug?
197
+ xml_msg = REXML::Document.new(message)
198
+ formatter = REXML::Formatters::Pretty.new(2)
199
+ formatter.compact = true
200
+ formatter.write(xml_msg, @logger)
201
+ @logger.debug("\n")
202
+ rescue StandardError => e
203
+ @logger.debug("Couldn't log SOAP request/response: #{e.message} - #{message}")
204
+ end
205
+ end
206
+ end
207
+ end
208
+
data/lib/version.rb ADDED
@@ -0,0 +1,7 @@
1
+ # encoding: UTF-8
2
+
3
+ # PSRP module
4
+ module PSRP
5
+ # The version of the PSRP library
6
+ VERSION = '0.0.1'
7
+ end
@@ -0,0 +1,153 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright 2016 Shawn Neal <sneal@sneal.net>
4
+ # Copyright 2016 Sam Oluwalana <soluwalana@gmail.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 'commands/receive'
19
+
20
+ module PSRP
21
+
22
+ module WSMV
23
+ # Class to handle getting all the output of a command until it completes
24
+ class CommandOutputProcessor
25
+
26
+ attr :msgs
27
+
28
+ INPUT_REQUIRED = [
29
+ PSRP::Message::MESSAGE_TYPES[:PIPELINE_HOST_CALL],
30
+ PSRP::Message::MESSAGE_TYPES[:RUNSPACEPOOL_HOST_CALL]
31
+ ]
32
+
33
+ # Creates a new command output processor
34
+ # @param connection_opts [ConnectionOpts] The WinRM connection options
35
+ # @param transport [HttpTransport] The WinRM SOAP transport
36
+ # @param out_opts [Hash] Additional output options
37
+ def initialize(connection_opts, transport, out_opts = {})
38
+ @connection_opts = connection_opts
39
+ @transport = transport
40
+ @out_opts = out_opts
41
+ @has_error = false
42
+ @command_done = false
43
+ @input_required = false
44
+ @msgs = {}
45
+ end
46
+
47
+ # Gets the command output from the remote shell
48
+ # @param shell_id [UUID] The remote shell id running the command
49
+ # @param command_id [UUID] The command id to get output for
50
+ # @param block Optional callback for any output
51
+ def command_output(shell_id, command_id, reset = false)
52
+ if reset == true
53
+ @has_error = false
54
+ @command_done = false
55
+ @input_required = false
56
+ end
57
+
58
+ out_message = command_output_message(shell_id, command_id)
59
+ resp_doc = send_get_output_message(out_message)
60
+ streams(resp_doc)
61
+ @command_done = REXML::XPath.match(
62
+ resp_doc,
63
+ "//*[@State='http://schemas.microsoft.com/wbem/wsman/1/windows/shell/" \
64
+ "CommandState/Done']").any?
65
+ resp_doc
66
+ end
67
+
68
+ def command_output_message(shell_id, command_id)
69
+ cmd_out_opts = {
70
+ shell_id: shell_id
71
+ }.merge(@out_opts)
72
+ if command_id
73
+ cmd_out_opts[:command_id] = command_id
74
+ end
75
+ PSRP::WSMV::ReceiveOutput.new(@connection_opts, cmd_out_opts).build
76
+ end
77
+
78
+ def send_get_output_message(message)
79
+ resp_doc = @transport.send_request(message)
80
+ rescue PSRP::WSManFault => e
81
+ # If no output is available before the wsman:OperationTimeout expires,
82
+ # the server MUST return a WSManFault with the Code attribute equal to
83
+ # 2150858793. When the client receives this fault, it SHOULD issue
84
+ # another Receive request.
85
+ # http://msdn.microsoft.com/en-us/library/cc251676.aspx
86
+ if e.fault_code == '2150858793'
87
+ retry
88
+ else
89
+ raise
90
+ end
91
+ end
92
+
93
+ def exit_code(resp_doc)
94
+ REXML::XPath.first(resp_doc, "//#{NS_WIN_SHELL}:ExitCode").text.to_i
95
+ end
96
+
97
+ def streams(resp_doc)
98
+ REXML::XPath.match(resp_doc, "//#{PSRP::WSMV::NS_WIN_SHELL}:Stream").each do |n|
99
+ next if n.text.nil? || n.text.empty?
100
+ msg = decode(n.text)
101
+ if not @msgs.has_key? msg.message_id
102
+ @msgs[msg.message_id] = []
103
+ end
104
+ @msgs[msg.message_id].push(msg)
105
+ if INPUT_REQUIRED.include? msg.message_type
106
+ @input_required = true
107
+ elsif msg.message_type == PSRP::Message::MESSAGE_TYPES[:ERROR_RECORD]
108
+ @has_error = true
109
+ end
110
+ end
111
+ end
112
+
113
+ # Defragment Messages
114
+ def defragmented
115
+ datas = {}
116
+ @msgs.each do |msg_id, msg_list|
117
+ msg_list.sort do |a, b|
118
+ a.fragment_id <=> b.fragment_id
119
+ end
120
+ unfragmented = msg_list.inject('') do |data, msg|
121
+ data += msg.data
122
+ end
123
+ datas[msg_id] = {
124
+ message_type: msg_list[0].message_type,
125
+ data: unfragmented,
126
+ }
127
+ end
128
+ datas
129
+ end
130
+
131
+ def has_error?
132
+ @has_error
133
+ end
134
+
135
+ def input_required?
136
+ @input_required
137
+ end
138
+
139
+ def command_done?
140
+ @command_done
141
+ end
142
+
143
+ # Decode the raw PSRP output into decoded and human consumable object
144
+
145
+ # @param raw_output [String] The raw encoded output
146
+ # @return [String] The decoded output
147
+ def decode(raw_output)
148
+ # TODO: Add better decoding based on MS-PSRP 2.2.5
149
+ PSRP::MessageDecoder.new(raw_output)
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,293 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright 2016 Shawn Neal <sneal@sneal.net>
4
+ # Copyright 2016 Sam Oluwalana <soluwalana@gmail.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 '../psrp_message'
19
+
20
+ module Iso8601Duration
21
+ # Convert the number of seconds to an ISO8601 duration format
22
+ # @see http://tools.ietf.org/html/rfc2445#section-4.3.6
23
+ # @param [Fixnum] seconds The amount of seconds for this duration
24
+ def self.sec_to_dur(seconds)
25
+ seconds = seconds.to_i
26
+ iso_str = 'P'
27
+ if seconds > 604_800 # more than a week
28
+ weeks = seconds / 604_800
29
+ seconds -= (604_800 * weeks)
30
+ iso_str << "#{weeks}W"
31
+ end
32
+ if seconds > 86_400 # more than a day
33
+ days = seconds / 86_400
34
+ seconds -= (86_400 * days)
35
+ iso_str << "#{days}D"
36
+ end
37
+ if seconds > 0
38
+ iso_str << 'T'
39
+ if seconds > 3600 # more than an hour
40
+ hours = seconds / 3600
41
+ seconds -= (3600 * hours)
42
+ iso_str << "#{hours}H"
43
+ end
44
+ if seconds > 60 # more than a minute
45
+ minutes = seconds / 60
46
+ seconds -= (60 * minutes)
47
+ iso_str << "#{minutes}M"
48
+ end
49
+ iso_str << "#{seconds}S"
50
+ end
51
+
52
+ iso_str
53
+ end
54
+ end
55
+
56
+ module PSRP
57
+ module WSMV
58
+ # Base class for all WSMV message classes
59
+
60
+ NS_SOAP_ENV = 's' # http://www.w3.org/2003/05/soap-envelope
61
+ NS_ADDRESSING = 'a' # http://schemas.xmlsoap.org/ws/2004/08/addressing
62
+ NS_CIMBINDING = 'b' # http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd
63
+ NS_ENUM = 'n' # http://schemas.xmlsoap.org/ws/2004/09/enumeration
64
+ NS_TRANSFER = 'x' # http://schemas.xmlsoap.org/ws/2004/09/transfer
65
+ NS_WSMAN_DMTF = 'w' # http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
66
+ NS_WSMAN_MSFT = 'p' # http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd
67
+ NS_SCHEMA_INST = 'xsi' # http://www.w3.org/2001/XMLSchema-instance
68
+ NS_WIN_SHELL = 'rsp' # http://schemas.microsoft.com/wbem/wsman/1/windows/shell
69
+ NS_WSMAN_FAULT = 'f' # http://schemas.microsoft.com/wbem/wsman/1/wsmanfault
70
+ NS_WSMAN_CONF = 'cfg' # http://schemas.microsoft.com/wbem/wsman/1/config
71
+
72
+ # WSMan URI of the regular Windows cmd shell
73
+ RESOURCE_URI_CMD = 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd'
74
+
75
+ # WSMan URI for PowerShell
76
+ RESOURCE_URI_POWERSHELL = 'http://schemas.microsoft.com/powershell/Microsoft.PowerShell'
77
+
78
+ class Base
79
+
80
+ # Builds the WSMV message XML payload
81
+ def build
82
+ builder = Builder::XmlMarkup.new
83
+ builder.instruct!(:xml, encoding: 'UTF-8')
84
+ builder.tag! :env, :Envelope, namespaces do |env|
85
+ env.tag!(:env, :Header) do |env_header|
86
+ create_header(env_header)
87
+ end
88
+ env.tag!(:env, :Body) do |env_body|
89
+ create_body(env_body)
90
+ end
91
+ end
92
+ end
93
+
94
+ def namespaces
95
+ @namespaces ||= {
96
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
97
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
98
+ 'xmlns:env' => 'http://www.w3.org/2003/05/soap-envelope',
99
+ "xmlns:#{NS_ADDRESSING}" => 'http://schemas.xmlsoap.org/ws/2004/08/addressing',
100
+ "xmlns:#{NS_CIMBINDING}" => 'http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd',
101
+ "xmlns:#{NS_ENUM}" => 'http://schemas.xmlsoap.org/ws/2004/09/enumeration',
102
+ "xmlns:#{NS_TRANSFER}" => 'http://schemas.xmlsoap.org/ws/2004/09/transfer',
103
+ "xmlns:#{NS_WSMAN_DMTF}" => 'http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd',
104
+ "xmlns:#{NS_WSMAN_MSFT}" => 'http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd',
105
+ "xmlns:#{NS_WIN_SHELL}" => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell',
106
+ "xmlns:#{NS_WSMAN_CONF}" => 'http://schemas.microsoft.com/wbem/wsman/1/config'
107
+ }
108
+ end
109
+
110
+ protected
111
+
112
+ def create_header
113
+ fail 'create_header must be implemented'
114
+ end
115
+
116
+ def create_body
117
+ fail 'create_body must be implemented'
118
+ end
119
+
120
+ def encode_bytes(bytes)
121
+ Base64.strict_encode64(bytes.pack('C*'))
122
+ end
123
+
124
+ # Merge the various header hashes and make sure we carry all of the attributes
125
+ # through instead of overwriting them.
126
+ def merge_headers(*headers)
127
+ hdr = {}
128
+ headers.each do |h|
129
+ hdr.merge!(h) do |k, v1, v2|
130
+ v1.merge!(v2) if k == :attributes!
131
+ end
132
+ end
133
+ hdr
134
+ end
135
+
136
+ def shared_headers(session_opts)
137
+ {
138
+ "#{NS_ADDRESSING}:To" => "#{session_opts[:endpoint]}",
139
+ "#{NS_ADDRESSING}:ReplyTo" => {
140
+ "#{NS_ADDRESSING}:Address" =>
141
+ 'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous',
142
+ :attributes! => {
143
+ "#{NS_ADDRESSING}:Address" => {
144
+ 'mustUnderstand' => true
145
+ }
146
+ }
147
+ },
148
+ "#{NS_WSMAN_DMTF}:MaxEnvelopeSize" => session_opts[:max_envelope_size],
149
+ "#{NS_ADDRESSING}:MessageID" => "uuid:#{SecureRandom.uuid.to_s.upcase}",
150
+ "#{NS_WSMAN_MSFT}:SessionId" => "uuid:#{session_opts[:session_id]}",
151
+ "#{NS_WSMAN_DMTF}:Locale/" => '',
152
+ "#{NS_WSMAN_MSFT}:DataLocale/" => '',
153
+ # "#{NS_WSMAN_DMTF}:OperationTimeout" =>
154
+ # Iso8601Duration.sec_to_dur(session_opts[:operation_timeout]),
155
+ :attributes! => {
156
+ "#{NS_WSMAN_DMTF}:MaxEnvelopeSize" => { 'mustUnderstand' => true },
157
+ "#{NS_WSMAN_DMTF}:Locale/" => {
158
+ 'xml:lang' => session_opts[:locale], 'mustUnderstand' => false
159
+ },
160
+ "#{NS_WSMAN_MSFT}:DataLocale/" => {
161
+ 'xml:lang' => session_opts[:locale], 'mustUnderstand' => false
162
+ },
163
+ "#{NS_WSMAN_MSFT}:SessionId" => { 'mustUnderstand' => false }
164
+ }
165
+ }
166
+ end
167
+
168
+ # Helper methods for SOAP Headers
169
+
170
+ def resource_uri_shell(shell_uri)
171
+ {
172
+ "#{NS_WSMAN_DMTF}:ResourceURI" => shell_uri, :attributes! => {
173
+ "#{NS_WSMAN_DMTF}:ResourceURI" => {
174
+ 'mustUnderstand' => true
175
+ }
176
+ }
177
+ }
178
+ end
179
+
180
+ def resource_uri_cmd
181
+ resource_uri_shell(RESOURCE_URI_CMD)
182
+ end
183
+
184
+ def resource_uri_wmi(namespace = 'root/cimv2/*')
185
+ {
186
+ "#{NS_WSMAN_DMTF}:ResourceURI" =>
187
+ "http://schemas.microsoft.com/wbem/wsman/1/wmi/#{namespace}",
188
+ :attributes! => {
189
+ "#{NS_WSMAN_DMTF}:ResourceURI" => {
190
+ 'mustUnderstand' => true
191
+ }
192
+ }
193
+ }
194
+ end
195
+
196
+ def action_create
197
+ {
198
+ "#{NS_ADDRESSING}:Action" =>
199
+ 'http://schemas.xmlsoap.org/ws/2004/09/transfer/Create',
200
+ :attributes! => {
201
+ "#{NS_ADDRESSING}:Action" => {
202
+ 'mustUnderstand' => true
203
+ }
204
+ }
205
+ }
206
+ end
207
+
208
+ def action_delete
209
+ {
210
+ "#{NS_ADDRESSING}:Action" =>
211
+ 'http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete',
212
+ :attributes! => {
213
+ "#{NS_ADDRESSING}:Action" => {
214
+ 'mustUnderstand' => true
215
+ }
216
+ }
217
+ }
218
+ end
219
+
220
+ def action_command
221
+ {
222
+ "#{NS_ADDRESSING}:Action" =>
223
+ 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Command',
224
+ :attributes! => {
225
+ "#{NS_ADDRESSING}:Action" => {
226
+ 'mustUnderstand' => true
227
+ }
228
+ }
229
+ }
230
+ end
231
+
232
+ def action_send
233
+ {
234
+ "#{NS_ADDRESSING}:Action" =>
235
+ 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Send',
236
+ :attributes! => {
237
+ "#{NS_ADDRESSING}:Action" => {
238
+ 'mustUnderstand' => true
239
+ }
240
+ }
241
+ }
242
+ end
243
+
244
+ def action_receive
245
+ {
246
+ "#{NS_ADDRESSING}:Action" =>
247
+ 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive',
248
+ :attributes! => {
249
+ "#{NS_ADDRESSING}:Action" => {
250
+ 'mustUnderstand' => true
251
+ }
252
+ }
253
+ }
254
+ end
255
+
256
+ def action_signal
257
+ {
258
+ "#{NS_ADDRESSING}:Action" =>
259
+ 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Signal',
260
+ :attributes! => {
261
+ "#{NS_ADDRESSING}:Action" => {
262
+ 'mustUnderstand' => true
263
+ }
264
+ }
265
+ }
266
+ end
267
+
268
+ def action_enumerate
269
+ {
270
+ "#{NS_ADDRESSING}:Action" =>
271
+ 'http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate',
272
+ :attributes! => {
273
+ "#{NS_ADDRESSING}:Action" => {
274
+ 'mustUnderstand' => true
275
+ }
276
+ }
277
+ }
278
+ end
279
+
280
+ def selector_shell_id(shell_id)
281
+ {
282
+ "#{NS_WSMAN_DMTF}:SelectorSet" => {
283
+ "#{NS_WSMAN_DMTF}:Selector" => shell_id, :attributes! => {
284
+ "#{NS_WSMAN_DMTF}:Selector" => {
285
+ 'Name' => 'ShellId'
286
+ }
287
+ }
288
+ }
289
+ }
290
+ end
291
+ end
292
+ end
293
+ end