ruby_smb 0.0.12 → 0.0.13
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -2
- data/lib/ruby_smb/client/authentication.rb +1 -1
- data/lib/ruby_smb/client/echo.rb +36 -0
- data/lib/ruby_smb/client/tree_connect.rb +1 -1
- data/lib/ruby_smb/client.rb +17 -0
- data/lib/ruby_smb/dispatcher/socket.rb +21 -14
- data/lib/ruby_smb/error.rb +3 -0
- data/lib/ruby_smb/field/ea_info_array.rb +58 -0
- data/lib/ruby_smb/field/extended_attribute_flag.rb +10 -0
- data/lib/ruby_smb/field/file_full_ea_info.rb +15 -0
- data/lib/ruby_smb/field/security_descriptor.rb +42 -0
- data/lib/ruby_smb/field/smb_fea.rb +14 -0
- data/lib/ruby_smb/field/smb_fea_list.rb +13 -0
- data/lib/ruby_smb/field/utime.rb +54 -0
- data/lib/ruby_smb/field.rb +7 -0
- data/lib/ruby_smb/generic_packet.rb +8 -4
- data/lib/ruby_smb/impersonation_levels.rb +22 -0
- data/lib/ruby_smb/smb1/bit_field/create_options.rb +38 -0
- data/lib/ruby_smb/smb1/bit_field/file_access_mask.rb +1 -1
- data/lib/ruby_smb/smb1/bit_field/open2_access_mode.rb +42 -0
- data/lib/ruby_smb/smb1/bit_field/open2_flags.rb +18 -0
- data/lib/ruby_smb/smb1/bit_field/open2_open_mode.rb +17 -0
- data/lib/ruby_smb/smb1/bit_field/share_access.rb +20 -0
- data/lib/ruby_smb/smb1/bit_field/smb_ext_file_attributes.rb +35 -0
- data/lib/ruby_smb/smb1/bit_field/smb_file_attributes.rb +26 -0
- data/lib/ruby_smb/smb1/bit_field/smb_nmpipe_status.rb +19 -0
- data/lib/ruby_smb/smb1/bit_field/trans2_flags.rb +15 -0
- data/lib/ruby_smb/smb1/bit_field.rb +9 -0
- data/lib/ruby_smb/smb1/commands.rb +10 -6
- data/lib/ruby_smb/smb1/create_actions.rb +22 -0
- data/lib/ruby_smb/smb1/dispositions.rb +36 -0
- data/lib/ruby_smb/smb1/oplock_levels.rb +19 -0
- data/lib/ruby_smb/smb1/packet/echo_request.rb +30 -0
- data/lib/ruby_smb/smb1/packet/echo_response.rb +31 -0
- data/lib/ruby_smb/smb1/packet/empty_packet.rb +14 -0
- data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +85 -0
- data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +61 -0
- data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +47 -0
- data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +44 -0
- data/lib/ruby_smb/smb1/packet/nt_trans/subcommands.rb +11 -0
- data/lib/ruby_smb/smb1/packet/nt_trans.rb +16 -0
- data/lib/ruby_smb/smb1/packet/trans2/data_block.rb +32 -0
- data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +60 -0
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +65 -0
- data/lib/ruby_smb/smb1/packet/trans2/request.rb +52 -0
- data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +39 -0
- data/lib/ruby_smb/smb1/packet/trans2/response.rb +48 -0
- data/lib/ruby_smb/smb1/packet/trans2/subcommands.rb +12 -0
- data/lib/ruby_smb/smb1/packet/trans2.rb +18 -0
- data/lib/ruby_smb/smb1/packet.rb +5 -1
- data/lib/ruby_smb/smb1.rb +3 -0
- data/lib/ruby_smb/smb2/bit_field/{share_capabailities.rb → share_capabilities.rb} +0 -0
- data/lib/ruby_smb/smb2/bit_field/{smb2_capabailities.rb → smb2_capabilities.rb} +0 -0
- data/lib/ruby_smb/smb2/bit_field.rb +2 -2
- data/lib/ruby_smb/smb2/packet/echo_request.rb +21 -0
- data/lib/ruby_smb/smb2/packet/echo_response.rb +22 -0
- data/lib/ruby_smb/smb2/packet.rb +2 -0
- data/lib/ruby_smb/version.rb +1 -1
- data/ruby_smb.gemspec +2 -0
- data/spec/lib/ruby_smb/client_spec.rb +46 -0
- data/spec/lib/ruby_smb/field/ea_info_array_spec.rb +51 -0
- data/spec/lib/ruby_smb/field/extended_attribute_flag_spec.rb +16 -0
- data/spec/lib/ruby_smb/field/file_full_ea_info_spec.rb +35 -0
- data/spec/lib/ruby_smb/field/security_descriptor.rb +194 -0
- data/spec/lib/ruby_smb/field/smb_fea_list_spec.rb +38 -0
- data/spec/lib/ruby_smb/field/smb_fea_spec.rb +27 -0
- data/spec/lib/ruby_smb/field/utime_spec.rb +59 -0
- data/spec/lib/ruby_smb/smb1/bit_field/create_options_spec.rb +181 -0
- data/spec/lib/ruby_smb/smb1/bit_field/open2_access_mode_spec.rb +81 -0
- data/spec/lib/ruby_smb/smb1/bit_field/open2_flags_spec.rb +62 -0
- data/spec/lib/ruby_smb/smb1/bit_field/open2_open_mode_spec.rb +27 -0
- data/spec/lib/ruby_smb/smb1/bit_field/share_access_spec.rb +38 -0
- data/spec/lib/ruby_smb/smb1/bit_field/smb_ext_file_attributes_spec.rb +144 -0
- data/spec/lib/ruby_smb/smb1/bit_field/smb_file_attributes_spec.rb +113 -0
- data/spec/lib/ruby_smb/smb1/bit_field/smb_nmpipe_status_spec.rb +53 -0
- data/spec/lib/ruby_smb/smb1/bit_field/trans2_flags_spec.rb +28 -0
- data/spec/lib/ruby_smb/smb1/packet/echo_request_spec.rb +44 -0
- data/spec/lib/ruby_smb/smb1/packet/echo_response_spec.rb +44 -0
- data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +1 -1
- data/spec/lib/ruby_smb/smb1/packet/nt_trans/create_request_spec.rb +194 -0
- data/spec/lib/ruby_smb/smb1/packet/nt_trans/create_response_spec.rb +124 -0
- data/spec/lib/ruby_smb/smb1/packet/nt_trans/request_spec.rb +91 -0
- data/spec/lib/ruby_smb/smb1/packet/nt_trans/response_spec.rb +75 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/open2_request_spec.rb +112 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +107 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/request_secondary_spec.rb +77 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/request_spec.rb +98 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/response_spec.rb +88 -0
- data/spec/lib/ruby_smb/smb2/packet/echo_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/smb2/packet/echo_response_spec.rb +30 -0
- data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +1 -1
- data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +104 -7
- metadata.gz.sig +0 -0
- data/lib/ruby_smb/smb1/packet/error_packet.rb +0 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e599cfd32ed2eef3ec64db3aeef90291f419a8cd
|
|
4
|
+
data.tar.gz: 31069aa5863e82e9a681300863f22aa8d3fa9a00
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bacd65cd70045c29a402f6d81b9002ff63797203963929e96175466416700a73bbf761bd274902985e6bb0c901124b90740c3accb30d19b14e99e438eda6704a
|
|
7
|
+
data.tar.gz: b022e98f38ec3e9962b14dc2428f454405eb367205f0a32844a747988818d7c87732162cd1aa0581ad4ae2e93d09329ee76fc43a776df2fbe0f8556501f79c48
|
checksums.yaml.gz.sig
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
e�F">E��U��IQ�;�$����ท�ϐ%���JE���@�U�.���֏��PH<��ÕF���S�v�F����9?hz�_I��^�� BH�/&��d�ٕvLu��)4����8�of�ǝ�Œ����"�[2��}�t�Zy�ftf�U���Xփ
|
|
1
|
+
lzK3�->�wU�N+jGC
|
|
@@ -92,7 +92,7 @@ module RubySMB
|
|
|
92
92
|
begin
|
|
93
93
|
packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
|
|
94
94
|
rescue
|
|
95
|
-
packet = RubySMB::SMB1::Packet::
|
|
95
|
+
packet = RubySMB::SMB1::Packet::EmptyPacket.read(raw_response)
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
unless packet.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
class Client
|
|
3
|
+
|
|
4
|
+
# Contains the methods for doing ECHO commands
|
|
5
|
+
module Echo
|
|
6
|
+
|
|
7
|
+
# Sends an ECHO request packet and returns the
|
|
8
|
+
# last response packet.
|
|
9
|
+
#
|
|
10
|
+
# @param echo [Integer] the number of times the server should echo (ignored in SMB2)
|
|
11
|
+
# @param data [String] the data the server should echo back (ignored in SMB2)
|
|
12
|
+
# @return [RubySMB::SMB1::Packet::EchoResponse] the last Echo Response packet received
|
|
13
|
+
def smb1_echo(count: 1, data: '')
|
|
14
|
+
request = RubySMB::SMB2::Packet::EchoRequest.new
|
|
15
|
+
request.parameter_block.echo_count = count
|
|
16
|
+
request.data_block.data = data
|
|
17
|
+
raw_response = send_recv(request)
|
|
18
|
+
(count - 1).times do
|
|
19
|
+
raw_response = dispatcher.recv_packet
|
|
20
|
+
end
|
|
21
|
+
RubySMB::SMB1::Packet::EchoResponse.read(raw_response)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# Sends an ECHO request packet and returns the
|
|
26
|
+
# response packet.
|
|
27
|
+
#
|
|
28
|
+
# @return [RubySMB::SMB2::Packet::EchoResponse]
|
|
29
|
+
def smb2_echo
|
|
30
|
+
request = RubySMB::SMB2::Packet::EchoRequest.new
|
|
31
|
+
raw_response = send_recv(request)
|
|
32
|
+
RubySMB::SMB2::Packet::EchoResponse.read(raw_response)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -22,7 +22,7 @@ module RubySMB
|
|
|
22
22
|
begin
|
|
23
23
|
response = RubySMB::SMB1::Packet::TreeConnectResponse.read(raw_response)
|
|
24
24
|
rescue EOFError
|
|
25
|
-
response = RubySMB::SMB1::Packet::
|
|
25
|
+
response = RubySMB::SMB1::Packet::EmptyPacket.read(raw_response)
|
|
26
26
|
end
|
|
27
27
|
smb1_tree_from_response(share, response)
|
|
28
28
|
end
|
data/lib/ruby_smb/client.rb
CHANGED
|
@@ -7,11 +7,13 @@ module RubySMB
|
|
|
7
7
|
require 'ruby_smb/client/authentication'
|
|
8
8
|
require 'ruby_smb/client/signing'
|
|
9
9
|
require 'ruby_smb/client/tree_connect'
|
|
10
|
+
require 'ruby_smb/client/echo'
|
|
10
11
|
|
|
11
12
|
include RubySMB::Client::Negotiation
|
|
12
13
|
include RubySMB::Client::Authentication
|
|
13
14
|
include RubySMB::Client::Signing
|
|
14
15
|
include RubySMB::Client::TreeConnect
|
|
16
|
+
include RubySMB::Client::Echo
|
|
15
17
|
|
|
16
18
|
# The Default SMB1 Dialect string used in an SMB1 Negotiate Request
|
|
17
19
|
SMB1_DIALECT_SMB1_DEFAULT = "NT LM 0.12"
|
|
@@ -131,6 +133,21 @@ module RubySMB
|
|
|
131
133
|
dispatcher.tcp_socket.close
|
|
132
134
|
end
|
|
133
135
|
|
|
136
|
+
# Sends an Echo request to the server and returns the
|
|
137
|
+
# NTStatus of the last response packet received.
|
|
138
|
+
#
|
|
139
|
+
# @param echo [Integer] the number of times the server should echo (ignored in SMB2)
|
|
140
|
+
# @param data [String] the data the server should echo back (ignored in SMB2)
|
|
141
|
+
# @return [WindowsError::ErrorCode] the NTStatus of the last response received
|
|
142
|
+
def echo(count: 1, data: '' )
|
|
143
|
+
if smb2
|
|
144
|
+
response = smb2_echo
|
|
145
|
+
else
|
|
146
|
+
response = smb1_echo(count:count, data:data)
|
|
147
|
+
end
|
|
148
|
+
response.status_code
|
|
149
|
+
end
|
|
150
|
+
|
|
134
151
|
# Sets the message id field in an SMB2 packet's
|
|
135
152
|
# header to the one tracked by the client. It then increments
|
|
136
153
|
# the counter on the client.
|
|
@@ -27,10 +27,13 @@ class RubySMB::Dispatcher::Socket < RubySMB::Dispatcher::Base
|
|
|
27
27
|
def send_packet(packet)
|
|
28
28
|
data = nbss(packet) + packet.to_binary_s
|
|
29
29
|
bytes_written = 0
|
|
30
|
-
|
|
31
|
-
bytes_written
|
|
30
|
+
begin
|
|
31
|
+
while bytes_written < data.size
|
|
32
|
+
bytes_written += @tcp_socket.write(data[bytes_written..-1])
|
|
33
|
+
end
|
|
34
|
+
rescue IOError => e
|
|
35
|
+
raise RubySMB::Error::CommunicationError, "An error occured writing to the Socket"
|
|
32
36
|
end
|
|
33
|
-
|
|
34
37
|
nil
|
|
35
38
|
end
|
|
36
39
|
|
|
@@ -40,17 +43,21 @@ class RubySMB::Dispatcher::Socket < RubySMB::Dispatcher::Base
|
|
|
40
43
|
# @return [String]
|
|
41
44
|
# @todo should return SMB2::Packet
|
|
42
45
|
def recv_packet
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
begin
|
|
47
|
+
IO.select([@tcp_socket])
|
|
48
|
+
nbss_header = @tcp_socket.read(4) # Length of NBSS header. TODO: remove to a constant
|
|
49
|
+
if nbss_header.nil?
|
|
50
|
+
raise ::RubySMB::Error::NetBiosSessionService, 'NBSS Header is missing'
|
|
51
|
+
else
|
|
52
|
+
length = nbss_header.unpack('N').first
|
|
53
|
+
end
|
|
54
|
+
IO.select([@tcp_socket])
|
|
55
|
+
data = @tcp_socket.read(length)
|
|
56
|
+
data << @tcp_socket.read(length - data.length) while data.length < length
|
|
53
57
|
|
|
54
|
-
|
|
58
|
+
data
|
|
59
|
+
rescue Errno::EINVAL, TypeError => e
|
|
60
|
+
raise RubySMB::Error::CommunicationError, "An error occured reading from the Socket"
|
|
61
|
+
end
|
|
55
62
|
end
|
|
56
63
|
end
|
data/lib/ruby_smb/error.rb
CHANGED
|
@@ -14,4 +14,7 @@ module RubySMB::Error
|
|
|
14
14
|
|
|
15
15
|
# Raised when a response packet has a NTStatus code that was unexpected.
|
|
16
16
|
class UnexpectedStatusCode < StandardError; end
|
|
17
|
+
|
|
18
|
+
# Raised when an error occurs with the underlying socket.
|
|
19
|
+
class CommunicationError < StandardError; end
|
|
17
20
|
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module Field
|
|
3
|
+
# Convenience class that extend the normal {BinData::Array} for use
|
|
4
|
+
# with {RubySMB::Field::FileFullEaInfo}. This array will automatically
|
|
5
|
+
# updates the {RubySMB::Field::FileFullEaInfo#next_entry_offset} of
|
|
6
|
+
# each element in the array.
|
|
7
|
+
class EaInfoArray < BinData::Array
|
|
8
|
+
|
|
9
|
+
# Overrides the method from {BinData::Array} to
|
|
10
|
+
# call #update_offsets
|
|
11
|
+
# @raise [ArgumentError] if the inserted element is not a {RubySMB::Field::FileFullEaInfo}
|
|
12
|
+
def []=(index, value)
|
|
13
|
+
unless value.is_a? RubySMB::Field::FileFullEaInfo
|
|
14
|
+
raise ArgumentError, "This array can only contain RubySMB::Field::FileFullEaInfo objects"
|
|
15
|
+
end
|
|
16
|
+
retval = super(index,value)
|
|
17
|
+
update_offsets
|
|
18
|
+
retval
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Overrides the insert method in {BinData::Array} to
|
|
22
|
+
# call #update_offsets.
|
|
23
|
+
#
|
|
24
|
+
# @param index [Integer] the index to insert into the array at
|
|
25
|
+
# @param objs [Array<Object>] the objects to be inserted
|
|
26
|
+
# @raise [ArgumentError] if the inserted element is not a {RubySMB::Field::FileFullEaInfo}
|
|
27
|
+
# @return [self]
|
|
28
|
+
def insert(index, *objs)
|
|
29
|
+
objs.each do |x|
|
|
30
|
+
unless x.is_a? RubySMB::Field::FileFullEaInfo
|
|
31
|
+
raise ArgumentError, "This array can only contain RubySMB::Field::FileFullEaInfo objects"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
super(index, *objs)
|
|
35
|
+
update_offsets
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Iterates through all of the elements in the array and
|
|
39
|
+
# dynamically updates all of the next_record_offset fields
|
|
40
|
+
# to properly reflect the chain.
|
|
41
|
+
#
|
|
42
|
+
# @return [self]
|
|
43
|
+
def update_offsets
|
|
44
|
+
self.each do |element|
|
|
45
|
+
if element == self.last
|
|
46
|
+
# If this is the end of our array, the offset must be 0
|
|
47
|
+
element.next_entry_offset = 0
|
|
48
|
+
else
|
|
49
|
+
# If there is an element after this one, set the offset
|
|
50
|
+
element.next_entry_offset = element.do_num_bytes
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
self
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module Field
|
|
3
|
+
# Representation of the ExtendedAttributeFlag bit-field as defined in
|
|
4
|
+
# [2.2.1.2.2 SMB_FEA](https://msdn.microsoft.com/en-us/library/ee915515.aspx)
|
|
5
|
+
class ExtendedAttributeFlag < BinData::Record
|
|
6
|
+
bit1 :file_need_ea, label: 'EA Required'
|
|
7
|
+
bit7 :reserved, label: 'Reserved Space'
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module Field
|
|
3
|
+
# Class representing a FillFullEaInformation structure as defined in
|
|
4
|
+
# [2.4.15 FileFullEaInformation](https://msdn.microsoft.com/en-us/library/cc232069.aspx)
|
|
5
|
+
class FileFullEaInfo < BinData::Record
|
|
6
|
+
endian :little
|
|
7
|
+
uint32 :next_entry_offset, label: 'Next Entry Offset'
|
|
8
|
+
extended_attribute_flag :flags
|
|
9
|
+
uint8 :ea_name_length, label: 'EA Name Length', value: lambda { ea_name.do_num_bytes }
|
|
10
|
+
uint8 :ea_value_length, label: 'EA Value Length', value: lambda { ea_value.do_num_bytes }
|
|
11
|
+
string :ea_name, label: 'EA Name'
|
|
12
|
+
string :ea_value, label: 'EA Value'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module Field
|
|
3
|
+
# Class representing a SECURITY_DESCRIPTOR as defined in
|
|
4
|
+
# [2.4.6 SECURITY_DESCRIPTOR](https://msdn.microsoft.com/en-us/library/cc230366.aspx)
|
|
5
|
+
class SecurityDescriptor < BinData::Record
|
|
6
|
+
endian :little
|
|
7
|
+
uint8 :revision, label: 'Revision', initial_value: 0x01
|
|
8
|
+
uint8 :sbz1, label: 'Resource Manager Control Bits'
|
|
9
|
+
|
|
10
|
+
struct :control do
|
|
11
|
+
endian :little
|
|
12
|
+
bit1 :dacl_computed_inheritance, label: 'DACL Computed Inheritance'
|
|
13
|
+
bit1 :sacl_computed_inheritance, label: 'SACL Computed Inheritance'
|
|
14
|
+
bit1 :dacl_auto_inherited, label: 'DACL Auto-Inherited'
|
|
15
|
+
bit1 :sacl_auto_inherited, label: 'SACL Auto-Inherited'
|
|
16
|
+
bit1 :dacl_protected, label: 'DACL Protected'
|
|
17
|
+
bit1 :sacl_protected, label: 'SACL Protected'
|
|
18
|
+
bit1 :rm_control_valid, label: 'RM Control Valid'
|
|
19
|
+
bit1 :self_relative, label: 'Self-Relative Format', initial_value: 0x01
|
|
20
|
+
# Byte Boundary
|
|
21
|
+
bit1 :owner_defaulted, label: 'Owner Defaulted'
|
|
22
|
+
bit1 :group_defaulted, label: 'Group Defaulted'
|
|
23
|
+
bit1 :dacl_present, label: 'DACL Present'
|
|
24
|
+
bit1 :dacl_defaulted, label: 'DACL Defaulted'
|
|
25
|
+
bit1 :sacl_present, label: 'SACL Present'
|
|
26
|
+
bit1 :sacl_defaulted, label: 'SACL Defaulted'
|
|
27
|
+
bit1 :server_security, label: 'Server Security'
|
|
28
|
+
bit1 :dacl_trusted, label: 'DACL Trusted'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
uint32 :offset_owner, label: 'Offset Owner', value: lambda { owner_sid.rel_offset }
|
|
32
|
+
uint32 :offset_group, label: 'Offset Group', value: lambda { group_sid.rel_offset }
|
|
33
|
+
uint32 :offset_sacl, label: 'Offset SACL', value: lambda { sacl.rel_offset }
|
|
34
|
+
uint32 :offset_dacl, label: 'Offset DACL', value: lambda { dacl.rel_offset }
|
|
35
|
+
|
|
36
|
+
string :owner_sid, label: 'Owner SID'
|
|
37
|
+
string :group_sid, label: 'Group SID'
|
|
38
|
+
string :sacl, label: 'SACL'
|
|
39
|
+
string :dacl, label: 'DACL'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module Field
|
|
3
|
+
# Class representing an SMB File Extended Attribute as defined in
|
|
4
|
+
# [2.2.1.2.2 SMB_FEA](https://msdn.microsoft.com/en-us/library/ee915515.aspx)
|
|
5
|
+
class SmbFea < BinData::Record
|
|
6
|
+
endian :little
|
|
7
|
+
extended_attribute_flag :ea_flag, label: 'Extended Attribute Flag'
|
|
8
|
+
uint8 :attribute_name_length, label: 'Attribute Name Length', value: lambda { attribute_name.length}
|
|
9
|
+
uint16 :attribute_value_length, label: 'Attribute Value Length', value: lambda { attribute_value.length}
|
|
10
|
+
string :attribute_name, label: 'Attribute Name'
|
|
11
|
+
string :attribute_value, label: 'Attribute Value'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module Field
|
|
3
|
+
# Class representing an SMB File Extended Attribute List as defined in
|
|
4
|
+
# [2.2.1.2.2.1 SMB_FEA_LIST](https://msdn.microsoft.com/en-us/library/ff359296.aspx)
|
|
5
|
+
class SmbFeaList < BinData::Record
|
|
6
|
+
endian :little
|
|
7
|
+
uint32 :size_of_list, label: 'Size of List in Bytes', value: lambda { fea_list.do_num_bytes }
|
|
8
|
+
array :fea_list, initial_length: 0 do
|
|
9
|
+
smb_fea
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module Field
|
|
3
|
+
|
|
4
|
+
# Conveneince class for dealing with 32-bit unsigned UTIME
|
|
5
|
+
# fields in SMB, as defined in
|
|
6
|
+
# [2.2.1.4.3 UTIME](https://msdn.microsoft.com/en-us/library/ee441907.aspx)
|
|
7
|
+
class Utime < BinData::Primitive
|
|
8
|
+
endian :little
|
|
9
|
+
uint32 :val
|
|
10
|
+
|
|
11
|
+
# Gets the value of the field
|
|
12
|
+
#
|
|
13
|
+
# @return [BinData::Bit32] the 64-bit value of the field
|
|
14
|
+
def get
|
|
15
|
+
val
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Sets the value of the field from a DateTime,Time,Fixnum, or object
|
|
19
|
+
# that can be converted to an integer. Any other
|
|
20
|
+
# parameter passed in will be assumed to already be correct.
|
|
21
|
+
#
|
|
22
|
+
# @param value [DateTime,Time,Fixnum,#to_i] the value to set
|
|
23
|
+
# @return
|
|
24
|
+
def set(value)
|
|
25
|
+
case value
|
|
26
|
+
when DateTime
|
|
27
|
+
set(value.to_time)
|
|
28
|
+
when Time
|
|
29
|
+
set(value.to_i)
|
|
30
|
+
when Fixnum
|
|
31
|
+
self.val = value
|
|
32
|
+
else
|
|
33
|
+
self.val = value.to_i
|
|
34
|
+
end
|
|
35
|
+
val
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Returns the value of the field as a {DateTime}
|
|
39
|
+
#
|
|
40
|
+
# @return [DateTime] the {DateTime} representation of the current value
|
|
41
|
+
def to_datetime
|
|
42
|
+
time = to_time
|
|
43
|
+
time.to_datetime
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns the value of the field as a {Time}
|
|
47
|
+
#
|
|
48
|
+
# @return [Time] the {Time} representation of the current value
|
|
49
|
+
def to_time
|
|
50
|
+
Time.at val
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/ruby_smb/field.rb
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
module RubySMB
|
|
2
2
|
module Field
|
|
3
3
|
require 'ruby_smb/field/file_time'
|
|
4
|
+
require 'ruby_smb/field/utime'
|
|
4
5
|
require 'ruby_smb/field/stringz16'
|
|
5
6
|
require 'ruby_smb/field/nt_status'
|
|
7
|
+
require 'ruby_smb/field/extended_attribute_flag'
|
|
8
|
+
require 'ruby_smb/field/smb_fea'
|
|
9
|
+
require 'ruby_smb/field/smb_fea_list'
|
|
10
|
+
require 'ruby_smb/field/security_descriptor'
|
|
11
|
+
require 'ruby_smb/field/file_full_ea_info'
|
|
12
|
+
require 'ruby_smb/field/ea_info_array'
|
|
6
13
|
end
|
|
7
14
|
end
|
|
@@ -35,15 +35,19 @@ module RubySMB
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def status_code
|
|
38
|
+
value = -1
|
|
38
39
|
smb_version = packet_smb_version
|
|
39
40
|
case smb_version
|
|
40
41
|
when 'SMB1'
|
|
41
|
-
|
|
42
|
+
value = self.smb_header.nt_status.value
|
|
42
43
|
when 'SMB2'
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
value = self.smb2_header.nt_status.value
|
|
45
|
+
end
|
|
46
|
+
status_code = WindowsError::NTStatus.find_by_retval(value).first
|
|
47
|
+
if status_code.nil?
|
|
48
|
+
status_code = WindowsError::ErrorCode.new("0x#{value.to_s(16)}", value, "Unknown 0x#{value.to_s(16)}")
|
|
46
49
|
end
|
|
50
|
+
status_code
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
private
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
# Contains constants for the various Impersonation levels as defined in
|
|
3
|
+
# [2.2.4.64.1 Request](https://msdn.microsoft.com/en-us/library/ee442175.aspx)
|
|
4
|
+
# See also [Impersonation Levels](https://msdn.microsoft.com/en-us/library/ms686632(v=vs.85).aspx)
|
|
5
|
+
module ImpersonationLevels
|
|
6
|
+
# The client is anonymous to the server. The server process can impersonate the client, but the impersonation
|
|
7
|
+
# token does not contain any information about the client. This level is only supported over the local
|
|
8
|
+
# interprocess communication transport. All other transports silently promote this level to identify.
|
|
9
|
+
SEC_ANONYMOUS = 0x00000000
|
|
10
|
+
|
|
11
|
+
# The system default level. The server can obtain the client's identity,
|
|
12
|
+
# and the server can impersonate the client to do ACL checks.
|
|
13
|
+
SEC_IDENTIFY = 0x00000001
|
|
14
|
+
|
|
15
|
+
# The server can impersonate the client's security context while acting on behalf of the client.
|
|
16
|
+
# The server can access local resources as the client. If the server is local, it can access
|
|
17
|
+
# network resources as the client. If the server is remote, it can access only resources
|
|
18
|
+
# that are on the same computer as the server.
|
|
19
|
+
SEC_IMPERSONATE = 0x00000002
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module SMB1
|
|
3
|
+
module BitField
|
|
4
|
+
|
|
5
|
+
# Represents a CreateOptions BitField as used by both the NT_CREATE_ANDX
|
|
6
|
+
# and the NT_TRANSACT_CREATE Requests. The definition for this field can be found at
|
|
7
|
+
# [2.2.4.64.1 Request](https://msdn.microsoft.com/en-us/library/ee442175.aspx)
|
|
8
|
+
class CreateOptions < BinData::Record
|
|
9
|
+
endian :little
|
|
10
|
+
bit1 :create_tree_connection, label: 'Create Tree Connection'
|
|
11
|
+
bit1 :non_directory_file, label: 'Non-Directory File'
|
|
12
|
+
bit1 :synchronous_io_nonalert, label: 'Synchronous IO Nonalert'
|
|
13
|
+
bit1 :synchronous_io_alert, label: 'Synchronous IO Alert'
|
|
14
|
+
bit1 :no_intermediate_buffer, label: 'No Intermediate Buffering'
|
|
15
|
+
bit1 :sequential_only, label: 'Sequential Only'
|
|
16
|
+
bit1 :write_through, label: 'Write Through'
|
|
17
|
+
bit1 :directory_file, label: 'Directory File'
|
|
18
|
+
# Byte Boundary
|
|
19
|
+
bit1 :no_compression, label: 'No Compression'
|
|
20
|
+
bit1 :open_for_backup_intent, label: 'Open For Backup Intent'
|
|
21
|
+
bit1 :open_by_file_id, label: 'Open by File ID'
|
|
22
|
+
bit1 :delete_on_close, label: 'Delete on Close'
|
|
23
|
+
bit1 :random_access, label: 'Random Access'
|
|
24
|
+
bit1 :open_for_recovery, label: 'Open for Recovery'
|
|
25
|
+
bit1 :no_ea_knowledge, label: 'No EA Knowledge'
|
|
26
|
+
bit1 :complete_if_oplocked, label: 'Complete if OPLocked'
|
|
27
|
+
# Byte Boundary
|
|
28
|
+
bit1 :open_for_free_space_query, label: 'Open for Free Space Query'
|
|
29
|
+
bit1 :open_no_recall, label: 'Open No Recall'
|
|
30
|
+
bit1 :reserved2, label: 'Reserved Space'
|
|
31
|
+
bit1 :reserve_opfilter, label: 'Reserve OPFilter'
|
|
32
|
+
bit4 :reserved, label: 'Reserved Space'
|
|
33
|
+
# Byte Boundary
|
|
34
|
+
bit8
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -7,7 +7,7 @@ module RubySMB
|
|
|
7
7
|
endian :little
|
|
8
8
|
bit1 :read_attr, label: 'Read Attributes'
|
|
9
9
|
bit1 :delete_child, label: 'Delete Child'
|
|
10
|
-
bit1 :execute, label: '
|
|
10
|
+
bit1 :execute, label: 'Execute'
|
|
11
11
|
bit1 :write_ea, label: 'Write Extended Attributes'
|
|
12
12
|
bit1 :read_ea, label: 'Read Extended Attributes'
|
|
13
13
|
bit1 :append_data, label: 'Append Data'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module SMB1
|
|
3
|
+
module BitField
|
|
4
|
+
# The AccessMode bit-field for an SMB1 Open2 Request as defined in
|
|
5
|
+
# [2.2.6.1.1 Request](https://msdn.microsoft.com/en-us/library/ee441733.aspx)
|
|
6
|
+
class Open2AccessMode< BinData::Record
|
|
7
|
+
endian :little
|
|
8
|
+
bit1 :reserved2, label: 'Reserved Space'
|
|
9
|
+
bit3 :sharing_mode, label: 'Sharing Mode'
|
|
10
|
+
bit1 :reserved, label: 'Reserved Space'
|
|
11
|
+
bit3 :access_mode, label: 'Access Mode'
|
|
12
|
+
# byte boundary
|
|
13
|
+
bit1 :reserved5, label: 'Reserved Space'
|
|
14
|
+
bit1 :writethrough, label: 'Writethrough mode'
|
|
15
|
+
bit1 :reserved4, label: 'Reserved Space'
|
|
16
|
+
bit1 :cache_mode, label: 'Cache Mode'
|
|
17
|
+
bit1 :reserved3, label: 'Reserved Space'
|
|
18
|
+
bit3 :reference_locality, label: 'Reference'
|
|
19
|
+
|
|
20
|
+
# Sets the #access_mode based on more human readableinput.
|
|
21
|
+
# Takes the symbols :r, :w, :rw, and :x to set Read, Write,
|
|
22
|
+
# ReadWrite, and Execute respectively.
|
|
23
|
+
#
|
|
24
|
+
# @param mode [Symbol] the access mode to set
|
|
25
|
+
def set_access_mode(mode=:r)
|
|
26
|
+
modes = [:r, :w, :rw, :x]
|
|
27
|
+
raise ArgumentError, "Mode must be one of #{modes.to_s}" unless modes.include? mode
|
|
28
|
+
case mode
|
|
29
|
+
when :r
|
|
30
|
+
self.access_mode = 0
|
|
31
|
+
when :w
|
|
32
|
+
self.access_mode = 1
|
|
33
|
+
when :rw
|
|
34
|
+
self.access_mode = 2
|
|
35
|
+
when :x
|
|
36
|
+
self.access_mode = 3
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module SMB1
|
|
3
|
+
module BitField
|
|
4
|
+
# The Flags bit-field for an SMB1 Open2 Request as defined in
|
|
5
|
+
# [2.2.6.1.1 Request](https://msdn.microsoft.com/en-us/library/ee441733.aspx)
|
|
6
|
+
class Open2Flags < BinData::Record
|
|
7
|
+
endian :little
|
|
8
|
+
bit4 :reserved, label: 'Reserved Space'
|
|
9
|
+
bit1 :req_easize, label: 'Request EA Size', initial_value: 1
|
|
10
|
+
bit1 :req_opbatch, label: 'Request Batch OpLock', initial_value: 0
|
|
11
|
+
bit1 :req_oplock, label: 'Request OpLock', initial_value: 0
|
|
12
|
+
bit1 :req_attrib, label: 'Request Attributes', initial_value: 1
|
|
13
|
+
# Byte boundary
|
|
14
|
+
bit8 :reserved2, label: 'Reserved Space'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module SMB1
|
|
3
|
+
module BitField
|
|
4
|
+
# The OpenMode bit-field for an SMB1 Open2 Request as defined in
|
|
5
|
+
# [2.2.6.1.1 Request](https://msdn.microsoft.com/en-us/library/ee441733.aspx)
|
|
6
|
+
class Open2OpenMode< BinData::Record
|
|
7
|
+
endian :little
|
|
8
|
+
bit3 :reserved2, label: 'Reserved Space'
|
|
9
|
+
bit1 :create_file, label: 'Create File Options'
|
|
10
|
+
bit2 :reserved, label: 'Reserved Space'
|
|
11
|
+
bit2 :file_exists_opts, label: 'File Exists Options'
|
|
12
|
+
# byte boundary
|
|
13
|
+
bit8 :reserved5, label: 'Reserved Space'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module SMB1
|
|
3
|
+
module BitField
|
|
4
|
+
|
|
5
|
+
# Represents a ShareAccess Bit-Field as defined in
|
|
6
|
+
# [2.2.4.64.1 Request](https://msdn.microsoft.com/en-us/library/ee442175.aspx)
|
|
7
|
+
class ShareAccess < BinData::Record
|
|
8
|
+
endian :little
|
|
9
|
+
bit5 :reserved, label: 'Reserved Space'
|
|
10
|
+
bit1 :share_delete, label: 'Share Delete Access'
|
|
11
|
+
bit1 :share_write, label: 'Share Write Access'
|
|
12
|
+
bit1 :share_read, label: 'Share Read Access'
|
|
13
|
+
# Byte Boundary
|
|
14
|
+
bit8 :reserved2, label: 'Reserved Space'
|
|
15
|
+
bit8 :reserved3, label: 'Reserved Space'
|
|
16
|
+
bit8 :reserved4, label: 'Reserved Space'
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module SMB1
|
|
3
|
+
module BitField
|
|
4
|
+
# The bit-field for SMB1 Extended File Attributes as defined in
|
|
5
|
+
# [2.2.1.2.3 SMB_EXT_FILE_ATTR](https://msdn.microsoft.com/en-us/library/ee878573.aspx)
|
|
6
|
+
class SmbExtFileAttributes < BinData::Record
|
|
7
|
+
endian :little
|
|
8
|
+
bit1 :normal, label: 'Normal File'
|
|
9
|
+
bit1 :reserved, label: 'Reserved Space'
|
|
10
|
+
bit1 :archive, label: 'Archive'
|
|
11
|
+
bit1 :directory, label: 'Directory'
|
|
12
|
+
bit1 :reserved2, label: 'Reserved Space'
|
|
13
|
+
bit1 :system, label: 'System File'
|
|
14
|
+
bit1 :hidden, label: 'Hidden File'
|
|
15
|
+
bit1 :read_only, label: 'Read Only'
|
|
16
|
+
# Byte boundary
|
|
17
|
+
bit4 :reserved3, label: 'Reserved Space'
|
|
18
|
+
bit1 :compressed, label: 'Compressed File'
|
|
19
|
+
bit2 :reserved4, label: 'Reserved Space'
|
|
20
|
+
bit1 :temporary, label: 'Temporary File'
|
|
21
|
+
# Byte Boundary
|
|
22
|
+
bit8 :reserved5, label: 'Reserved Space'
|
|
23
|
+
# Byte Boundary
|
|
24
|
+
bit1 :write_through, label: 'Write through'
|
|
25
|
+
bit1 :reserved6, label: 'Reserved Space'
|
|
26
|
+
bit1 :no_buffering, label: 'Do not Buffer'
|
|
27
|
+
bit1 :random_access, label: 'Random Access'
|
|
28
|
+
bit1 :sequential_scan, label: 'Sequential Access'
|
|
29
|
+
bit1 :delete_on_close, label: 'Delete on close'
|
|
30
|
+
bit1 :backup_semantics, label: 'Backup Semantics'
|
|
31
|
+
bit1 :posix_semantics, label: 'POSIX Semantics'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|