psrp 0.0.1

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.
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