Class: Rex::Proto::SMB::SimpleClient::OpenFile
- Inherits:
-
Object
- Object
- Rex::Proto::SMB::SimpleClient::OpenFile
- Defined in:
- lib/rex/proto/smb/simple_client/open_file.rb
Overview
This represents an open file, which can be read, written, or closed
Direct Known Subclasses
Instance Attribute Summary collapse
-
#chunk_size ⇒ Object
Returns the value of attribute chunk_size.
-
#client ⇒ Object
Returns the value of attribute client.
-
#file_id ⇒ Object
Returns the value of attribute file_id.
-
#mode ⇒ Object
Returns the value of attribute mode.
-
#name ⇒ Object
Returns the value of attribute name.
-
#tree_id ⇒ Object
Returns the value of attribute tree_id.
-
#versions ⇒ Object
Returns the value of attribute versions.
Instance Method Summary collapse
- #<<(data) ⇒ Object
-
#close ⇒ Object
Close this open file.
- #delete ⇒ Object
-
#initialize(client, name, tree_id, file_id, versions) ⇒ OpenFile
constructor
A new instance of OpenFile.
-
#read(length = nil, offset = 0) ⇒ Object
Read data from the file.
- #read_rex_smb(length, offset) ⇒ Object
- #read_ruby_smb(length, offset, depth = 0) ⇒ Object
-
#write(data, offset = 0) ⇒ Object
Write data to the file.
Constructor Details
#initialize(client, name, tree_id, file_id, versions) ⇒ OpenFile
Returns a new instance of OpenFile.
10 11 12 13 14 15 16 17 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 10 def initialize(client, name, tree_id, file_id, versions) self.client = client self.name = name self.tree_id = tree_id self.file_id = file_id self.chunk_size = 48000 self.versions = versions end |
Instance Attribute Details
#chunk_size ⇒ Object
Returns the value of attribute chunk_size.
8 9 10 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 8 def chunk_size @chunk_size end |
#client ⇒ Object
Returns the value of attribute client.
8 9 10 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 8 def client @client end |
#file_id ⇒ Object
Returns the value of attribute file_id.
8 9 10 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 8 def file_id @file_id end |
#mode ⇒ Object
Returns the value of attribute mode.
8 9 10 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 8 def mode @mode end |
#name ⇒ Object
Returns the value of attribute name.
8 9 10 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 8 def name @name end |
#tree_id ⇒ Object
Returns the value of attribute tree_id.
8 9 10 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 8 def tree_id @tree_id end |
#versions ⇒ Object
Returns the value of attribute versions.
8 9 10 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 8 def versions @versions end |
Instance Method Details
#<<(data) ⇒ Object
110 111 112 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 110 def <<(data) write(data) end |
#close ⇒ Object
Close this open file
28 29 30 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 28 def close client.close(file_id, tree_id) end |
#delete ⇒ Object
19 20 21 22 23 24 25 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 19 def delete begin close rescue StandardError end client.delete(name, tree_id) end |
#read(length = nil, offset = 0) ⇒ Object
Read data from the file
102 103 104 105 106 107 108 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 102 def read(length = nil, offset = 0) if self.client.is_a?(RubySMB::Client) read_ruby_smb(length, offset) else read_rex_smb(length, offset) end end |
#read_rex_smb(length, offset) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 65 def read_rex_smb(length, offset) if length.nil? data = '' fptr = offset ok = client.read(file_id, fptr, chunk_size) while ok && ok['Payload'].v['DataLenLow'] > 0 buff = ok.to_s.slice( ok['Payload'].v['DataOffset'] + 4, ok['Payload'].v['DataLenLow'] ) data << buff break if ok['Payload'].v['Remaining'] == 0 fptr += ok['Payload'].v['DataLenLow'] begin ok = client.read(file_id, fptr, chunk_size) rescue XCEPT::ErrorCode => e case e.error_code when 0x00050001 # Novell fires off an access denied error on EOF ok = nil else raise e end end end else ok = client.read(file_id, offset, length) data = ok.to_s.slice( ok['Payload'].v['DataOffset'] + 4, ok['Payload'].v['DataLenLow'] ) end data end |
#read_ruby_smb(length, offset, depth = 0) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 32 def read_ruby_smb(length, offset, depth = 0) file_size = client.open_files[client.last_file_id].size file_size_remaining = file_size - offset if length.nil? max_size = file_size_remaining else max_size = [length, file_size_remaining].min end fptr = offset chunk = [max_size, chunk_size].min data = client.read(file_id, fptr, chunk).pack('C*') fptr += data.length while data.length < max_size if (max_size - data.length) < chunk chunk = max_size - data.length end new_data = client.read(file_id, fptr, chunk).pack('C*') data << new_data fptr += new_data.length end data rescue RubySMB::Error::UnexpectedStatusCode => e if e. == 'STATUS_PIPE_EMPTY' && depth < 20 read_ruby_smb(max_size, offset, depth + 1) else raise e end end |
#write(data, offset = 0) ⇒ Object
Write data to the file
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/rex/proto/smb/simple_client/open_file.rb', line 115 def write(data, offset = 0) # Track our offset into the remote file fptr = offset # Duplicate the data so we can use slice! data = data.dup # Take our first chunk of bytes chunk = data.slice!(0, chunk_size) # Keep writing data until we run out until chunk.empty? ok = client.write(file_id, fptr, chunk) if self.client.is_a?(RubySMB::Client) cl = ok else cl = ok['Payload'].v['CountLow'] end # Partial write, push the failed data back into the queue if cl != chunk.length data = chunk.slice(cl - 1, chunk.length - cl) + data end # Increment our painter and grab the next chunk fptr += cl chunk = data.slice!(0, chunk_size) end fptr end |