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,102 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::BitField::HeaderFlags do
|
|
2
|
+
subject(:flags) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :reply }
|
|
5
|
+
it { is_expected.to respond_to :opbatch }
|
|
6
|
+
it { is_expected.to respond_to :oplock }
|
|
7
|
+
it { is_expected.to respond_to :canonicalized_paths }
|
|
8
|
+
it { is_expected.to respond_to :case_insensitive }
|
|
9
|
+
it { is_expected.to respond_to :reserved }
|
|
10
|
+
it { is_expected.to respond_to :buf_avail }
|
|
11
|
+
it { is_expected.to respond_to :lock_and_read_ok }
|
|
12
|
+
|
|
13
|
+
it 'is little endian' do
|
|
14
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe '#reply' do
|
|
18
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
19
|
+
expect(flags.reply).to be_a BinData::Bit1
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it_behaves_like 'bit field with one flag set', :reply, 'C', 0x80
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe '#opbatch' do
|
|
26
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
27
|
+
expect(flags.opbatch).to be_a BinData::Bit1
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'should have a default value of 0' do
|
|
31
|
+
expect(flags.opbatch).to eq 0
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it_behaves_like 'bit field with one flag set', :opbatch, 'C', 0x40
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe '#oplock' do
|
|
38
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
39
|
+
expect(flags.oplock).to be_a BinData::Bit1
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'should have a default value of 0' do
|
|
43
|
+
expect(flags.oplock).to eq 0
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it_behaves_like 'bit field with one flag set', :oplock, 'C', 0x20
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe '#canonicalized_paths' do
|
|
50
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
51
|
+
expect(flags.canonicalized_paths).to be_a BinData::Bit1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'should have a default value of 1' do
|
|
55
|
+
expect(flags.canonicalized_paths).to eq 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it_behaves_like 'bit field with one flag set', :canonicalized_paths, 'C', 0x10
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe '#case_insensitive' do
|
|
62
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
63
|
+
expect(flags.case_insensitive).to be_a BinData::Bit1
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'should have a default value of 1' do
|
|
67
|
+
expect(flags.case_insensitive).to eq 1
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it_behaves_like 'bit field with one flag set', :case_insensitive, 'C', 0x08
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe '#reserved' do
|
|
74
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
75
|
+
expect(flags.reserved).to be_a BinData::Bit1
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'should have a default value of 0' do
|
|
79
|
+
expect(flags.reserved).to eq 0
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe '#buf_avail' do
|
|
84
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
85
|
+
expect(flags.buf_avail).to be_a BinData::Bit1
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'should have a default value of 0' do
|
|
89
|
+
expect(flags.buf_avail).to eq 0
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it_behaves_like 'bit field with one flag set', :buf_avail, 'C', 0x02
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
describe '#lock_and_read_ok' do
|
|
96
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
97
|
+
expect(flags.lock_and_read_ok).to be_a BinData::Bit1
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it_behaves_like 'bit field with one flag set', :lock_and_read_ok, 'C', 0x01
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::BitField::SecurityMode do
|
|
2
|
+
subject(:security_mode) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :user_security }
|
|
5
|
+
it { is_expected.to respond_to :encrypt_passwords }
|
|
6
|
+
it { is_expected.to respond_to :security_signatures_enabled }
|
|
7
|
+
it { is_expected.to respond_to :security_signatures_required }
|
|
8
|
+
|
|
9
|
+
it 'is little endian' do
|
|
10
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe '#user_security' do
|
|
14
|
+
it 'is a 1-bit flag' do
|
|
15
|
+
expect(security_mode.user_security).to be_a BinData::Bit1
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it_behaves_like 'bit field with one flag set', :user_security, 'C', 0x01
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe '#encrypt_passwords' do
|
|
22
|
+
it 'is a 1-bit flag' do
|
|
23
|
+
expect(security_mode.encrypt_passwords).to be_a BinData::Bit1
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it_behaves_like 'bit field with one flag set', :encrypt_passwords, 'C', 0x02
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe '#security_signatures_enabled' do
|
|
30
|
+
it 'is a 1-bit flag' do
|
|
31
|
+
expect(security_mode.security_signatures_enabled).to be_a BinData::Bit1
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it_behaves_like 'bit field with one flag set', :security_signatures_enabled, 'C', 0x04
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe '#security_signatures_required' do
|
|
38
|
+
it 'is a 1-bit flag' do
|
|
39
|
+
expect(security_mode.security_signatures_required).to be_a BinData::Bit1
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it_behaves_like 'bit field with one flag set', :security_signatures_required, 'C', 0x08
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::DataBlock do
|
|
2
|
+
subject(:data_block) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :byte_count }
|
|
5
|
+
|
|
6
|
+
describe 'byte_count' do
|
|
7
|
+
it 'should be a 16-bit field per the SMB spec' do
|
|
8
|
+
expect(data_block.byte_count).to be_a BinData::Uint16le
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should equal the size of the rest of the block in bytes' do
|
|
12
|
+
remaining_size = data_block.do_num_bytes - 2
|
|
13
|
+
expect(data_block.byte_count).to eq remaining_size
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe 'class method #calculate_byte_count' do
|
|
18
|
+
it 'always returns 0' do
|
|
19
|
+
expect(described_class.calculate_byte_count).to eq 0
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'is little endian' do
|
|
24
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::Dialect do
|
|
2
|
+
subject(:dialect) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :buffer_format }
|
|
5
|
+
it { is_expected.to respond_to :dialect_string }
|
|
6
|
+
|
|
7
|
+
it 'is little endian' do
|
|
8
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe 'buffer_format' do
|
|
12
|
+
it 'should be a 8-bit field per the SMB spec' do
|
|
13
|
+
expect(dialect.buffer_format).to be_a BinData::Bit8
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'should be hardcoded to 0x2 by default per the SMB spec' do
|
|
17
|
+
expect(dialect.buffer_format).to eq 0x2
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe 'dialect_string' do
|
|
22
|
+
it 'should be a null terminated string per the SMB spec' do
|
|
23
|
+
expect(dialect.dialect_string).to be_a BinData::Stringz
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe RubySMB::SMB1::Packet::ErrorPacket do
|
|
4
|
+
subject(:packet) { described_class.new }
|
|
5
|
+
|
|
6
|
+
describe '#smb_header' do
|
|
7
|
+
subject(:header) { packet.smb_header }
|
|
8
|
+
|
|
9
|
+
it 'is a standard SMB Header' do
|
|
10
|
+
expect(header).to be_a RubySMB::SMB1::SMBHeader
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe '#parameter_block' do
|
|
16
|
+
subject(:parameter_block) { packet.parameter_block }
|
|
17
|
+
|
|
18
|
+
it 'is a standard ParameterBlock' do
|
|
19
|
+
expect(parameter_block).to be_a RubySMB::SMB1::ParameterBlock
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'should be empty' do
|
|
23
|
+
expect(parameter_block.to_binary_s).to eq "\x00"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#data_block' do
|
|
28
|
+
subject(:data_block) { packet.data_block }
|
|
29
|
+
|
|
30
|
+
it 'is a standard DataBlock' do
|
|
31
|
+
expect(data_block).to be_a RubySMB::SMB1::DataBlock
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'should be empty' do
|
|
35
|
+
expect(data_block.to_binary_s).to eq "\x00\x00"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::Packet::NegotiateRequest do
|
|
2
|
+
subject(:packet) { described_class.new }
|
|
3
|
+
let(:dialect_string) { 'NT LM 0.12' }
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
packet.add_dialect(dialect_string)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe '#smb_header' do
|
|
10
|
+
subject(:header) { packet.smb_header }
|
|
11
|
+
|
|
12
|
+
it 'is a standard SMB Header' do
|
|
13
|
+
expect(header).to be_a RubySMB::SMB1::SMBHeader
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'should have the command set to SMB_COM_NEGOTIATE' do
|
|
17
|
+
expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_NEGOTIATE
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should not have the response flag set' do
|
|
21
|
+
expect(header.flags.reply).to eq 0
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe '#parameter_block' do
|
|
26
|
+
subject(:parameter_block) { packet.parameter_block }
|
|
27
|
+
|
|
28
|
+
it 'is a standard ParameterBlock' do
|
|
29
|
+
expect(parameter_block).to be_a RubySMB::SMB1::ParameterBlock
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe '#data_block' do
|
|
34
|
+
subject(:data_block) { packet.data_block }
|
|
35
|
+
|
|
36
|
+
it 'is a standard DataBlock' do
|
|
37
|
+
expect(data_block).to be_a RubySMB::SMB1::DataBlock
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it { is_expected.to respond_to :dialects }
|
|
41
|
+
|
|
42
|
+
describe '#dialects' do
|
|
43
|
+
it 'is an array field as per the SMB spec' do
|
|
44
|
+
expect(data_block.dialects).to be_a BinData::Array
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe '#add_dialect' do
|
|
50
|
+
it 'adds a Dialect to the packet' do
|
|
51
|
+
expect { packet.add_dialect('foo') }.to change { packet.data_block.dialects.count }.by(1)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'uses the argument as the Dialect String' do
|
|
55
|
+
packet.add_dialect('bar')
|
|
56
|
+
dialects = packet.data_block.dialects.to_a
|
|
57
|
+
expect(dialects.last.dialect_string).to eq 'bar'
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe '#set_dialects' do
|
|
62
|
+
it 'clears out any existing dialects' do
|
|
63
|
+
expect { packet.set_dialects([]) }.to change { packet.data_block.dialects.count }.to(0)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'calls #add_dialect once for each string in the array' do
|
|
67
|
+
expect(packet).to receive(:add_dialect).exactly(3).times
|
|
68
|
+
packet.set_dialects(%w(foo bar baz))
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe '#dialects' do
|
|
73
|
+
it 'returns a ruby array of the dialect hashes' do
|
|
74
|
+
expect(packet.dialects).to eq [{:buffer_format=>2, :dialect_string=>"NT LM 0.12"}]
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::Packet::NegotiateResponseExtended do
|
|
2
|
+
subject(:packet) { described_class.new }
|
|
3
|
+
|
|
4
|
+
describe '#smb_header' do
|
|
5
|
+
subject(:header) { packet.smb_header }
|
|
6
|
+
|
|
7
|
+
it 'is a standard SMB Header' do
|
|
8
|
+
expect(header).to be_a RubySMB::SMB1::SMBHeader
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should have the command set to SMB_COM_NEGOTIATE' do
|
|
12
|
+
expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_NEGOTIATE
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'should have the response flag set' do
|
|
16
|
+
expect(header.flags.reply).to eq 1
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '#parameter_block' do
|
|
21
|
+
subject(:parameter_block) { packet.parameter_block }
|
|
22
|
+
|
|
23
|
+
it 'is a standard ParameterBlock' do
|
|
24
|
+
expect(parameter_block).to be_a RubySMB::SMB1::ParameterBlock
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it { is_expected.to respond_to :dialect_index }
|
|
28
|
+
it { is_expected.to respond_to :security_mode }
|
|
29
|
+
it { is_expected.to respond_to :max_mpx_count }
|
|
30
|
+
it { is_expected.to respond_to :max_number_vcs }
|
|
31
|
+
it { is_expected.to respond_to :max_buffer_size }
|
|
32
|
+
it { is_expected.to respond_to :max_raw_size }
|
|
33
|
+
it { is_expected.to respond_to :session_key }
|
|
34
|
+
it { is_expected.to respond_to :capabilities }
|
|
35
|
+
it { is_expected.to respond_to :system_time }
|
|
36
|
+
it { is_expected.to respond_to :server_time_zone }
|
|
37
|
+
it { is_expected.to respond_to :challenge_length }
|
|
38
|
+
|
|
39
|
+
describe '#dialect_index' do
|
|
40
|
+
it 'is a 16-bit Unsigned Integer' do
|
|
41
|
+
expect(parameter_block.dialect_index).to be_a BinData::Uint16le
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe '#security_mode' do
|
|
46
|
+
it 'is a SecurityMode bit-field' do
|
|
47
|
+
expect(parameter_block.security_mode).to be_a RubySMB::SMB1::BitField::SecurityMode
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe '#max_mpx_count' do
|
|
52
|
+
it 'is a 16-bit Unsigned Integer' do
|
|
53
|
+
expect(parameter_block.max_mpx_count).to be_a BinData::Uint16le
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#max_number_vcs' do
|
|
58
|
+
it 'is a 16-bit Unsigned Integer' do
|
|
59
|
+
expect(parameter_block.max_number_vcs).to be_a BinData::Uint16le
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe '#max_buffer_size' do
|
|
64
|
+
it 'is a 32-bit Unsigned Integer' do
|
|
65
|
+
expect(parameter_block.max_buffer_size).to be_a BinData::Uint32le
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe '#max_raw_size' do
|
|
70
|
+
it 'is a 32-bit Unsigned Integer' do
|
|
71
|
+
expect(parameter_block.max_raw_size).to be_a BinData::Uint32le
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe '#session_key' do
|
|
76
|
+
it 'is a 32-bit Unsigned Integer' do
|
|
77
|
+
expect(parameter_block.session_key).to be_a BinData::Uint32le
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe '#capabilities' do
|
|
82
|
+
it 'is a Capabilities bit-field' do
|
|
83
|
+
expect(parameter_block.capabilities).to be_a RubySMB::SMB1::BitField::Capabilities
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe '#system_time' do
|
|
88
|
+
it 'is a FileTime field' do
|
|
89
|
+
expect(parameter_block.system_time).to be_a RubySMB::Field::FileTime
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe '#server_time_zone' do
|
|
94
|
+
it 'is a 16-bit Signed Integer' do
|
|
95
|
+
expect(parameter_block.server_time_zone).to be_a BinData::Int16le
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe '#challenge_length' do
|
|
100
|
+
it 'is a 8-bit Unsigned Integer' do
|
|
101
|
+
expect(parameter_block.challenge_length).to be_a BinData::Uint8
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe '#data_block' do
|
|
107
|
+
subject(:data_block) { packet.data_block }
|
|
108
|
+
|
|
109
|
+
it 'is a standard DataBlock' do
|
|
110
|
+
expect(data_block).to be_a RubySMB::SMB1::DataBlock
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it { is_expected.to respond_to :server_guid }
|
|
114
|
+
it { is_expected.to respond_to :security_blob }
|
|
115
|
+
|
|
116
|
+
describe '#server_guid' do
|
|
117
|
+
it 'is binary string field' do
|
|
118
|
+
expect(data_block.server_guid).to be_a BinData::String
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'is exactly 16-bytes long' do
|
|
122
|
+
expect(data_block.server_guid.length).to eq 16
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
describe '#security_blob' do
|
|
127
|
+
it 'is a variable length "rest" field' do
|
|
128
|
+
expect(data_block.security_blob).to be_a BinData::Rest
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
describe '#valid?' do
|
|
134
|
+
it 'should return true if the command value ix 0x72' do
|
|
135
|
+
packet.parameter_block.capabilities.extended_security = 1
|
|
136
|
+
expect(packet.valid?).to be true
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it 'should return false if the command value is not 0x72' do
|
|
140
|
+
packet.smb_header.command = 0xff
|
|
141
|
+
expect(packet.valid?).to be false
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'should return false if the capabilities do not include extended security' do
|
|
145
|
+
packet.parameter_block.capabilities.extended_security = 0
|
|
146
|
+
expect(packet.valid?).to be false
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::Packet::NegotiateResponse do
|
|
2
|
+
subject(:packet) { described_class.new }
|
|
3
|
+
|
|
4
|
+
describe '#smb_header' do
|
|
5
|
+
subject(:header) { packet.smb_header }
|
|
6
|
+
|
|
7
|
+
it 'is a standard SMB Header' do
|
|
8
|
+
expect(header).to be_a RubySMB::SMB1::SMBHeader
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should have the command set to SMB_COM_NEGOTIATE' do
|
|
12
|
+
expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_NEGOTIATE
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'should have the response flag set' do
|
|
16
|
+
expect(header.flags.reply).to eq 1
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '#parameter_block' do
|
|
21
|
+
subject(:parameter_block) { packet.parameter_block }
|
|
22
|
+
|
|
23
|
+
it 'is a standard ParameterBlock' do
|
|
24
|
+
expect(parameter_block).to be_a RubySMB::SMB1::ParameterBlock
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it { is_expected.to respond_to :dialect_index }
|
|
28
|
+
it { is_expected.to respond_to :security_mode }
|
|
29
|
+
it { is_expected.to respond_to :max_mpx_count }
|
|
30
|
+
it { is_expected.to respond_to :max_number_vcs }
|
|
31
|
+
it { is_expected.to respond_to :max_buffer_size }
|
|
32
|
+
it { is_expected.to respond_to :max_raw_size }
|
|
33
|
+
it { is_expected.to respond_to :session_key }
|
|
34
|
+
it { is_expected.to respond_to :capabilities }
|
|
35
|
+
it { is_expected.to respond_to :system_time }
|
|
36
|
+
it { is_expected.to respond_to :server_time_zone }
|
|
37
|
+
it { is_expected.to respond_to :challenge_length }
|
|
38
|
+
|
|
39
|
+
describe '#dialect_index' do
|
|
40
|
+
it 'is a 16-bit Unsigned Integer' do
|
|
41
|
+
expect(parameter_block.dialect_index).to be_a BinData::Uint16le
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe '#security_mode' do
|
|
46
|
+
it 'is a SecurityMode bit-field' do
|
|
47
|
+
expect(parameter_block.security_mode).to be_a RubySMB::SMB1::BitField::SecurityMode
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe '#max_mpx_count' do
|
|
52
|
+
it 'is a 16-bit Unsigned Integer' do
|
|
53
|
+
expect(parameter_block.max_mpx_count).to be_a BinData::Uint16le
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#max_number_vcs' do
|
|
58
|
+
it 'is a 16-bit Unsigned Integer' do
|
|
59
|
+
expect(parameter_block.max_number_vcs).to be_a BinData::Uint16le
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe '#max_buffer_size' do
|
|
64
|
+
it 'is a 32-bit Unsigned Integer' do
|
|
65
|
+
expect(parameter_block.max_buffer_size).to be_a BinData::Uint32le
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe '#max_raw_size' do
|
|
70
|
+
it 'is a 32-bit Unsigned Integer' do
|
|
71
|
+
expect(parameter_block.max_raw_size).to be_a BinData::Uint32le
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe '#session_key' do
|
|
76
|
+
it 'is a 32-bit Unsigned Integer' do
|
|
77
|
+
expect(parameter_block.session_key).to be_a BinData::Uint32le
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe '#capabilities' do
|
|
82
|
+
it 'is a Capabilities bit-field' do
|
|
83
|
+
expect(parameter_block.capabilities).to be_a RubySMB::SMB1::BitField::Capabilities
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe '#system_time' do
|
|
88
|
+
it 'is a FileTime field' do
|
|
89
|
+
expect(parameter_block.system_time).to be_a RubySMB::Field::FileTime
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe '#server_time_zone' do
|
|
94
|
+
it 'is a 16-bit Signed Integer' do
|
|
95
|
+
expect(parameter_block.server_time_zone).to be_a BinData::Int16le
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe '#challenge_length' do
|
|
100
|
+
it 'is a 8-bit Unsigned Integer' do
|
|
101
|
+
expect(parameter_block.challenge_length).to be_a BinData::Uint8
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe '#data_block' do
|
|
107
|
+
subject(:data_block) { packet.data_block }
|
|
108
|
+
|
|
109
|
+
it 'is a standard DataBlock' do
|
|
110
|
+
expect(data_block).to be_a RubySMB::SMB1::DataBlock
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it { is_expected.to respond_to :challenge }
|
|
114
|
+
it { is_expected.to respond_to :domain_name }
|
|
115
|
+
it { is_expected.to respond_to :server_name }
|
|
116
|
+
|
|
117
|
+
describe '#challenge' do
|
|
118
|
+
it 'is a sized string of bytes' do
|
|
119
|
+
expect(data_block.challenge).to be_a BinData::String
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'is exactly 8-bytes long' do
|
|
123
|
+
expect(data_block.challenge.length).to eq 8
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
describe '#domain_name' do
|
|
128
|
+
it 'is a Unicode Null-terminated string' do
|
|
129
|
+
expect(data_block.domain_name).to be_a RubySMB::Field::Stringz16
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
describe '#server_name' do
|
|
134
|
+
it 'is a Unicode Null-terminated string' do
|
|
135
|
+
expect(data_block.server_name).to be_a RubySMB::Field::Stringz16
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
describe '#valid?' do
|
|
141
|
+
it 'should return true if the command value ix 0x72' do
|
|
142
|
+
expect(packet.valid?).to be true
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'should return false if the command value is not 0x72' do
|
|
146
|
+
packet.smb_header.command = 0xff
|
|
147
|
+
expect(packet.valid?).to be false
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|