ruby_smb 2.0.13 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/examples/anonymous_auth.rb +29 -6
  4. data/examples/auth_capture.rb +28 -0
  5. data/examples/file_server.rb +76 -0
  6. data/examples/read_file.rb +51 -10
  7. data/examples/tree_connect.rb +49 -8
  8. data/lib/ruby_smb/client/authentication.rb +11 -3
  9. data/lib/ruby_smb/client.rb +11 -2
  10. data/lib/ruby_smb/create_actions.rb +21 -0
  11. data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_request.rb +20 -0
  12. data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_response.rb +20 -0
  13. data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_request.rb +21 -0
  14. data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_response.rb +21 -0
  15. data/lib/ruby_smb/dcerpc/encrypting_file_system.rb +44 -0
  16. data/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_request.rb +22 -0
  17. data/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_response.rb +20 -0
  18. data/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_request.rb +24 -0
  19. data/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_response.rb +23 -0
  20. data/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_request.rb +24 -0
  21. data/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_response.rb +22 -0
  22. data/lib/ruby_smb/dcerpc/print_system.rb +69 -0
  23. data/lib/ruby_smb/dcerpc.rb +2 -2
  24. data/lib/ruby_smb/field/nt_status.rb +20 -1
  25. data/lib/ruby_smb/fscc/file_information/file_ea_information.rb +14 -0
  26. data/lib/ruby_smb/fscc/file_information/file_network_open_information.rb +22 -0
  27. data/lib/ruby_smb/fscc/file_information/file_stream_information.rb +16 -0
  28. data/lib/ruby_smb/fscc/file_information.rb +29 -0
  29. data/lib/ruby_smb/fscc/file_system_information/file_fs_attribute_information.rb +46 -0
  30. data/lib/ruby_smb/fscc/file_system_information/file_fs_volume_information.rb +19 -0
  31. data/lib/ruby_smb/fscc/file_system_information.rb +22 -0
  32. data/lib/ruby_smb/fscc.rb +1 -0
  33. data/lib/ruby_smb/generic_packet.rb +6 -0
  34. data/lib/ruby_smb/gss/provider/authenticator.rb +4 -0
  35. data/lib/ruby_smb/gss/provider/ntlm.rb +13 -3
  36. data/lib/ruby_smb/server/server_client/negotiation.rb +0 -2
  37. data/lib/ruby_smb/server/server_client/session_setup.rb +43 -32
  38. data/lib/ruby_smb/server/server_client/share_io.rb +28 -0
  39. data/lib/ruby_smb/server/server_client/tree_connect.rb +60 -0
  40. data/lib/ruby_smb/server/server_client.rb +214 -24
  41. data/lib/ruby_smb/server/session.rb +71 -0
  42. data/lib/ruby_smb/server/share/provider/disk.rb +437 -0
  43. data/lib/ruby_smb/server/share/provider/pipe.rb +27 -0
  44. data/lib/ruby_smb/server/share/provider/processor.rb +76 -0
  45. data/lib/ruby_smb/server/share/provider.rb +38 -0
  46. data/lib/ruby_smb/server/share.rb +11 -0
  47. data/lib/ruby_smb/server.rb +35 -3
  48. data/lib/ruby_smb/signing.rb +37 -11
  49. data/lib/ruby_smb/smb1/commands.rb +4 -0
  50. data/lib/ruby_smb/smb1/tree.rb +87 -79
  51. data/lib/ruby_smb/smb1.rb +0 -1
  52. data/lib/ruby_smb/smb2/bit_field/smb2_header_flags.rb +2 -1
  53. data/lib/ruby_smb/smb2/commands.rb +4 -0
  54. data/lib/ruby_smb/smb2/create_context/request.rb +64 -0
  55. data/lib/ruby_smb/smb2/create_context/response.rb +62 -0
  56. data/lib/ruby_smb/smb2/create_context.rb +74 -22
  57. data/lib/ruby_smb/smb2/packet/create_request.rb +44 -11
  58. data/lib/ruby_smb/smb2/packet/create_response.rb +17 -3
  59. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +1 -1
  60. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +2 -2
  61. data/lib/ruby_smb/smb2/packet/query_info_request.rb +43 -0
  62. data/lib/ruby_smb/smb2/packet/query_info_response.rb +23 -0
  63. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +1 -1
  64. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +1 -0
  65. data/lib/ruby_smb/smb2/packet.rb +2 -0
  66. data/lib/ruby_smb/smb2/tree.rb +80 -70
  67. data/lib/ruby_smb/smb2.rb +11 -0
  68. data/lib/ruby_smb/smb_error.rb +110 -0
  69. data/lib/ruby_smb/version.rb +1 -1
  70. data/lib/ruby_smb.rb +2 -0
  71. data/ruby_smb.gemspec +1 -1
  72. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_request_spec.rb +30 -0
  73. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_response_spec.rb +30 -0
  74. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_request_spec.rb +38 -0
  75. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_response_spec.rb +38 -0
  76. data/spec/lib/ruby_smb/dcerpc/print_system/driver_container_spec.rb +41 -0
  77. data/spec/lib/ruby_smb/dcerpc/print_system/driver_info2_spec.rb +64 -0
  78. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_request_spec.rb +59 -0
  79. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_response_spec.rb +30 -0
  80. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_request_spec.rb +62 -0
  81. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_response_spec.rb +54 -0
  82. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_request_spec.rb +62 -0
  83. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_response_spec.rb +46 -0
  84. data/spec/lib/ruby_smb/field/nt_status_spec.rb +6 -2
  85. data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +4 -0
  86. data/spec/lib/ruby_smb/server/server_client_spec.rb +36 -53
  87. data/spec/lib/ruby_smb/server/session_spec.rb +38 -0
  88. data/spec/lib/ruby_smb/server/share/provider/disk_spec.rb +61 -0
  89. data/spec/lib/ruby_smb/server/share/provider/pipe_spec.rb +31 -0
  90. data/spec/lib/ruby_smb/server/share/provider_spec.rb +13 -0
  91. data/spec/lib/ruby_smb/smb1/tree_spec.rb +3 -3
  92. data/spec/lib/ruby_smb/smb2/bit_field/header_flags_spec.rb +8 -2
  93. data/spec/lib/ruby_smb/smb2/{create_context_spec.rb → create_context/create_context_request_spec.rb} +1 -1
  94. data/spec/lib/ruby_smb/smb2/packet/create_request_spec.rb +5 -5
  95. data/spec/lib/ruby_smb/smb2/packet/create_response_spec.rb +9 -5
  96. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +3 -2
  97. data/spec/lib/ruby_smb/smb2/tree_spec.rb +3 -3
  98. data.tar.gz.sig +3 -2
  99. metadata +71 -7
  100. metadata.gz.sig +0 -0
  101. data/lib/ruby_smb/smb1/create_actions.rb +0 -20
