ruby_smb 0.0.8
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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.gitignore +21 -0
- data/.rspec +3 -0
- data/.simplecov +42 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/CONTRIBUTING.md +119 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +18 -0
- data/README.md +64 -0
- data/Rakefile +22 -0
- data/examples/authenticate.rb +30 -0
- data/examples/negotiate.rb +25 -0
- data/lib/ruby_smb/client/authentication.rb +236 -0
- data/lib/ruby_smb/client/negotiation.rb +126 -0
- data/lib/ruby_smb/client/signing.rb +48 -0
- data/lib/ruby_smb/client.rb +164 -0
- data/lib/ruby_smb/dispatcher/base.rb +18 -0
- data/lib/ruby_smb/dispatcher/socket.rb +53 -0
- data/lib/ruby_smb/dispatcher.rb +4 -0
- data/lib/ruby_smb/error.rb +17 -0
- data/lib/ruby_smb/field/file_time.rb +62 -0
- data/lib/ruby_smb/field/nt_status.rb +16 -0
- data/lib/ruby_smb/field/stringz16.rb +55 -0
- data/lib/ruby_smb/field.rb +7 -0
- data/lib/ruby_smb/generic_packet.rb +179 -0
- data/lib/ruby_smb/gss.rb +109 -0
- data/lib/ruby_smb/smb1/andx_block.rb +13 -0
- data/lib/ruby_smb/smb1/bit_field/capabilities.rb +39 -0
- data/lib/ruby_smb/smb1/bit_field/header_flags.rb +19 -0
- data/lib/ruby_smb/smb1/bit_field/header_flags2.rb +27 -0
- data/lib/ruby_smb/smb1/bit_field/security_mode.rb +16 -0
- data/lib/ruby_smb/smb1/bit_field.rb +10 -0
- data/lib/ruby_smb/smb1/commands.rb +9 -0
- data/lib/ruby_smb/smb1/data_block.rb +42 -0
- data/lib/ruby_smb/smb1/dialect.rb +11 -0
- data/lib/ruby_smb/smb1/packet/error_packet.rb +14 -0
- data/lib/ruby_smb/smb1/packet/negotiate_request.rb +52 -0
- data/lib/ruby_smb/smb1/packet/negotiate_response.rb +46 -0
- data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +47 -0
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +71 -0
- data/lib/ruby_smb/smb1/packet/session_setup_response.rb +48 -0
- data/lib/ruby_smb/smb1/packet.rb +12 -0
- data/lib/ruby_smb/smb1/parameter_block.rb +42 -0
- data/lib/ruby_smb/smb1/smb_header.rb +21 -0
- data/lib/ruby_smb/smb1.rb +16 -0
- data/lib/ruby_smb/smb2/bit_field/session_flags.rb +17 -0
- data/lib/ruby_smb/smb2/bit_field/smb2_capabailities.rb +23 -0
- data/lib/ruby_smb/smb2/bit_field/smb2_header_flags.rb +23 -0
- data/lib/ruby_smb/smb2/bit_field/smb2_security_mode.rb +15 -0
- data/lib/ruby_smb/smb2/bit_field/smb2_security_mode_single.rb +14 -0
- data/lib/ruby_smb/smb2/bit_field.rb +11 -0
- data/lib/ruby_smb/smb2/commands.rb +25 -0
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +50 -0
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +33 -0
- data/lib/ruby_smb/smb2/packet/session_setup_request.rb +53 -0
- data/lib/ruby_smb/smb2/packet/session_setup_response.rb +38 -0
- data/lib/ruby_smb/smb2/packet.rb +10 -0
- data/lib/ruby_smb/smb2/smb2_header.rb +22 -0
- data/lib/ruby_smb/smb2.rb +12 -0
- data/lib/ruby_smb/version.rb +3 -0
- data/lib/ruby_smb.rb +22 -0
- data/ruby_smb.gemspec +38 -0
- data/spec/lib/ruby_smb/client_spec.rb +638 -0
- data/spec/lib/ruby_smb/dispatcher/dispatcher_base_spec.rb +22 -0
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +60 -0
- data/spec/lib/ruby_smb/field/file_time_spec.rb +59 -0
- data/spec/lib/ruby_smb/field/nt_status_spec.rb +19 -0
- data/spec/lib/ruby_smb/field/stringz16_spec.rb +50 -0
- data/spec/lib/ruby_smb/generic_packet_spec.rb +58 -0
- data/spec/lib/ruby_smb/smb1/andx_block_spec.rb +41 -0
- data/spec/lib/ruby_smb/smb1/bit_field/capabilities_spec.rb +245 -0
- data/spec/lib/ruby_smb/smb1/bit_field/header_flags2_spec.rb +146 -0
- data/spec/lib/ruby_smb/smb1/bit_field/header_flags_spec.rb +102 -0
- data/spec/lib/ruby_smb/smb1/bit_field/security_mode_spec.rb +44 -0
- data/spec/lib/ruby_smb/smb1/data_block_spec.rb +26 -0
- data/spec/lib/ruby_smb/smb1/dialect_spec.rb +26 -0
- data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +39 -0
- data/spec/lib/ruby_smb/smb1/packet/negotiate_request_spec.rb +77 -0
- data/spec/lib/ruby_smb/smb1/packet/negotiate_response_extended_spec.rb +149 -0
- data/spec/lib/ruby_smb/smb1/packet/negotiate_response_spec.rb +150 -0
- data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +100 -0
- data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +72 -0
- data/spec/lib/ruby_smb/smb1/parameter_block_spec.rb +26 -0
- data/spec/lib/ruby_smb/smb1/smb_header_spec.rb +96 -0
- data/spec/lib/ruby_smb/smb2/bit_field/header_flags_spec.rb +81 -0
- data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +28 -0
- data/spec/lib/ruby_smb/smb2/bit_field/smb2_capabilities_spec.rb +72 -0
- data/spec/lib/ruby_smb/smb2/bit_field/smb_secruity_mode_spec.rb +22 -0
- data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +122 -0
- data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +147 -0
- data/spec/lib/ruby_smb/smb2/packet/session_setup_request_spec.rb +79 -0
- data/spec/lib/ruby_smb/smb2/packet/session_setup_response_spec.rb +54 -0
- data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +127 -0
- data/spec/lib/ruby_smb_spec.rb +2 -0
- data/spec/spec_helper.rb +100 -0
- data/spec/support/mock_socket_dispatcher.rb +8 -0
- data/spec/support/shared/examples/bit_field_single_flag.rb +14 -0
- data.tar.gz.sig +0 -0
- metadata +384 -0
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
RSpec.describe RubySMB::Dispatcher::Socket do
|
|
2
|
+
let(:fake_tcp_socket) { StringIO.new('deadbeef') }
|
|
3
|
+
|
|
4
|
+
subject(:smb_socket) { described_class.new(fake_tcp_socket) }
|
|
5
|
+
let(:negotiate_response) { RubySMB::SMB2::Packet::NegotiateResponse.new }
|
|
6
|
+
let(:nbss) { smb_socket.nbss(negotiate_response) }
|
|
7
|
+
let(:response_packet) { nbss + negotiate_response.to_binary_s }
|
|
8
|
+
|
|
9
|
+
# Don't try to actually select on our StringIO fake socket
|
|
10
|
+
before(:each) do
|
|
11
|
+
allow(IO).to receive(:select).and_return(nil)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe '#connect' do
|
|
15
|
+
it 'should support setting a custom socket object' do
|
|
16
|
+
socket = described_class.connect('172.16.22.165', socket: fake_tcp_socket)
|
|
17
|
+
expect(socket.tcp_socket).to eq(fake_tcp_socket)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should default to setting up a TCPSocket' do
|
|
21
|
+
host = '172.16.22.165'
|
|
22
|
+
port = 445
|
|
23
|
+
expect(TCPSocket).to receive(:new).with(host, port)
|
|
24
|
+
described_class.connect(host)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe '#recv_packet' do
|
|
29
|
+
let(:blank_socket) { StringIO.new('') }
|
|
30
|
+
let(:response_socket) { StringIO.new(response_packet) }
|
|
31
|
+
|
|
32
|
+
describe 'when reading from the socket results in a nil value' do
|
|
33
|
+
it 'should raise Error::NetBiosSessionService' do
|
|
34
|
+
smb_socket.tcp_socket = blank_socket
|
|
35
|
+
expect { smb_socket.recv_packet }.to raise_error(::RubySMB::Error::NetBiosSessionService)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe 'when reading an SMB Response packet' do
|
|
40
|
+
it 'reads a number of bytes defined in the nbss header' do
|
|
41
|
+
smb_socket.tcp_socket = response_socket
|
|
42
|
+
expect(response_socket).to receive(:read).with(4).and_call_original
|
|
43
|
+
expect(response_socket).to receive(:read).with(negotiate_response.do_num_bytes).and_call_original
|
|
44
|
+
smb_socket.recv_packet
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe '#send_packet' do
|
|
50
|
+
it 'calls nbss to create the nbss header for the packet' do
|
|
51
|
+
expect(smb_socket).to receive(:nbss).with(negotiate_response).and_return(nbss)
|
|
52
|
+
smb_socket.send_packet(negotiate_response)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'writes the packet to the socket' do
|
|
56
|
+
expect(fake_tcp_socket).to receive(:write).with(response_packet).and_call_original
|
|
57
|
+
smb_socket.send_packet(negotiate_response)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
RSpec.describe RubySMB::Field::FileTime do
|
|
2
|
+
subject(:file_time) { described_class.read(binary_filetime) }
|
|
3
|
+
|
|
4
|
+
let(:binary_filetime) { "\x36\x32\xe8\xe0\xd2\xe4\xd0\x01" }
|
|
5
|
+
let(:int_filetime) { binary_filetime.unpack('Q<').first }
|
|
6
|
+
let(:str_filetime) { '2015-09-01T11:25:56-05:00' }
|
|
7
|
+
let(:time_filetime) { Time.parse str_filetime }
|
|
8
|
+
let(:datetime_filetime) { time_filetime.to_datetime }
|
|
9
|
+
|
|
10
|
+
it { is_expected.to respond_to :val }
|
|
11
|
+
it { is_expected.to respond_to :get }
|
|
12
|
+
it { is_expected.to respond_to :set }
|
|
13
|
+
it { is_expected.to respond_to :to_time }
|
|
14
|
+
it { is_expected.to respond_to :to_datetime }
|
|
15
|
+
|
|
16
|
+
describe '#val' do
|
|
17
|
+
it 'should b an Unsigned 64-bit Integer' do
|
|
18
|
+
expect(file_time.val).to be_a BinData::Uint64le
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe '#get' do
|
|
23
|
+
it 'returns the expected integer value' do
|
|
24
|
+
expect(file_time.val).to eq int_filetime
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe '#to_time' do
|
|
29
|
+
it 'returns a Time object representing the correct time' do
|
|
30
|
+
expect(file_time.to_time).to eq time_filetime
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe '#to_datetime' do
|
|
35
|
+
it 'returns a DateTime object representing the correct time' do
|
|
36
|
+
expect(file_time.to_datetime).to eq datetime_filetime
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe '#set' do
|
|
41
|
+
subject(:empty_filetime) { described_class.new }
|
|
42
|
+
it 'will take a Time object correctly but lose Nanoseconds' do
|
|
43
|
+
empty_filetime.set time_filetime
|
|
44
|
+
val = empty_filetime.get
|
|
45
|
+
expect(val / 10_000_000).to eq (int_filetime / 10_000_000)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'will take a DateTime object correctly but lose Nanoseconds' do
|
|
49
|
+
empty_filetime.set datetime_filetime
|
|
50
|
+
val = empty_filetime.get
|
|
51
|
+
expect(val / 10_000_000).to eq (int_filetime / 10_000_000)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'will accept a raw integer value and set it' do
|
|
55
|
+
empty_filetime.set int_filetime
|
|
56
|
+
expect(empty_filetime.get).to eq int_filetime
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
RSpec.describe RubySMB::Field::NtStatus do
|
|
2
|
+
subject(:nt_status) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :to_nt_status }
|
|
5
|
+
|
|
6
|
+
it 'is a Unsigned 32-bit little endian integer' do
|
|
7
|
+
expect(nt_status).to be_a BinData::Uint32le
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe '#to_nt_status' do
|
|
11
|
+
it 'should return a WindowsError::ErrorCode' do
|
|
12
|
+
expect(nt_status.to_nt_status).to be_a WindowsError::ErrorCode
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'should return the correct ErrorCode' do
|
|
16
|
+
expect(nt_status.to_nt_status).to eq WindowsError::NTStatus::STATUS_SUCCESS
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe RubySMB::Field::Stringz16 do
|
|
4
|
+
subject(:stringz16) { described_class.new }
|
|
5
|
+
|
|
6
|
+
it 'starts as an empty string' do
|
|
7
|
+
expect(stringz16).to eq ""
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
context 'with a value already set' do
|
|
11
|
+
let(:abcd) { described_class.new("ABCD") }
|
|
12
|
+
|
|
13
|
+
it 'should be UTF-16le' do
|
|
14
|
+
expect(abcd).to eq "ABCD".encode("utf-16le")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should include the NULL terminator on binary output' do
|
|
18
|
+
expect(abcd.to_binary_s).to eq "A\x00B\x00C\x00D\x00\x00\x00"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context 'with a null terminator in the middle' do
|
|
23
|
+
let(:null_terminator) { described_class.new("ABCD\x00EFG") }
|
|
24
|
+
|
|
25
|
+
it 'drops everything after the null terminator' do
|
|
26
|
+
expect(null_terminator).to eq "ABCD".encode("utf-16le")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'when reading data in' do
|
|
31
|
+
|
|
32
|
+
it 'stops at the first double null byte' do
|
|
33
|
+
io = StringIO.new("A\x00B\x00C\x00D\x00\x00\x00E\x00F\x00")
|
|
34
|
+
stringz16.read(io)
|
|
35
|
+
expect(stringz16.to_binary_s).to eq "A\x00B\x00C\x00D\x00\x00\x00"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'handles a zero length string' do
|
|
39
|
+
io = StringIO.new("\x00\x00A\x00")
|
|
40
|
+
stringz16.read(io)
|
|
41
|
+
expect(stringz16).to eq ""
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'fails if no null terminator is found' do
|
|
45
|
+
io = StringIO.new("A\x00B\x00C\x00D\x00")
|
|
46
|
+
expect{ stringz16.read(io) }.to raise_error(EOFError)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe RubySMB::GenericPacket do
|
|
4
|
+
|
|
5
|
+
class TestPacket < RubySMB::GenericPacket
|
|
6
|
+
endian :little
|
|
7
|
+
uint8 :first_value, initial_value: 0x01
|
|
8
|
+
uint16 :second_value, initial_value: 0x02
|
|
9
|
+
array :array_value, type: :dialect, read_until: :eof
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class ParentTestPacket < RubySMB::GenericPacket
|
|
13
|
+
endian :little
|
|
14
|
+
uint8 :header
|
|
15
|
+
test_packet :test_packet
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
subject(:test_packet) { TestPacket.new(first_value: 16, second_value: 4056, array_value: [RubySMB::SMB1::Dialect.new(dialect_string: 'test')]) }
|
|
19
|
+
let(:parent_packet) { ParentTestPacket.new }
|
|
20
|
+
|
|
21
|
+
describe '#describe class method' do
|
|
22
|
+
it 'outputs a string representing the structure of the packet' do
|
|
23
|
+
str = "\nFirst_value (Uint8) \n"+
|
|
24
|
+
"Second_value (Uint16le) \n"+
|
|
25
|
+
"Array_value (Array) "
|
|
26
|
+
expect(TestPacket.describe).to eq str
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'handles nested record structures as well' do
|
|
30
|
+
str = "\nHeader (Uint8) \n"+
|
|
31
|
+
"TEST_PACKET \n"+
|
|
32
|
+
"\tFirst_value (Uint8) \n"+
|
|
33
|
+
"\tSecond_value (Uint16le) \n"+
|
|
34
|
+
"\tArray_value (Array) "
|
|
35
|
+
expect(ParentTestPacket.describe).to eq str
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe '#display' do
|
|
40
|
+
it 'shows the actual contents of the packet fields' do
|
|
41
|
+
str = "\nFIRST_VALUE 16\n" +
|
|
42
|
+
"SECOND_VALUE 4056\n" +
|
|
43
|
+
"ARRAY_VALUE\n" +
|
|
44
|
+
"\tBuffer Format ID 2\n" +
|
|
45
|
+
"\tDialect Name test"
|
|
46
|
+
expect(test_packet.display).to eq str
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'handles nested record structures as well' do
|
|
50
|
+
str = "\nHEADER 0\n" +
|
|
51
|
+
"TEST_PACKET\n" +
|
|
52
|
+
"\tFirst_value 1\n" +
|
|
53
|
+
"\tSecond_value 2\n" +
|
|
54
|
+
"\tARRAY_VALUE"
|
|
55
|
+
expect(parent_packet.display).to eq str
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::AndXBlock do
|
|
2
|
+
subject(:andx_block) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :andx_command }
|
|
5
|
+
it { is_expected.to respond_to :andx_reserved }
|
|
6
|
+
it { is_expected.to respond_to :andx_offset }
|
|
7
|
+
|
|
8
|
+
it 'is little endian' do
|
|
9
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe 'andx_command' do
|
|
13
|
+
it 'should be a 8-bit field per the SMB spec' do
|
|
14
|
+
expect(andx_block.andx_command).to be_a BinData::Bit8
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should be hardcoded to SMB_COM_NO_ANDX_COMMAND by default per the SMB spec' do
|
|
18
|
+
expect(andx_block.andx_command).to eq RubySMB::SMB1::Commands::SMB_COM_NO_ANDX_COMMAND
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe 'andx_reserved' do
|
|
23
|
+
it 'should be a 8-bit field per the SMB spec' do
|
|
24
|
+
expect(andx_block.andx_reserved).to be_a BinData::Bit8
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'should be hardcoded to 0 by default per the SMB spec' do
|
|
28
|
+
expect(andx_block.andx_reserved).to eq 0
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe 'andx_offset' do
|
|
33
|
+
it 'should be a 16-bit field per the SMB spec' do
|
|
34
|
+
expect(andx_block.andx_offset).to be_a BinData::Bit16
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should be hardcoded to 0 by default per the SMB spec' do
|
|
38
|
+
expect(andx_block.andx_offset).to eq 0
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::BitField::Capabilities do
|
|
2
|
+
subject(:capabilities) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :level_2_oplocks }
|
|
5
|
+
it { is_expected.to respond_to :nt_status }
|
|
6
|
+
it { is_expected.to respond_to :rpc_remote_apis }
|
|
7
|
+
it { is_expected.to respond_to :nt_smbs }
|
|
8
|
+
it { is_expected.to respond_to :large_files }
|
|
9
|
+
it { is_expected.to respond_to :unicode }
|
|
10
|
+
it { is_expected.to respond_to :mpx_mode }
|
|
11
|
+
it { is_expected.to respond_to :raw_mode }
|
|
12
|
+
it { is_expected.to respond_to :large_writex }
|
|
13
|
+
it { is_expected.to respond_to :large_readx }
|
|
14
|
+
it { is_expected.to respond_to :info_level_passthru }
|
|
15
|
+
it { is_expected.to respond_to :dfs }
|
|
16
|
+
it { is_expected.to respond_to :reserved1 }
|
|
17
|
+
it { is_expected.to respond_to :bulk_transfer }
|
|
18
|
+
it { is_expected.to respond_to :nt_find }
|
|
19
|
+
it { is_expected.to respond_to :lock_and_read }
|
|
20
|
+
it { is_expected.to respond_to :unix }
|
|
21
|
+
it { is_expected.to respond_to :reserved2 }
|
|
22
|
+
it { is_expected.to respond_to :lwio }
|
|
23
|
+
it { is_expected.to respond_to :extended_security }
|
|
24
|
+
it { is_expected.to respond_to :reserved3 }
|
|
25
|
+
it { is_expected.to respond_to :dynamic_reauth }
|
|
26
|
+
it { is_expected.to respond_to :reserved4 }
|
|
27
|
+
it { is_expected.to respond_to :compressed_data }
|
|
28
|
+
it { is_expected.to respond_to :reserved5 }
|
|
29
|
+
|
|
30
|
+
it 'is little endian' do
|
|
31
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe '#level_2_oplocks' do
|
|
35
|
+
it 'is a 1-bit flag' do
|
|
36
|
+
expect(capabilities.level_2_oplocks).to be_a BinData::Bit1
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it_behaves_like 'bit field with one flag set', :level_2_oplocks, 'V', 0x00000080
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe '#nt_status' do
|
|
43
|
+
it 'is a 1-bit flag' do
|
|
44
|
+
expect(capabilities.nt_status).to be_a BinData::Bit1
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it_behaves_like 'bit field with one flag set', :nt_status, 'V', 0x00000040
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe '#rpc_remote_apis' do
|
|
51
|
+
it 'is a 1-bit flag' do
|
|
52
|
+
expect(capabilities.rpc_remote_apis).to be_a BinData::Bit1
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it_behaves_like 'bit field with one flag set', :rpc_remote_apis, 'V', 0x00000020
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe '#nt_smbs' do
|
|
59
|
+
it 'is a 1-bit flag' do
|
|
60
|
+
expect(capabilities.nt_smbs).to be_a BinData::Bit1
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it_behaves_like 'bit field with one flag set', :nt_smbs, 'V', 0x00000010
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe '#large_files' do
|
|
67
|
+
it 'is a 1-bit flag' do
|
|
68
|
+
expect(capabilities.large_files).to be_a BinData::Bit1
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it_behaves_like 'bit field with one flag set', :large_files, 'V', 0x00000008
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe '#unicode' do
|
|
75
|
+
it 'is a 1-bit flag' do
|
|
76
|
+
expect(capabilities.unicode).to be_a BinData::Bit1
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it_behaves_like 'bit field with one flag set', :unicode, 'V', 0x00000004
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe '#mpx_mode' do
|
|
83
|
+
it 'is a 1-bit flag' do
|
|
84
|
+
expect(capabilities.mpx_mode).to be_a BinData::Bit1
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it_behaves_like 'bit field with one flag set', :mpx_mode, 'V', 0x00000002
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe '#raw_mode' do
|
|
91
|
+
it 'is a 1-bit flag' do
|
|
92
|
+
expect(capabilities.raw_mode).to be_a BinData::Bit1
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it_behaves_like 'bit field with one flag set', :raw_mode, 'V', 0x00000001
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe '#large_writex' do
|
|
99
|
+
it 'is a 1-bit flag' do
|
|
100
|
+
expect(capabilities.large_writex).to be_a BinData::Bit1
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it_behaves_like 'bit field with one flag set', :large_writex, 'V', 0x00008000
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe '#large_readx' do
|
|
107
|
+
it 'is a 1-bit flag' do
|
|
108
|
+
expect(capabilities.large_readx).to be_a BinData::Bit1
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it_behaves_like 'bit field with one flag set', :large_readx, 'V', 0x00004000
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
describe '#info_level_passthru' do
|
|
115
|
+
it 'is a 1-bit flag' do
|
|
116
|
+
expect(capabilities.info_level_passthru).to be_a BinData::Bit1
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it_behaves_like 'bit field with one flag set', :info_level_passthru, 'V', 0x00002000
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
describe '#dfs' do
|
|
123
|
+
it 'is a 1-bit flag' do
|
|
124
|
+
expect(capabilities.dfs).to be_a BinData::Bit1
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it_behaves_like 'bit field with one flag set', :dfs, 'V', 0x00001000
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe '#reserved1' do
|
|
131
|
+
it 'is a 1-bit flag' do
|
|
132
|
+
expect(capabilities.reserved1).to be_a BinData::Bit1
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it 'should have a default value of 0' do
|
|
136
|
+
expect(capabilities.reserved1).to eq 0
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
describe '#bulk_transfer' do
|
|
141
|
+
it 'is a 1-bit flag' do
|
|
142
|
+
expect(capabilities.bulk_transfer).to be_a BinData::Bit1
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'should have a default value of 0' do
|
|
146
|
+
expect(capabilities.bulk_transfer).to eq 0
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
describe '#nt_find' do
|
|
151
|
+
it 'is a 1-bit flag' do
|
|
152
|
+
expect(capabilities.nt_find).to be_a BinData::Bit1
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it_behaves_like 'bit field with one flag set', :nt_find, 'V', 0x00000200
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
describe '#lock_and_read' do
|
|
159
|
+
it 'is a 1-bit flag' do
|
|
160
|
+
expect(capabilities.lock_and_read).to be_a BinData::Bit1
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it_behaves_like 'bit field with one flag set', :lock_and_read, 'V', 0x00000100
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
describe '#unix' do
|
|
167
|
+
it 'is a 1-bit flag' do
|
|
168
|
+
expect(capabilities.unix).to be_a BinData::Bit1
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it_behaves_like 'bit field with one flag set', :unix, 'V', 0x00800000
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
describe '#reserved2' do
|
|
175
|
+
it 'is a 6-bit reserved space' do
|
|
176
|
+
expect(capabilities.reserved2).to be_a BinData::Bit6
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it 'should have a default value of 0' do
|
|
180
|
+
expect(capabilities.reserved2).to eq 0
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
describe '#lwio' do
|
|
185
|
+
it 'is a 1-bit flag' do
|
|
186
|
+
expect(capabilities.lwio).to be_a BinData::Bit1
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it_behaves_like 'bit field with one flag set', :lwio, 'V', 0x00010000
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
describe '#extended_security' do
|
|
193
|
+
it 'is a 1-bit flag' do
|
|
194
|
+
expect(capabilities.extended_security).to be_a BinData::Bit1
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it_behaves_like 'bit field with one flag set', :extended_security, 'V', 0x80000000
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
describe '#reserved3' do
|
|
201
|
+
it 'is a 1-bit flag' do
|
|
202
|
+
expect(capabilities.reserved3).to be_a BinData::Bit1
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it 'should have a default value of 0' do
|
|
206
|
+
expect(capabilities.reserved3).to eq 0
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
describe '#dynamic_reauth' do
|
|
211
|
+
it 'is a 1-bit flag' do
|
|
212
|
+
expect(capabilities.dynamic_reauth).to be_a BinData::Bit1
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it_behaves_like 'bit field with one flag set', :dynamic_reauth, 'V', 0x20000000
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
describe '#reserved4' do
|
|
219
|
+
it 'is a 3-bit reserved space' do
|
|
220
|
+
expect(capabilities.reserved4).to be_a BinData::Bit3
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it 'should have a default value of 0' do
|
|
224
|
+
expect(capabilities.reserved1).to eq 0
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
describe '#compressed_data' do
|
|
229
|
+
it 'is a 1-bit flag' do
|
|
230
|
+
expect(capabilities.compressed_data).to be_a BinData::Bit1
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it_behaves_like 'bit field with one flag set', :compressed_data, 'V', 0x02000000
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
describe '#reserved5' do
|
|
237
|
+
it 'is a 1-bit flag' do
|
|
238
|
+
expect(capabilities.reserved5).to be_a BinData::Bit1
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
it 'should have a default value of 0' do
|
|
242
|
+
expect(capabilities.reserved5).to eq 0
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::BitField::HeaderFlags2 do
|
|
2
|
+
subject(:flags2) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :unicode }
|
|
5
|
+
it { is_expected.to respond_to :nt_status }
|
|
6
|
+
it { is_expected.to respond_to :paging_io }
|
|
7
|
+
it { is_expected.to respond_to :dfs }
|
|
8
|
+
it { is_expected.to respond_to :extended_security }
|
|
9
|
+
it { is_expected.to respond_to :reparse_path }
|
|
10
|
+
it { is_expected.to respond_to :reserved1 }
|
|
11
|
+
it { is_expected.to respond_to :is_long_name }
|
|
12
|
+
it { is_expected.to respond_to :reserved2 }
|
|
13
|
+
it { is_expected.to respond_to :signature_required }
|
|
14
|
+
it { is_expected.to respond_to :compressed }
|
|
15
|
+
it { is_expected.to respond_to :security_signature }
|
|
16
|
+
it { is_expected.to respond_to :eas }
|
|
17
|
+
it { is_expected.to respond_to :long_names }
|
|
18
|
+
|
|
19
|
+
it 'is little endian' do
|
|
20
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe 'unicode' do
|
|
24
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
25
|
+
expect(flags2.unicode).to be_a BinData::Bit1
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'should have a default value of 0' do
|
|
29
|
+
expect(flags2.unicode).to eq 0
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it_behaves_like 'bit field with one flag set', :unicode, 'v', 0x8000
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe 'nt_status' do
|
|
36
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
37
|
+
expect(flags2.nt_status).to be_a BinData::Bit1
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'should have a default value of 1' do
|
|
41
|
+
expect(flags2.nt_status).to eq 1
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it_behaves_like 'bit field with one flag set', :nt_status, 'v', 0x4000
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe 'paging_io' do
|
|
48
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
49
|
+
expect(flags2.paging_io).to be_a BinData::Bit1
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it_behaves_like 'bit field with one flag set', :paging_io, 'v', 0x2000
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe 'dfs' do
|
|
56
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
57
|
+
expect(flags2.dfs).to be_a BinData::Bit1
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it_behaves_like 'bit field with one flag set', :dfs, 'v', 0x1000
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe 'extended_security' do
|
|
64
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
65
|
+
expect(flags2.extended_security).to be_a BinData::Bit1
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it_behaves_like 'bit field with one flag set', :extended_security, 'v', 0x0800
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe 'reparse_path' do
|
|
72
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
73
|
+
expect(flags2.reparse_path).to be_a BinData::Bit1
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it_behaves_like 'bit field with one flag set', :reparse_path, 'v', 0x0400
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe 'reserved1' do
|
|
80
|
+
it 'should be a 3-bit field per the SMB spec' do
|
|
81
|
+
expect(flags2.reserved1).to be_a BinData::Bit1
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'should have a default value of 0' do
|
|
85
|
+
expect(flags2.reserved1).to eq 0
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe 'is_long_name' do
|
|
90
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
91
|
+
expect(flags2.is_long_name).to be_a BinData::Bit1
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it_behaves_like 'bit field with one flag set', :is_long_name, 'v', 0x0040
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe 'reserved2' do
|
|
98
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
99
|
+
expect(flags2.reserved2).to be_a BinData::Bit1
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'should have a default value of 0' do
|
|
103
|
+
expect(flags2.reserved2).to eq 0
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
describe 'signature_required' do
|
|
108
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
109
|
+
expect(flags2.signature_required).to be_a BinData::Bit1
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it_behaves_like 'bit field with one flag set', :signature_required, 'v', 0x0010
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
describe 'compressed' do
|
|
116
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
117
|
+
expect(flags2.compressed).to be_a BinData::Bit1
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it_behaves_like 'bit field with one flag set', :compressed, 'v', 0x0008
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
describe 'security_signature' do
|
|
124
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
125
|
+
expect(flags2.security_signature).to be_a BinData::Bit1
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it_behaves_like 'bit field with one flag set', :security_signature, 'v', 0x0004
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
describe 'eas' do
|
|
132
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
133
|
+
expect(flags2.eas).to be_a BinData::Bit1
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it_behaves_like 'bit field with one flag set', :eas, 'v', 0x0002
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe 'long_names' do
|
|
140
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
141
|
+
expect(flags2.long_names).to be_a BinData::Bit1
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it_behaves_like 'bit field with one flag set', :long_names, 'v', 0x0001
|
|
145
|
+
end
|
|
146
|
+
end
|