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.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.gitignore +21 -0
  4. data/.rspec +3 -0
  5. data/.simplecov +42 -0
  6. data/.travis.yml +5 -0
  7. data/.yardopts +1 -0
  8. data/CONTRIBUTING.md +119 -0
  9. data/Gemfile +13 -0
  10. data/LICENSE.txt +18 -0
  11. data/README.md +64 -0
  12. data/Rakefile +22 -0
  13. data/examples/authenticate.rb +30 -0
  14. data/examples/negotiate.rb +25 -0
  15. data/lib/ruby_smb/client/authentication.rb +236 -0
  16. data/lib/ruby_smb/client/negotiation.rb +126 -0
  17. data/lib/ruby_smb/client/signing.rb +48 -0
  18. data/lib/ruby_smb/client.rb +164 -0
  19. data/lib/ruby_smb/dispatcher/base.rb +18 -0
  20. data/lib/ruby_smb/dispatcher/socket.rb +53 -0
  21. data/lib/ruby_smb/dispatcher.rb +4 -0
  22. data/lib/ruby_smb/error.rb +17 -0
  23. data/lib/ruby_smb/field/file_time.rb +62 -0
  24. data/lib/ruby_smb/field/nt_status.rb +16 -0
  25. data/lib/ruby_smb/field/stringz16.rb +55 -0
  26. data/lib/ruby_smb/field.rb +7 -0
  27. data/lib/ruby_smb/generic_packet.rb +179 -0
  28. data/lib/ruby_smb/gss.rb +109 -0
  29. data/lib/ruby_smb/smb1/andx_block.rb +13 -0
  30. data/lib/ruby_smb/smb1/bit_field/capabilities.rb +39 -0
  31. data/lib/ruby_smb/smb1/bit_field/header_flags.rb +19 -0
  32. data/lib/ruby_smb/smb1/bit_field/header_flags2.rb +27 -0
  33. data/lib/ruby_smb/smb1/bit_field/security_mode.rb +16 -0
  34. data/lib/ruby_smb/smb1/bit_field.rb +10 -0
  35. data/lib/ruby_smb/smb1/commands.rb +9 -0
  36. data/lib/ruby_smb/smb1/data_block.rb +42 -0
  37. data/lib/ruby_smb/smb1/dialect.rb +11 -0
  38. data/lib/ruby_smb/smb1/packet/error_packet.rb +14 -0
  39. data/lib/ruby_smb/smb1/packet/negotiate_request.rb +52 -0
  40. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +46 -0
  41. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +47 -0
  42. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +71 -0
  43. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +48 -0
  44. data/lib/ruby_smb/smb1/packet.rb +12 -0
  45. data/lib/ruby_smb/smb1/parameter_block.rb +42 -0
  46. data/lib/ruby_smb/smb1/smb_header.rb +21 -0
  47. data/lib/ruby_smb/smb1.rb +16 -0
  48. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +17 -0
  49. data/lib/ruby_smb/smb2/bit_field/smb2_capabailities.rb +23 -0
  50. data/lib/ruby_smb/smb2/bit_field/smb2_header_flags.rb +23 -0
  51. data/lib/ruby_smb/smb2/bit_field/smb2_security_mode.rb +15 -0
  52. data/lib/ruby_smb/smb2/bit_field/smb2_security_mode_single.rb +14 -0
  53. data/lib/ruby_smb/smb2/bit_field.rb +11 -0
  54. data/lib/ruby_smb/smb2/commands.rb +25 -0
  55. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +50 -0
  56. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +33 -0
  57. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +53 -0
  58. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +38 -0
  59. data/lib/ruby_smb/smb2/packet.rb +10 -0
  60. data/lib/ruby_smb/smb2/smb2_header.rb +22 -0
  61. data/lib/ruby_smb/smb2.rb +12 -0
  62. data/lib/ruby_smb/version.rb +3 -0
  63. data/lib/ruby_smb.rb +22 -0
  64. data/ruby_smb.gemspec +38 -0
  65. data/spec/lib/ruby_smb/client_spec.rb +638 -0
  66. data/spec/lib/ruby_smb/dispatcher/dispatcher_base_spec.rb +22 -0
  67. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +60 -0
  68. data/spec/lib/ruby_smb/field/file_time_spec.rb +59 -0
  69. data/spec/lib/ruby_smb/field/nt_status_spec.rb +19 -0
  70. data/spec/lib/ruby_smb/field/stringz16_spec.rb +50 -0
  71. data/spec/lib/ruby_smb/generic_packet_spec.rb +58 -0
  72. data/spec/lib/ruby_smb/smb1/andx_block_spec.rb +41 -0
  73. data/spec/lib/ruby_smb/smb1/bit_field/capabilities_spec.rb +245 -0
  74. data/spec/lib/ruby_smb/smb1/bit_field/header_flags2_spec.rb +146 -0
  75. data/spec/lib/ruby_smb/smb1/bit_field/header_flags_spec.rb +102 -0
  76. data/spec/lib/ruby_smb/smb1/bit_field/security_mode_spec.rb +44 -0
  77. data/spec/lib/ruby_smb/smb1/data_block_spec.rb +26 -0
  78. data/spec/lib/ruby_smb/smb1/dialect_spec.rb +26 -0
  79. data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +39 -0
  80. data/spec/lib/ruby_smb/smb1/packet/negotiate_request_spec.rb +77 -0
  81. data/spec/lib/ruby_smb/smb1/packet/negotiate_response_extended_spec.rb +149 -0
  82. data/spec/lib/ruby_smb/smb1/packet/negotiate_response_spec.rb +150 -0
  83. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +100 -0
  84. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +72 -0
  85. data/spec/lib/ruby_smb/smb1/parameter_block_spec.rb +26 -0
  86. data/spec/lib/ruby_smb/smb1/smb_header_spec.rb +96 -0
  87. data/spec/lib/ruby_smb/smb2/bit_field/header_flags_spec.rb +81 -0
  88. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +28 -0
  89. data/spec/lib/ruby_smb/smb2/bit_field/smb2_capabilities_spec.rb +72 -0
  90. data/spec/lib/ruby_smb/smb2/bit_field/smb_secruity_mode_spec.rb +22 -0
  91. data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +122 -0
  92. data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +147 -0
  93. data/spec/lib/ruby_smb/smb2/packet/session_setup_request_spec.rb +79 -0
  94. data/spec/lib/ruby_smb/smb2/packet/session_setup_response_spec.rb +54 -0
  95. data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +127 -0
  96. data/spec/lib/ruby_smb_spec.rb +2 -0
  97. data/spec/spec_helper.rb +100 -0
  98. data/spec/support/mock_socket_dispatcher.rb +8 -0
  99. data/spec/support/shared/examples/bit_field_single_flag.rb +14 -0
  100. data.tar.gz.sig +0 -0
  101. metadata +384 -0
  102. 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