@@ -0,0 +1,64 @@
1
+ RSpec.describe RubySMB::Dcerpc::PrintSystem::DriverInfo2 do
2
+ subject(:struct) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :c_version }
5
+ it { is_expected.to respond_to :p_name }
6
+ it { is_expected.to respond_to :p_environment }
7
+ it { is_expected.to respond_to :p_driver_path }
8
+ it { is_expected.to respond_to :p_data_file }
9
+ it { is_expected.to respond_to :p_config_file }
10
+
11
+ it 'is little endian' do
12
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
13
+ end
14
+
15
+ describe '#c_version' do
16
+ it 'is a NdrUint32' do
17
+ expect(struct.c_version).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
18
+ end
19
+ end
20
+
21
+ describe '#p_name' do
22
+ it 'is a NdrWideStringzPtr' do
23
+ expect(struct.p_name).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
24
+ end
25
+ end
26
+
27
+ describe '#p_environment' do
28
+ it 'is a NdrWideStringzPtr' do
29
+ expect(struct.p_environment).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
30
+ end
31
+ end
32
+
33
+ describe '#p_driver_path' do
34
+ it 'is a NdrWideStringzPtr' do
35
+ expect(struct.p_driver_path).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
36
+ end
37
+ end
38
+
39
+ describe '#p_data_file' do
40
+ it 'is a NdrWideStringzPtr' do
41
+ expect(struct.p_data_file).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
42
+ end
43
+ end
44
+
45
+ describe '#p_config_file' do
46
+ it 'is a NdrWideStringzPtr' do
47
+ expect(struct.p_config_file).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
48
+ end
49
+ end
50
+
51
+ it 'reads its own binary representation and outputs the same struct' do
52
+ struct = described_class.new(
53
+ c_version: 0,
54
+ p_name: 'p_name',
55
+ p_environment: 'p_environment',
56
+ p_driver_path: 'p_driver_path',
57
+ p_data_file: 'p_data_file',
58
+ p_config_file: 'p_config_file'
59
+ )
60
+ binary = struct.to_binary_s
61
+ expect(described_class.read(binary)).to eq(struct)
62
+ end
63
+ end
64
+
@@ -0,0 +1,59 @@
1
+ RSpec.describe RubySMB::Dcerpc::PrintSystem::RpcAddPrinterDriverExRequest do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :p_name }
5
+ it { is_expected.to respond_to :p_driver_container }
6
+ it { is_expected.to respond_to :dw_file_copy_flags }
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 '#p_name' do
13
+ it 'is a NdrWideStringzPtr' do
14
+ expect(packet.p_name).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
15
+ end
16
+ end
17
+
18
+ describe '#p_driver_container' do
19
+ it 'is a DriverContainer structure' do
20
+ expect(packet.p_driver_container).to be_a RubySMB::Dcerpc::PrintSystem::DriverContainer
21
+ end
22
+ end
23
+
24
+ describe '#dw_file_copy_flags' do
25
+ it 'is a NdrUint32' do
26
+ expect(packet.dw_file_copy_flags).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
27
+ end
28
+ end
29
+
30
+ describe '#initialize_instance' do
31
+ it 'sets #opnum to RPC_ADD_PRINTER_DRIVER_EX constant' do
32
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::PrintSystem::RPC_ADD_PRINTER_DRIVER_EX)
33
+ end
34
+ end
35
+
36
+ it 'reads its own binary representation and outputs the same packet' do
37
+ packet = described_class.new(
38
+ p_name: 'p_name',
39
+ p_driver_container: RubySMB::Dcerpc::PrintSystem::DriverContainer.new(
40
+ RubySMB::Dcerpc::PrintSystem::DriverContainer.new(
41
+ level: 2,
42
+ tag: 2,
43
+ driver_info: RubySMB::Dcerpc::PrintSystem::DriverInfo2.new(
44
+ c_version: 0,
45
+ p_name: 'p_name',
46
+ p_environment: 'p_environment',
47
+ p_driver_path: 'p_driver_path',
48
+ p_data_file: 'p_data_file',
49
+ p_config_file: 'p_config_file'
50
+ )
51
+ )
52
+ ),
53
+ dw_file_copy_flags: 0
54
+ )
55
+ binary = packet.to_binary_s
56
+ expect(described_class.read(binary)).to eq(packet)
57
+ end
58
+ end
59
+
@@ -0,0 +1,30 @@
1
+ RSpec.describe RubySMB::Dcerpc::PrintSystem::RpcAddPrinterDriverExResponse do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :error_status }
5
+
6
+ it 'is little endian' do
7
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
8
+ end
9
+
10
+ describe '#error_status' do
11
+ it 'is a NdrUint32' do
12
+ expect(packet.error_status).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
13
+ end
14
+ end
15
+
16
+ describe '#initialize_instance' do
17
+ it 'sets #opnum to RPC_ADD_PRINTER_DRIVER_EX constant' do
18
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::PrintSystem::RPC_ADD_PRINTER_DRIVER_EX)
19
+ end
20
+ end
21
+
22
+ it 'reads its own binary representation and outputs the same packet' do
23
+ packet = described_class.new(
24
+ error_status: 0
25
+ )
26
+ binary = packet.to_binary_s
27
+ expect(described_class.read(binary)).to eq(packet)
28
+ end
29
+ end
30
+
@@ -0,0 +1,62 @@
1
+ RSpec.describe RubySMB::Dcerpc::PrintSystem::RpcEnumPrinterDriversRequest do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :p_name }
5
+ it { is_expected.to respond_to :p_environment }
6
+ it { is_expected.to respond_to :level }
7
+ it { is_expected.to respond_to :p_drivers }
8
+ it { is_expected.to respond_to :cb_buf }
9
+
10
+ it 'is little endian' do
11
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
12
+ end
13
+
14
+ describe '#p_name' do
15
+ it 'is a NdrWideStringzPtr' do
16
+ expect(packet.p_name).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
17
+ end
18
+ end
19
+
20
+ describe '#p_environment' do
21
+ it 'is a NdrWideStringzPtr' do
22
+ expect(packet.p_environment).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
23
+ end
24
+ end
25
+
26
+ describe '#level' do
27
+ it 'is a NdrUint32' do
28
+ expect(packet.level).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
29
+ end
30
+ end
31
+
32
+ describe '#p_drivers' do
33
+ it 'is a RprnByteArrayPtr' do
34
+ expect(packet.p_drivers).to be_a RubySMB::Dcerpc::PrintSystem::RprnByteArrayPtr
35
+ end
36
+ end
37
+
38
+ describe '#cb_buf' do
39
+ it 'is a NdrUint32' do
40
+ expect(packet.cb_buf).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
41
+ end
42
+ end
43
+
44
+ describe '#initialize_instance' do
45
+ it 'sets #opnum to RPC_ENUM_PRINTER_DRIVERS constant' do
46
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::PrintSystem::RPC_ENUM_PRINTER_DRIVERS)
47
+ end
48
+ end
49
+
50
+ it 'reads its own binary representation and outputs the same packet' do
51
+ packet = described_class.new(
52
+ p_name: 'p_name',
53
+ p_environment: 'p_environment',
54
+ level: 0,
55
+ p_drivers: [0, 1, 2],
56
+ cb_buf: 0
57
+ )
58
+ binary = packet.to_binary_s
59
+ expect(described_class.read(binary)).to eq(packet)
60
+ end
61
+ end
62
+
@@ -0,0 +1,54 @@
1
+ RSpec.describe RubySMB::Dcerpc::PrintSystem::RpcEnumPrinterDriversResponse do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :p_drivers }
5
+ it { is_expected.to respond_to :pcb_needed }
6
+ it { is_expected.to respond_to :pc_returned }
7
+ it { is_expected.to respond_to :error_status }
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 '#p_drivers' do
14
+ it 'is a RprnByteArrayPtr' do
15
+ expect(packet.p_drivers).to be_a RubySMB::Dcerpc::PrintSystem::RprnByteArrayPtr
16
+ end
17
+ end
18
+
19
+ describe '#pcb_needed' do
20
+ it 'is a NdrUint32' do
21
+ expect(packet.pcb_needed).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
22
+ end
23
+ end
24
+
25
+ describe '#pc_returned' do
26
+ it 'is a NdrUint32' do
27
+ expect(packet.pc_returned).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
28
+ end
29
+ end
30
+
31
+ describe '#error_status' do
32
+ it 'is a NdrUint32' do
33
+ expect(packet.error_status).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
34
+ end
35
+ end
36
+
37
+ describe '#initialize_instance' do
38
+ it 'sets #opnum to RPC_ENUM_PRINTER_DRIVERS constant' do
39
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::PrintSystem::RPC_ENUM_PRINTER_DRIVERS)
40
+ end
41
+ end
42
+
43
+ it 'reads its own binary representation and outputs the same packet' do
44
+ packet = described_class.new(
45
+ p_drivers: [0, 1, 2],
46
+ pcb_needed: 0,
47
+ pc_returned: 0,
48
+ error_status: 0
49
+ )
50
+ binary = packet.to_binary_s
51
+ expect(described_class.read(binary)).to eq(packet)
52
+ end
53
+ end
54
+
@@ -0,0 +1,62 @@
1
+ RSpec.describe RubySMB::Dcerpc::PrintSystem::RpcGetPrinterDriverDirectoryRequest do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :p_name }
5
+ it { is_expected.to respond_to :p_environment }
6
+ it { is_expected.to respond_to :level}
7
+ it { is_expected.to respond_to :p_driver_directory }
8
+ it { is_expected.to respond_to :cb_buf }
9
+
10
+ it 'is little endian' do
11
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
12
+ end
13
+
14
+ describe '#p_name' do
15
+ it 'is a NdrWideStringzPtr' do
16
+ expect(packet.p_name).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
17
+ end
18
+ end
19
+
20
+ describe '#p_environment' do
21
+ it 'is a NdrWideStringzPtr' do
22
+ expect(packet.p_environment).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
23
+ end
24
+ end
25
+
26
+ describe '#level' do
27
+ it 'is a NdrUint32' do
28
+ expect(packet.level).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
29
+ end
30
+ end
31
+
32
+ describe '#p_driver_directory' do
33
+ it 'is a RprnByteArrayPtr' do
34
+ expect(packet.p_driver_directory).to be_a RubySMB::Dcerpc::PrintSystem::RprnByteArrayPtr
35
+ end
36
+ end
37
+
38
+ describe '#cb_buf' do
39
+ it 'is a NdrUint32' do
40
+ expect(packet.cb_buf).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
41
+ end
42
+ end
43
+
44
+ describe '#initialize_instance' do
45
+ it 'sets #opnum to RPC_GET_PRINTER_DRIVER_DIRECTORY constant' do
46
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::PrintSystem::RPC_GET_PRINTER_DRIVER_DIRECTORY)
47
+ end
48
+ end
49
+
50
+ it 'reads its own binary representation and outputs the same packet' do
51
+ packet = described_class.new(
52
+ p_name: 'p_name',
53
+ p_environment: 'p_environment',
54
+ level: 0,
55
+ p_driver_directory: [0, 1, 2],
56
+ cb_buf: 0
57
+ )
58
+ binary = packet.to_binary_s
59
+ expect(described_class.read(binary)).to eq(packet)
60
+ end
61
+ end
62
+
@@ -0,0 +1,46 @@
1
+ RSpec.describe RubySMB::Dcerpc::PrintSystem::RpcGetPrinterDriverDirectoryResponse do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :p_driver_directory }
5
+ it { is_expected.to respond_to :pcb_needed }
6
+ it { is_expected.to respond_to :error_status }
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 '#p_driver_directory' do
13
+ it 'is a RprnByteArrayPtr' do
14
+ expect(packet.p_driver_directory).to be_a RubySMB::Dcerpc::PrintSystem::RprnByteArrayPtr
15
+ end
16
+ end
17
+
18
+ describe '#pcb_needed' do
19
+ it 'is a NdrUint32' do
20
+ expect(packet.pcb_needed).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
21
+ end
22
+ end
23
+
24
+ describe '#error_status' do
25
+ it 'is a NdrUint32' do
26
+ expect(packet.error_status).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
27
+ end
28
+ end
29
+
30
+ describe '#initialize_instance' do
31
+ it 'sets #opnum to RPC_GET_PRINTER_DRIVER_DIRECTORY constant' do
32
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::PrintSystem::RPC_GET_PRINTER_DRIVER_DIRECTORY)
33
+ end
34
+ end
35
+
36
+ it 'reads its own binary representation and outputs the same packet' do
37
+ packet = described_class.new(
38
+ p_driver_directory: [0, 1, 2],
39
+ pcb_needed: 0,
40
+ error_status: 0
41
+ )
42
+ binary = packet.to_binary_s
43
+ expect(described_class.read(binary)).to eq(packet)
44
+ end
45
+ end
46
+
@@ -3,8 +3,12 @@ RSpec.describe RubySMB::Field::NtStatus do
3
3
 
