File Manager
Viewing File: message.rb
# Copyright 2015 Matt Wrock <matt@mattwrock.com>
# Copyright 2016 Shawn Neal <sneal@sneal.net>
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require_relative 'uuid'
require_relative 'message_data'
module WinRM
# PowerShell Remoting Protcol module
module PSRP
# PowerShell Remoting Protocol base message.
# http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-PSRP%5D.pdf
class Message
include UUID
# Value of message destination when sent to a client
CLIENT_DESTINATION = 1
# Value of message destination when sent to a server
SERVER_DESTINATION = 2
# All known PSRP message types
MESSAGE_TYPES = {
session_capability: 0x00010002,
init_runspacepool: 0x00010004,
public_key: 0x00010005,
encrypted_session_key: 0x00010006,
public_key_request: 0x00010007,
connect_runspacepool: 0x00010008,
runspace_init_data: 0x0002100b,
reset_runspace_state: 0x0002100c,
set_max_runspaces: 0x00021002,
set_min_runspaces: 0x00021003,
runspace_availability: 0x00021004,
runspacepool_state: 0x00021005,
create_pipeline: 0x00021006,
get_available_runspaces: 0x00021007,
user_event: 0x00021008,
application_private_data: 0x00021009,
get_command_metadata: 0x0002100a,
runspacepool_host_call: 0x00021100,
runspacepool_host_response: 0x00021101,
pipeline_input: 0x00041002,
end_of_pipeline_input: 0x00041003,
pipeline_output: 0x00041004,
error_record: 0x00041005,
pipeline_state: 0x00041006,
debug_record: 0x00041007,
verbose_record: 0x00041008,
warning_record: 0x00041009,
progress_record: 0x00041010,
information_record: 0x00041011,
pipeline_host_call: 0x00041100,
pipeline_host_response: 0x00041101
}.freeze
# Creates a new PSRP message instance
# @param runspace_pool_id [String] The UUID of the remote shell/runspace pool.
# @param pipeline_id [String] The UUID to correlate the command/pipeline response
# @param type [Integer] The PSRP MessageType. This is most commonly
# specified in hex, e.g. 0x00010002.
# @param data [String] The PSRP payload as serialized XML
# @param destination [Integer] The destination for this message - client or server
def initialize(
runspace_pool_id,
type,
data,
pipeline_id = nil,
destination = SERVER_DESTINATION
)
raise 'invalid message type' unless MESSAGE_TYPES.value?(type)
@data = data
@destination = destination
@type = type
@pipeline_id = pipeline_id
@runspace_pool_id = runspace_pool_id
end
attr_reader :destination, :type, :runspace_pool_id, :pipeline_id, :data
# Returns the raw PSRP message bytes ready for transfer to Windows inside a
# WinRM message.
# @return [Array<Byte>] Unencoded raw byte array of the PSRP message.
def bytes
[
int16le(destination),
int16le(type),
uuid_to_windows_guid_bytes(runspace_pool_id),
uuid_to_windows_guid_bytes(pipeline_id),
byte_order_mark,
data_bytes
].flatten
end
# Parses the raw data to a MessageData class
# @return [MessageData::Base] MessageData corresponding to this message type
def parsed_data
@parsed_data ||= MessageData.parse(self)
end
private
def byte_order_mark
[239, 187, 191]
end
def data_bytes
@data_bytes ||= data.force_encoding('utf-8').bytes
end
def int16le(int16)
[int16].pack('N').unpack('C4').reverse
end
end
end
end