Class: RubySMB::SMB2::Pipe

Inherits:
File
  • Object
show all
Includes:
Dcerpc
Defined in:
lib/ruby_smb/smb2/pipe.rb

Overview

Represents a pipe on the Remote server that we can perform various I/O operations on.

Constant Summary collapse

STATUS_CONNECTED =
0x00000003
STATUS_CLOSING =
0x00000004

Constants inherited from File

File::MAX_PACKET_SIZE

Instance Attribute Summary

Attributes inherited from File

#attributes, #guid, #last_access, #last_change, #last_write, #name, #size, #size_on_disk, #tree

Instance Method Summary collapse

Methods included from Dcerpc

#bind, #ioctl_send_recv, #net_share_enum_all, #request

Methods inherited from File

#append, #close, #delete, #delete_packet, #initialize, #read, #read_packet, #rename, #rename_packet, #send_recv_read, #send_recv_write, #set_header_fields, #write, #write_packet

Constructor Details

This class inherits a constructor from RubySMB::SMB2::File

Instance Method Details

#is_connected?Boolean

Returns True if pipe is connected, false otherwise.

Returns:

  • (Boolean)

    True if pipe is connected, false otherwise



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/ruby_smb/smb2/pipe.rb', line 58

def is_connected?
  begin
    state = peek_state
  rescue RubySMB::Error::UnexpectedStatusCode => e
    if e.message == 'STATUS_FILE_CLOSED'
      return false
    end
    raise e
  end
  state == STATUS_CONNECTED
end

#peek(peek_size: 0) ⇒ RubySMB::SMB2::Packet::IoctlResponse

Performs a peek operation on the named pipe

Parameters:

  • peek_size (Integer) (defaults to: 0)

    Amount of data to peek

Returns:

Raises:



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/ruby_smb/smb2/pipe.rb', line 19

def peek(peek_size: 0)
  packet = RubySMB::SMB2::Packet::IoctlRequest.new
  packet.ctl_code = RubySMB::Fscc::ControlCodes::FSCTL_PIPE_PEEK
  packet.flags.is_fsctl = true
  # read at least 16 bytes for state, avail, msg_count, first_msg_len
  packet.max_output_response = 16 + peek_size
  packet = set_header_fields(packet)
  raw_response = @tree.client.send_recv(packet)
  response = RubySMB::SMB2::Packet::IoctlResponse.read(raw_response)
  unless response.valid?
    raise RubySMB::Error::InvalidPacket.new(
      expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
      expected_cmd:   RubySMB::SMB2::Packet::IoctlResponse::COMMAND,
      received_proto: response.smb2_header.protocol,
      received_cmd:   response.smb2_header.command
    )
  end

  unless response.status_code == WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW or response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
    raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
  end
  response
end

#peek_availableInteger

Returns The number of bytes available to be read from the pipe.

Returns:

  • (Integer)

    The number of bytes available to be read from the pipe



44
45
46
47
48
49
# File 'lib/ruby_smb/smb2/pipe.rb', line 44

def peek_available
  packet = peek
  state, avail, msg_count, first_msg_len = packet.buffer.unpack('VVVV')
  # Only 1 of these should be non-zero
  avail or first_msg_len
end

#peek_stateInteger

Returns Pipe status.

Returns:

  • (Integer)

    Pipe status



52
53
54
55
# File 'lib/ruby_smb/smb2/pipe.rb', line 52

def peek_state
  packet = peek
  packet.buffer.unpack('V')[0]
end