4
4
  it { is_expected.to respond_to :to_nt_status }
5
5
 
6
- it 'is a Unsigned 32-bit little endian integer' do
7
- expect(nt_status).to be_a BinData::Uint32le
6
+ it 'uses an internal Unsigned 32-bit little endian integer' do
7
+ expect(nt_status.val).to be_a BinData::Uint32le
8
+ end
9
+
10
+ it 'returns an integer value' do
11
+ expect(nt_status.value).to be_a Integer
8
12
  end
9
13
 
10
14
  describe '#to_nt_status' do
@@ -13,6 +13,10 @@ RSpec.describe RubySMB::Gss::Provider::NTLM::Authenticator do
13
13
  Net::NTLM::Message::Type2.new.response(user: username, password: '', domain: domain)
14
14
  end
15
15
 
16
+ before(:each) do
17
+ allow(authenticator).to receive(:logger).and_return(Logger.new(IO::NULL))
18
+ end
19
+
16
20
  describe '#initialize' do
17
21
  it 'defaults to a null session key' do
18
22
  expect(authenticator.session_key).to be_nil
@@ -5,33 +5,24 @@ RSpec.describe RubySMB::Server::ServerClient do
5
5
  subject(:server_client) { described_class.new(server, dispatcher) }
6
6
 
