ruby_smb 3.0.0 → 3.0.4

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 +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 +16 -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/client_spec.rb +10 -0
  73. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_request_spec.rb +30 -0
  74. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_response_spec.rb +30 -0
  75. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_request_spec.rb +38 -0
  76. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_response_spec.rb +38 -0
  77. data/spec/lib/ruby_smb/dcerpc/print_system/driver_container_spec.rb +41 -0
  78. data/spec/lib/ruby_smb/dcerpc/print_system/driver_info2_spec.rb +64 -0
  79. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_request_spec.rb +59 -0
  80. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_response_spec.rb +30 -0
  81. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_request_spec.rb +62 -0
  82. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_response_spec.rb +54 -0
  83. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_request_spec.rb +62 -0
  84. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_response_spec.rb +46 -0
  85. data/spec/lib/ruby_smb/field/nt_status_spec.rb +6 -2
  86. data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +4 -0
  87. data/spec/lib/ruby_smb/server/server_client_spec.rb +36 -53
  88. data/spec/lib/ruby_smb/server/session_spec.rb +38 -0
  89. data/spec/lib/ruby_smb/server/share/provider/disk_spec.rb +61 -0
  90. data/spec/lib/ruby_smb/server/share/provider/pipe_spec.rb +31 -0
  91. data/spec/lib/ruby_smb/server/share/provider_spec.rb +13 -0
  92. data/spec/lib/ruby_smb/smb1/tree_spec.rb +3 -3
  93. data/spec/lib/ruby_smb/smb2/bit_field/header_flags_spec.rb +8 -2
  94. data/spec/lib/ruby_smb/smb2/{create_context_spec.rb → create_context/create_context_request_spec.rb} +1 -1
  95. data/spec/lib/ruby_smb/smb2/packet/create_request_spec.rb +5 -5
  96. data/spec/lib/ruby_smb/smb2/packet/create_response_spec.rb +9 -5
  97. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +3 -2
  98. data/spec/lib/ruby_smb/smb2/tree_spec.rb +3 -3
  99. data.tar.gz.sig +0 -0
  100. metadata +71 -7
  101. metadata.gz.sig +0 -0
  102. 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