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,100 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe RubySMB::SMB1::Packet::SessionSetupRequest do
|
|
4
|
+
|
|
5
|
+
subject(:packet) { described_class.new }
|
|
6
|
+
|
|
7
|
+
describe '#smb_header' do
|
|
8
|
+
subject(:header) { packet.smb_header }
|
|
9
|
+
|
|
10
|
+
it 'is a standard SMB Header' do
|
|
11
|
+
expect(header).to be_a RubySMB::SMB1::SMBHeader
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'should have the command set to SMB_COM_NEGOTIATE' do
|
|
15
|
+
expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'should not have the response flag set' do
|
|
19
|
+
expect(header.flags.reply).to eq 0
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe '#parameter_block' do
|
|
24
|
+
subject(:parameter_block) { packet.parameter_block }
|
|
25
|
+
|
|
26
|
+
it 'is a standard ParameterBlock' do
|
|
27
|
+
expect(parameter_block).to be_a RubySMB::SMB1::ParameterBlock
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it { is_expected.to respond_to :andx_block }
|
|
31
|
+
it { is_expected.to respond_to :max_buffer_size }
|
|
32
|
+
it { is_expected.to respond_to :max_mpx_count }
|
|
33
|
+
it { is_expected.to respond_to :vc_number }
|
|
34
|
+
it { is_expected.to respond_to :session_key }
|
|
35
|
+
it { is_expected.to respond_to :security_blob_length }
|
|
36
|
+
it { is_expected.to respond_to :capabilities }
|
|
37
|
+
|
|
38
|
+
it 'has an AndXBlock' do
|
|
39
|
+
expect(parameter_block.andx_block).to be_a RubySMB::SMB1::AndXBlock
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe '#data_block' do
|
|
44
|
+
subject(:data_block) { packet.data_block }
|
|
45
|
+
|
|
46
|
+
it 'is a standard DataBlock' do
|
|
47
|
+
expect(data_block).to be_a RubySMB::SMB1::DataBlock
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it { is_expected.to respond_to :security_blob }
|
|
51
|
+
it { is_expected.to respond_to :native_os }
|
|
52
|
+
it { is_expected.to respond_to :native_lan_man }
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe '#set_type1_blob' do
|
|
57
|
+
let(:fake_message) { "foo" }
|
|
58
|
+
|
|
59
|
+
it 'calls the #gss_type1 method to create a blob' do
|
|
60
|
+
expect(RubySMB::Gss).to receive(:gss_type1).with(fake_message).and_return(fake_message)
|
|
61
|
+
packet.set_type1_blob(fake_message)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'sets the security blob to the result from the GSS call' do
|
|
65
|
+
expect(RubySMB::Gss).to receive(:gss_type1).with(fake_message).and_return(fake_message)
|
|
66
|
+
packet.set_type1_blob(fake_message)
|
|
67
|
+
expect(packet.data_block.security_blob).to eq fake_message
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'sets the security_blob_length field automatically' do
|
|
71
|
+
expect(RubySMB::Gss).to receive(:gss_type1).with(fake_message).and_return(fake_message)
|
|
72
|
+
packet.set_type1_blob(fake_message)
|
|
73
|
+
expect(packet.parameter_block.security_blob_length).to eq fake_message.length
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe '#set_type3_blob' do
|
|
78
|
+
let(:fake_message) { "foo" }
|
|
79
|
+
|
|
80
|
+
it 'calls the #gss_type3 method to create a blob' do
|
|
81
|
+
expect(RubySMB::Gss).to receive(:gss_type3).with(fake_message).and_return(fake_message)
|
|
82
|
+
packet.set_type3_blob(fake_message)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'sets the security blob to the result from the GSS call' do
|
|
86
|
+
expect(RubySMB::Gss).to receive(:gss_type3).with(fake_message).and_return(fake_message)
|
|
87
|
+
packet.set_type3_blob(fake_message)
|
|
88
|
+
expect(packet.data_block.security_blob).to eq fake_message
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'sets the security_blob_length field automatically' do
|
|
92
|
+
expect(RubySMB::Gss).to receive(:gss_type3).with(fake_message).and_return(fake_message)
|
|
93
|
+
packet.set_type3_blob(fake_message)
|
|
94
|
+
expect(packet.parameter_block.security_blob_length).to eq fake_message.length
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe RubySMB::SMB1::Packet::SessionSetupResponse do
|
|
4
|
+
|
|
5
|
+
subject(:packet) { described_class.new }
|
|
6
|
+
|
|
7
|
+
describe '#smb_header' do
|
|
8
|
+
subject(:header) { packet.smb_header }
|
|
9
|
+
|
|
10
|
+
it 'is a standard SMB Header' do
|
|
11
|
+
expect(header).to be_a RubySMB::SMB1::SMBHeader
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'should have the command set to SMB_COM_NEGOTIATE' do
|
|
15
|
+
expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'should have the response flag set' do
|
|
19
|
+
expect(header.flags.reply).to eq 1
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe '#parameter_block' do
|
|
24
|
+
subject(:parameter_block) { packet.parameter_block }
|
|
25
|
+
|
|
26
|
+
it 'is a standard ParameterBlock' do
|
|
27
|
+
expect(parameter_block).to be_a RubySMB::SMB1::ParameterBlock
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it { is_expected.to respond_to :andx_block }
|
|
31
|
+
it { is_expected.to respond_to :action }
|
|
32
|
+
it { is_expected.to respond_to :security_blob_length }
|
|
33
|
+
|
|
34
|
+
it 'has an AndXBlock' do
|
|
35
|
+
expect(parameter_block.andx_block).to be_a RubySMB::SMB1::AndXBlock
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe '#data_block' do
|
|
40
|
+
subject(:data_block) { packet.data_block }
|
|
41
|
+
|
|
42
|
+
it 'is a standard DataBlock' do
|
|
43
|
+
expect(data_block).to be_a RubySMB::SMB1::DataBlock
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it { is_expected.to respond_to :security_blob }
|
|
47
|
+
it { is_expected.to respond_to :native_os }
|
|
48
|
+
it { is_expected.to respond_to :native_lan_man }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe '#set_type2_blob' do
|
|
52
|
+
let(:fake_message) { "foo" }
|
|
53
|
+
|
|
54
|
+
it 'calls the #gss_type2 method to create a blob' do
|
|
55
|
+
expect(RubySMB::Gss).to receive(:gss_type2).with(fake_message).and_return(fake_message)
|
|
56
|
+
packet.set_type2_blob(fake_message)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'sets the security blob to the result from the GSS call' do
|
|
60
|
+
expect(RubySMB::Gss).to receive(:gss_type2).with(fake_message).and_return(fake_message)
|
|
61
|
+
packet.set_type2_blob(fake_message)
|
|
62
|
+
expect(packet.data_block.security_blob).to eq fake_message
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'sets the security_blob_length field automatically' do
|
|
66
|
+
expect(RubySMB::Gss).to receive(:gss_type2).with(fake_message).and_return(fake_message)
|
|
67
|
+
packet.set_type2_blob(fake_message)
|
|
68
|
+
expect(packet.parameter_block.security_blob_length).to eq fake_message.length
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::ParameterBlock do
|
|
2
|
+
subject(:parameter_block) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :word_count }
|
|
5
|
+
|
|
6
|
+
describe 'byte_count' do
|
|
7
|
+
it 'should be a 8-bit field per the SMB spec' do
|
|
8
|
+
expect(parameter_block.word_count).to be_a BinData::Uint8
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should equal the size of the rest of the block in words' do
|
|
12
|
+
remaining_size = ((parameter_block.do_num_bytes - 1) / 2).ceil
|
|
13
|
+
expect(parameter_block.word_count).to eq remaining_size
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe 'class method #calculate_word_count' do
|
|
18
|
+
it 'always returns 0' do
|
|
19
|
+
expect(described_class.calculate_word_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,96 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB1::SMBHeader do
|
|
2
|
+
subject(:header) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :protocol }
|
|
5
|
+
it { is_expected.to respond_to :command }
|
|
6
|
+
it { is_expected.to respond_to :nt_status }
|
|
7
|
+
it { is_expected.to respond_to :flags }
|
|
8
|
+
|
|
9
|
+
it { is_expected.to respond_to :pid_high }
|
|
10
|
+
it { is_expected.to respond_to :security_features }
|
|
11
|
+
it { is_expected.to respond_to :reserved }
|
|
12
|
+
it { is_expected.to respond_to :tid }
|
|
13
|
+
it { is_expected.to respond_to :pid_low }
|
|
14
|
+
it { is_expected.to respond_to :uid }
|
|
15
|
+
it { is_expected.to respond_to :mid }
|
|
16
|
+
|
|
17
|
+
describe 'protocol' do
|
|
18
|
+
it 'should be a 32-bit field per the SMB spec' do
|
|
19
|
+
expect(header.protocol).to be_a BinData::Bit32
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'should be hardcoded to SMB_PROTOCOL_ID by default per the SMB spec' do
|
|
23
|
+
expect(header.protocol).to eq RubySMB::SMB1::SMB_PROTOCOL_ID
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe 'command' do
|
|
28
|
+
it 'should be a 8-bit field per the SMB spec' do
|
|
29
|
+
expect(header.command).to be_a BinData::Bit8
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe 'nt_status' do
|
|
34
|
+
it 'should be a NTStatus field' do
|
|
35
|
+
expect(header.nt_status).to be_a RubySMB::Field::NtStatus
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe 'flags' do
|
|
40
|
+
it 'should be a HeaderFlags BitField' do
|
|
41
|
+
expect(header.flags).to be_a RubySMB::SMB1::BitField::HeaderFlags
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe 'flags2' do
|
|
46
|
+
it 'should be a HeaderFlags2 BitField' do
|
|
47
|
+
expect(header.flags2).to be_a RubySMB::SMB1::BitField::HeaderFlags2
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe 'pid_high' do
|
|
52
|
+
it 'should be a 16-bit field per the SMB spec' do
|
|
53
|
+
expect(header.pid_high).to be_a BinData::Bit16
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe 'security_features' do
|
|
58
|
+
it 'should be a 8-byte string per the SMB spec' do
|
|
59
|
+
expect(header.security_features).to be_a BinData::String
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe 'reserved' do
|
|
64
|
+
it 'should be a 16-bit field per the SMB spec' do
|
|
65
|
+
expect(header.reserved).to be_a BinData::Bit16
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe 'tid' do
|
|
70
|
+
it 'should be a 16-bit field per the SMB spec' do
|
|
71
|
+
expect(header.tid).to be_a BinData::Bit16
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe 'pid_low' do
|
|
76
|
+
it 'should be a 16-bit field per the SMB spec' do
|
|
77
|
+
expect(header.pid_low).to be_a BinData::Bit16
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe 'uid' do
|
|
82
|
+
it 'should be a 16-bit field per the SMB spec' do
|
|
83
|
+
expect(header.uid).to be_a BinData::Bit16
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe 'mid' do
|
|
88
|
+
it 'should be a 16-bit field per the SMB spec' do
|
|
89
|
+
expect(header.mid).to be_a BinData::Bit16
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it 'is little endian' do
|
|
94
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB2::BitField::Smb2HeaderFlags do
|
|
2
|
+
subject(:flags) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :reserved1 }
|
|
5
|
+
it { is_expected.to respond_to :replay_operation }
|
|
6
|
+
it { is_expected.to respond_to :dfs_operation }
|
|
7
|
+
it { is_expected.to respond_to :reserved2 }
|
|
8
|
+
it { is_expected.to respond_to :reserved3 }
|
|
9
|
+
it { is_expected.to respond_to :signed }
|
|
10
|
+
it { is_expected.to respond_to :related_operations }
|
|
11
|
+
it { is_expected.to respond_to :async_command }
|
|
12
|
+
it { is_expected.to respond_to :reply }
|
|
13
|
+
|
|
14
|
+
it 'is little endian' do
|
|
15
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe '#reserved1' do
|
|
19
|
+
it 'should be a 2-bit field per the SMB spec' do
|
|
20
|
+
expect(flags.reserved1).to be_a BinData::Bit2
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe '#replay_operation' do
|
|
25
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
26
|
+
expect(flags.replay_operation).to be_a BinData::Bit1
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it_behaves_like 'bit field with one flag set', :replay_operation, 'V', 0x20000000
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe '#dfs_operation' do
|
|
33
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
34
|
+
expect(flags.dfs_operation).to be_a BinData::Bit1
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it_behaves_like 'bit field with one flag set', :dfs_operation, 'V', 0x10000000
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe '#reserved2' do
|
|
41
|
+
it 'should be a 2-byte field per the SMB spec' do
|
|
42
|
+
expect(flags.reserved2).to be_a BinData::Uint16le
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe '#reserved3' do
|
|
47
|
+
it 'should be a 4-bit field per the SMB spec' do
|
|
48
|
+
expect(flags.reserved3).to be_a BinData::Bit4
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe '#signed' do
|
|
53
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
54
|
+
expect(flags.signed).to be_a BinData::Bit1
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it_behaves_like 'bit field with one flag set', :signed, 'V', 0x00000008
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe '#related_operations' do
|
|
61
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
62
|
+
expect(flags.related_operations).to be_a BinData::Bit1
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it_behaves_like 'bit field with one flag set', :related_operations, 'V', 0x00000004
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe '#async_command' do
|
|
69
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
70
|
+
expect(flags.async_command).to be_a BinData::Bit1
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe '#reply' do
|
|
75
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
76
|
+
expect(flags.reply).to be_a BinData::Bit1
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it_behaves_like 'bit field with one flag set', :reply, 'V', 0x00000001
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe RubySMB::SMB2::BitField::SessionFlags do
|
|
4
|
+
subject(:flags) { described_class.new }
|
|
5
|
+
|
|
6
|
+
it { is_expected.to respond_to :guest }
|
|
7
|
+
it { is_expected.to respond_to :null }
|
|
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 '#guest' do
|
|
14
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
15
|
+
expect(flags.guest).to be_a BinData::Bit1
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it_behaves_like 'bit field with one flag set', :guest, 'v', 0x00000001
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe '#null' do
|
|
22
|
+
it 'should be a 1-bit field per the SMB spec' do
|
|
23
|
+
expect(flags.null).to be_a BinData::Bit1
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it_behaves_like 'bit field with one flag set', :null, 'v', 0x00000002
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB2::BitField::Smb2Capabilities do
|
|
2
|
+
subject(:capabilities) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :reserved2 }
|
|
5
|
+
it { is_expected.to respond_to :encryption }
|
|
6
|
+
it { is_expected.to respond_to :directory_leasing }
|
|
7
|
+
it { is_expected.to respond_to :persistent_handles }
|
|
8
|
+
it { is_expected.to respond_to :multi_channel }
|
|
9
|
+
it { is_expected.to respond_to :large_mtu }
|
|
10
|
+
it { is_expected.to respond_to :leasing }
|
|
11
|
+
it { is_expected.to respond_to :dfs }
|
|
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 '#encryption' do
|
|
18
|
+
it 'is a 1-bit flag' do
|
|
19
|
+
expect(capabilities.encryption).to be_a BinData::Bit1
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it_behaves_like 'bit field with one flag set', :encryption, 'V', 0x00000040
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe '#directory_leasing' do
|
|
26
|
+
it 'is a 1-bit flag' do
|
|
27
|
+
expect(capabilities.directory_leasing).to be_a BinData::Bit1
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it_behaves_like 'bit field with one flag set', :directory_leasing, 'V', 0x00000020
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe '#persistent_handles' do
|
|
34
|
+
it 'is a 1-bit flag' do
|
|
35
|
+
expect(capabilities.persistent_handles).to be_a BinData::Bit1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it_behaves_like 'bit field with one flag set', :persistent_handles, 'V', 0x00000010
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe '#multi_channel' do
|
|
42
|
+
it 'is a 1-bit flag' do
|
|
43
|
+
expect(capabilities.multi_channel).to be_a BinData::Bit1
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it_behaves_like 'bit field with one flag set', :multi_channel, 'V', 0x00000008
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe '#large_mtu' do
|
|
50
|
+
it 'is a 1-bit flag' do
|
|
51
|
+
expect(capabilities.large_mtu).to be_a BinData::Bit1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it_behaves_like 'bit field with one flag set', :large_mtu, 'V', 0x00000004
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#leasing' do
|
|
58
|
+
it 'is a 1-bit flag' do
|
|
59
|
+
expect(capabilities.leasing).to be_a BinData::Bit1
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it_behaves_like 'bit field with one flag set', :leasing, 'V', 0x00000002
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe '#dfs' do
|
|
66
|
+
it 'is a 1-bit flag' do
|
|
67
|
+
expect(capabilities.dfs).to be_a BinData::Bit1
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it_behaves_like 'bit field with one flag set', :dfs, 'V', 0x00000001
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB2::BitField::Smb2SecurityMode do
|
|
2
|
+
subject(:security_mode) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :signing_required }
|
|
5
|
+
it { is_expected.to respond_to :signing_enabled }
|
|
6
|
+
|
|
7
|
+
describe '#signing_required' do
|
|
8
|
+
it 'is a 1-bit flag' do
|
|
9
|
+
expect(security_mode.signing_required).to be_a BinData::Bit1
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it_behaves_like 'bit field with one flag set', :signing_required, 'v', 0x0002
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe '#signing_enabled' do
|
|
16
|
+
it 'is a 1-bit flag' do
|
|
17
|
+
expect(security_mode.signing_enabled).to be_a BinData::Bit1
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it_behaves_like 'bit field with one flag set', :signing_enabled, 'v', 0x0001
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
RSpec.describe RubySMB::SMB2::Packet::NegotiateRequest do
|
|
2
|
+
subject(:packet) { described_class.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :smb2_header }
|
|
5
|
+
it { is_expected.to respond_to :structure_size }
|
|
6
|
+
it { is_expected.to respond_to :dialect_count }
|
|
7
|
+
it { is_expected.to respond_to :security_mode }
|
|
8
|
+
it { is_expected.to respond_to :reserved1 }
|
|
9
|
+
it { is_expected.to respond_to :capabilities }
|
|
10
|
+
it { is_expected.to respond_to :client_guid }
|
|
11
|
+
it { is_expected.to respond_to :client_start_time }
|
|
12
|
+
it { is_expected.to respond_to :dialects }
|
|
13
|
+
|
|
14
|
+
it 'is little endian' do
|
|
15
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe '#smb2_header' do
|
|
19
|
+
subject(:header) { packet.smb2_header }
|
|
20
|
+
|
|
21
|
+
it 'is a standard SMB Header' do
|
|
22
|
+
expect(header).to be_a RubySMB::SMB2::SMB2Header
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'should have the command set to SMB_COM_NEGOTIATE' do
|
|
26
|
+
expect(header.command).to eq RubySMB::SMB2::Commands::NEGOTIATE
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'should not have the response flag set' do
|
|
30
|
+
expect(header.flags.reply).to eq 0
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe '#structure_size' do
|
|
35
|
+
it 'should be a 16-bit unsigned integer' do
|
|
36
|
+
expect(packet.structure_size).to be_a BinData::Uint16le
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'should have a default value of 36 as per the SMB2 spec' do
|
|
40
|
+
expect(packet.structure_size).to eq 36
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe '#dialect_count' do
|
|
45
|
+
it 'should be a 16-bit unsigned integer' do
|
|
46
|
+
expect(packet.dialect_count).to be_a BinData::Uint16le
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe '#security_mode' do
|
|
51
|
+
it 'should be a SMB2 Security Mode BitField' do
|
|
52
|
+
expect(packet.security_mode).to be_a RubySMB::SMB2::BitField::Smb2SecurityMode
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe '#capabailities' do
|
|
57
|
+
it 'should be a SMB2 Capabilities BitField' do
|
|
58
|
+
expect(packet.capabilities).to be_a RubySMB::SMB2::BitField::Smb2Capabilities
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe '#client_guid' do
|
|
63
|
+
it 'should be a binary string' do
|
|
64
|
+
expect(packet.client_guid).to be_a BinData::String
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'should be 16-bytes' do
|
|
68
|
+
expect(packet.client_guid.do_num_bytes).to eq 16
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe '#client_start_time' do
|
|
73
|
+
it 'should be a Filetime field' do
|
|
74
|
+
expect(packet.client_start_time).to be_a RubySMB::Field::FileTime
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'should have a default value of 0 as per the SMB2 spec' do
|
|
78
|
+
expect(packet.client_start_time).to eq 0
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe '#dialects' do
|
|
83
|
+
it 'is an array field as per the SMB spec' do
|
|
84
|
+
expect(packet.dialects).to be_a BinData::Array
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe '#add_dialect' do
|
|
89
|
+
it 'adds the dialect to the Dialects array' do
|
|
90
|
+
packet.add_dialect 0x0201
|
|
91
|
+
expect(packet.dialects).to include(0x0201)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'updates the #dialect_count field' do
|
|
95
|
+
packet.add_dialect 0x0201
|
|
96
|
+
expect(packet.dialect_count).to eq 1
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
describe '#set_dialects' do
|
|
101
|
+
before(:each) do
|
|
102
|
+
packet.add_dialect 0x0201
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
let(:dialect_set) { [0x0202, 0x0210, 0x0300] }
|
|
106
|
+
|
|
107
|
+
it 'removes the existing dialects' do
|
|
108
|
+
packet.set_dialects dialect_set
|
|
109
|
+
expect(packet.dialects).to_not include(0x0201)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'sets #dialects to exacty what is supplied' do
|
|
113
|
+
packet.set_dialects dialect_set
|
|
114
|
+
expect(packet.dialects).to match_array(dialect_set)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'sets the #dialect_count field correctly' do
|
|
118
|
+
packet.set_dialects dialect_set
|
|
119
|
+
expect(packet.dialect_count).to eq 3
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|