7
7
  it { is_expected.to respond_to :dialect }
8
- it { is_expected.to respond_to :identity }
9
- it { is_expected.to respond_to :state }
10
- it { is_expected.to respond_to :session_key }
8
+ it { is_expected.to respond_to :session_table }
11
9
 
12
10
  describe '#disconnect!' do
13
11
  it 'closes the socket' do
12
+ expect(dispatcher.tcp_socket).to receive(:closed?).with(no_args).and_return(false)
14
13
  expect(dispatcher.tcp_socket).to receive(:close).with(no_args).and_return(nil)
15
14
  server_client.disconnect!
16
15
  end
17
16
  end
18
17
 
19
18
  describe '#initialize' do
20
- it 'starts in the negotiate state' do
21
- expect(server_client.state).to eq :negotiate
22
- end
23
-
24
19
  it 'starts without a dialect' do
25
20
  expect(server_client.dialect).to be_nil
26
21
  expect(server_client.metadialect).to be_nil
27
22
  end
28
23
 
29
- it 'starts without an identity' do
30
- expect(server_client.identity).to be_nil
31
- end
32
-
33
- it 'starts without a session_key' do
34
- expect(server_client.session_key).to be_nil
24
+ it 'starts without any sessions' do
25
+ expect(server_client.session_table).to be_empty
35
26
  end
36
27
 
37
28
  it 'creates a new authenticator instance' do
@@ -66,33 +57,30 @@ RSpec.describe RubySMB::Server::ServerClient do
66
57
  before(:each) do
67
58
  expect(server_client).to receive(:recv_packet).and_return(packet)
68
59
  # this hook should ensure that the dispatcher loop returns after processing a single request
69
- expect(dispatcher.tcp_socket).to receive(:closed?).and_return(true)
60
+ expect(dispatcher.tcp_socket).to receive(:closed?).with(no_args).and_return(true)
61
+ expect(server_client).to receive(:disconnect!).with(no_args).and_return(nil)
70
62
  end
71
63
 
72
- it 'calls #handle_negotiate when the state is negotiate' do
64
+ it 'calls #handle_negotiate when the dialect is nil' do
73
65
  expect(server_client).to receive(:handle_negotiate).with(packet).and_return(nil)
74
- server_client.instance_eval { @state = :negotiate }
75
- server_client.run
76
- end
77
-
78
- it 'calls #handle_session_setup when the state is session_setup' do
79
- expect(server_client).to receive(:handle_session_setup).with(packet).and_return(nil)
80
- server_client.instance_eval { @state = :session_setup }
66
+ server_client.instance_eval { @dialect = nil }
81
67
  server_client.run
82
68
  end
83
69
 
84
- it 'calls #authenticated when the state is authenticated' do
85
- expect(server_client).to receive(:handle_authenticated).with(packet).and_return(nil)
86
- server_client.instance_eval { @state = :authenticated }
70
+ it 'calls #handle_smb when the dialect is not nil' do
71
+ expect(server_client).to receive(:handle_smb).with(packet).and_return(nil)
72
+ server_client.instance_eval { @dialect = true }
87
73
  server_client.run
88
74
  end
89
75
  end
90
76
 
91
77
  describe '#send_packet' do
92
- let(:packet) { RubySMB::GenericPacket.new }
78
+ let(:session_id) { rand(0xffffffff) }
79
+ let(:packet) { RubySMB::SMB2::Packet::SessionSetupResponse.new(smb2_header: { session_id: session_id }) }
93
80
 
94
81
  before(:each) do
95
82
  expect(dispatcher).to receive(:send_packet).with(packet).and_return(nil)
83
+ server_client.session_table[session_id] = RubySMB::Server::Session.new(session_id)
96
84
  end
97
85
 
98
86
  it 'sends a packet to the dispatcher' do
@@ -105,40 +93,35 @@ RSpec.describe RubySMB::Server::ServerClient do
105
93
  server_client.instance_eval { @dialect = dialect }
106
94
  end
107
95
 
108
- context 'and the state is authenticated' do
96
+ context 'and the identity is anonymous' do
109
97
  before(:each) do
110
- server_client.instance_eval { @state = :authenticated }
98
+ server_client.session_table[session_id].user_id = RubySMB::Gss::Provider::IDENTITY_ANONYMOUS
111
99
  end
112
100
 
113
- context 'and the identity is anonymous' do
114
- before(:each) do
115
- server_client.instance_eval { @identity = RubySMB::Gss::Provider::IDENTITY_ANONYMOUS }
116
- end
117
-
118
- it 'does not sign packets' do
119
- expect(server_client).to_not receive(:smb2_sign)
120
- expect(server_client).to_not receive(:smb3_sign)
121
- server_client.send_packet(packet)
122
- end
101
+ it 'does not sign packets' do
102
+ expect(RubySMB::Signing).to_not receive(:smb2_sign)
103
+ expect(RubySMB::Signing).to_not receive(:smb3_sign)
104
+ server_client.send_packet(packet)
123
105
  end
106
+ end
124
107
 
125
- context 'and the identity is not anonymous' do
126
- before(:each) do
127
- server_client.instance_eval { @identity = 'WORKGROUP\RubySMB'; @session_key = Random.new.bytes(16) }
128
- end
108
+ context 'and the identity is not anonymous' do
109
+ before(:each) do
110
+ server_client.session_table[session_id].user_id = 'WORKGROUP\RubySMB'
111
+ server_client.session_table[session_id].key = Random.new.bytes(16)
112
+ end
129
113
 
130
- it 'does sign packets' do
131
- packet = RubySMB::GenericPacket.new
132
- dialect_family = RubySMB::Dialect[dialect].family
133
- if dialect_family == RubySMB::Dialect::FAMILY_SMB2
134
- expect(server_client).to receive(:smb2_sign).with(packet).and_return(packet)
135
- expect(server_client).to_not receive(:smb3_sign)
136
- elsif dialect_family == RubySMB::Dialect::FAMILY_SMB3
137
- expect(server_client).to receive(:smb3_sign).with(packet).and_return(packet)
138
- expect(server_client).to_not receive(:smb2_sign)
139
- end
140
- server_client.send_packet(packet)
114
+ it 'does sign packets' do
115
+ dialect_family = RubySMB::Dialect[dialect].family
116
+ session = server_client.session_table[session_id]
117
+ if dialect_family == RubySMB::Dialect::FAMILY_SMB2
118
+ expect(RubySMB::Signing).to receive(:smb2_sign).with(packet, session.key).and_return(packet)
119
+ expect(RubySMB::Signing).to_not receive(:smb3_sign)
120
+ elsif dialect_family == RubySMB::Dialect::FAMILY_SMB3
121
+ expect(RubySMB::Signing).to receive(:smb3_sign).with(packet, session.key, dialect, any_args).and_return(packet)
122
+ expect(RubySMB::Signing).to_not receive(:smb2_sign)
141
123
  end
124
+ server_client.send_packet(packet)
142
125
  end
143
126
  end
144
127
  end
@@ -0,0 +1,38 @@
1
+ RSpec.describe RubySMB::Server::Session do
2
+ let(:user_id) { 'WORKGROUP\RubySMB' }
3
+ subject(:session) { described_class.new(rand(0xffffffff), user_id: user_id) }
4
+
5
+ it { is_expected.to respond_to :id }
6
+ it { is_expected.to respond_to :key }
7
+ it { is_expected.to respond_to :signing_required }
8
+ it { is_expected.to respond_to :tree_connect_table }
9
+ it { is_expected.to respond_to :creation_time }
10
+
11
+ describe '#initialize' do
12
+ it 'starts with no signing required' do
13
+ expect(session.signing_required).to be_falsey
14
+ end
15
+
16
+ it 'starts with no tree connections' do
17
+ expect(session.tree_connect_table).to be_empty
18
+ end
19
+
20
+ it 'starts in the in progress state' do
21
+ expect(session.state).to be :in_progress
22
+ end
23
+ end
24
+
25
+ describe '#is_anonymous' do
26
+ it 'is false' do
27
+ expect(session.is_anonymous).to be_falsey
28
+ end
29
+
30
+ context 'when the identity is set to anonymous' do
31
+ let(:user_id) { RubySMB::Gss::Provider::IDENTITY_ANONYMOUS }
32
+
33
+ it 'is true' do
34
+ expect(session.is_anonymous).to be_truthy
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,61 @@
1
+ RSpec.describe RubySMB::Server::Share::Provider::Disk do
2
+ let(:name) { 'share' }
3
+ let(:path) { Dir.getwd }
4
+ subject(:share_provider) { described_class.new(name, path) }
5
+
6
+ it { is_expected.to respond_to :name }
7
+ it { is_expected.to respond_to :path }
8
+ it { is_expected.to respond_to :type }
9
+
10
+ describe '#TYPE' do
11
+ it 'is TYPE_DISK' do
12
+ expect(described_class::TYPE).to eq RubySMB::Server::Share::TYPE_DISK
13
+ end
14
+ end
15
+
16
+ describe '#initialize' do
17
+ it 'sets the name' do
18
+ expect(share_provider.name).to eq name
19
+ end
20
+
21
+ it 'sets the path' do
22
+ expect(share_provider.path).to be_a Pathname
23
+ expect(share_provider.path).to eq Pathname.new(path)
24
+ end
25
+
26
+ it 'sets the type correctly' do
27
+ expect(share_provider.type).to eq RubySMB::Server::Share::TYPE_DISK
28
+ end
29
+
30
+ it 'raises an ArgumentError for an invalid path' do
31
+ # __FILE__ is not a directory so it's invalid
32
+ expect { described_class.new(name, __FILE__) }.to raise_error(ArgumentError)
33
+ end
34
+ end
35
+ end
36
+
37
+ RSpec.describe RubySMB::Server::Share::Provider::Disk::Processor do
38
+ let(:session) { RubySMB::Server::Session.new(rand(0xffffffff)) }
39
+ let(:share_provider) { RubySMB::Server::Share::Provider::Disk.new('share', Dir.getwd) }
40
+ subject(:share_processor) { described_class.new(share_provider, nil, session) }
41
+
42
+ it { is_expected.to respond_to :provider }
43
+
44
+ describe '#maximal_access' do
45
+ # no path specified should be the root of the share
46
+ context 'with no path specified' do
47
+ let(:maximal_access) { share_processor.maximal_access }
48
+ it 'is a FileAccessMask' do
49
+ expect(maximal_access).to be_a RubySMB::SMB2::BitField::FileAccessMask
50
+ end
51
+
52
+ it 'marks the data as readable' do
53
+ expect(maximal_access.read_data).to eq 1
54
+ end
55
+
56
+ it 'marks the data attributes as readable' do
57
+ expect(maximal_access.read_attr).to eq 1
58
+ end
59
+ end
60
+ end
61
+ end