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,23 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module PrintSystem
4
+
5
+ # [3.1.4.4.2 RpcEnumPrinterDrivers (Opnum 10)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/857d00ac-3682-4a0d-86ca-3d3c372e5e4a)
6
+ class RpcEnumPrinterDriversResponse < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ def initialize_instance
12
+ super
13
+ @opnum = RPC_ENUM_PRINTER_DRIVERS
14
+ end
15
+
16
+ rprn_byte_array_ptr :p_drivers
17
+ ndr_uint32 :pcb_needed
18
+ ndr_uint32 :pc_returned
19
+ ndr_uint32 :error_status
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module PrintSystem
4
+
5
+ # [3.1.4.4.4 RpcGetPrinterDriverDirectory (Opnum 12)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/9df11cf4-4098-4852-ad72-d1f75a82bffe)
6
+ class RpcGetPrinterDriverDirectoryRequest < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ def initialize_instance
12
+ super
13
+ @opnum = RPC_GET_PRINTER_DRIVER_DIRECTORY
14
+ end
15
+
16
+ ndr_wide_stringz_ptr :p_name
17
+ ndr_wide_stringz_ptr :p_environment
18
+ ndr_uint32 :level
19
+ rprn_byte_array_ptr :p_driver_directory
20
+ ndr_uint32 :cb_buf
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module PrintSystem
4
+
5
+ # [3.1.4.4.4 RpcGetPrinterDriverDirectory (Opnum 12)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/9df11cf4-4098-4852-ad72-d1f75a82bffe)
6
+ class RpcGetPrinterDriverDirectoryResponse < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ def initialize_instance
12
+ super
13
+ @opnum = RPC_GET_PRINTER_DRIVER_DIRECTORY
14
+ end
15
+
16
+ rprn_byte_array_ptr :p_driver_directory
17
+ ndr_uint32 :pcb_needed
18
+ ndr_uint32 :error_status
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,69 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module PrintSystem
4
+
5
+ # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/848b8334-134a-4d02-aea4-03b673d6c515
6
+ UUID = '12345678-1234-abcd-ef00-0123456789ab'.freeze
7
+ VER_MAJOR = 1
8
+ VER_MINOR = 0
9
+
10
+ # Operation numbers
11
+ RPC_ENUM_PRINTER_DRIVERS = 10
12
+ RPC_GET_PRINTER_DRIVER_DIRECTORY = 12
13
+ RPC_ADD_PRINTER_DRIVER_EX = 89
14
+
15
+ # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/b96cc497-59e5-4510-ab04-5484993b259b
16
+ APD_STRICT_UPGRADE = 0x00000001
17
+ APD_STRICT_DOWNGRADE = 0x00000002
18
+ APD_COPY_ALL_FILES = 0x00000004
19
+ APD_COPY_NEW_FILES = 0x00000008
20
+ APD_COPY_FROM_DIRECTORY = 0x00000010
21
+ APD_DONT_COPY_FILES_TO_CLUSTER = 0x00001000
22
+ APD_COPY_TO_ALL_SPOOLERS = 0x00002000
23
+ APD_INSTALL_WARNED_DRIVER = 0x00008000
24
+ APD_RETURN_BLOCKING_STATUS_CODE = 0x00010000
25
+
26
+ # [2.2.1.5.2 DRIVER_INFO_2](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/39bbfc30-8768-4cd4-9930-434857e2c2a2)
27
+ class DriverInfo2 < RubySMB::Dcerpc::Ndr::NdrStruct
28
+ default_parameter byte_align: 4
29
+ endian :little
30
+
31
+ ndr_uint32 :c_version
32
+ ndr_wide_stringz_ptr :p_name
33
+ ndr_wide_stringz_ptr :p_environment
34
+ ndr_wide_stringz_ptr :p_driver_path
35
+ ndr_wide_stringz_ptr :p_data_file
36
+ ndr_wide_stringz_ptr :p_config_file
37
+ end
38
+
39
+ class PDriverInfo2 < DriverInfo2
40
+ extend RubySMB::Dcerpc::Ndr::PointerClassPlugin
41
+ end
42
+
43
+ # [2.2.1.2.3 DRIVER_CONTAINER](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/3a3f9cf7-8ec4-4921-b1f6-86cf8d139bc2)
44
+ class DriverContainer < RubySMB::Dcerpc::Ndr::NdrStruct
45
+ default_parameter byte_align: 4
46
+ endian :little
47
+
48
+ ndr_uint32 :level, check_value: -> { [2].include?(value) }
49
+ ndr_uint32 :tag
50
+ choice :driver_info, selection: :level, byte_align: 4 do
51
+ p_driver_info2 2
52
+ end
53
+ end
54
+
55
+ # for RpcEnumPrinterDrivers and RpcGetPrinterDriverDirectory `BYTE*` fields
56
+ class RprnByteArrayPtr < RubySMB::Dcerpc::Ndr::NdrConfArray
57
+ default_parameters type: :ndr_uint8
58
+ extend RubySMB::Dcerpc::Ndr::PointerClassPlugin
59
+ end
60
+
61
+ require 'ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_request'
62
+ require 'ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_response'
63
+ require 'ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_request'
64
+ require 'ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_response'
65
+ require 'ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_request'
66
+ require 'ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_response'
67
+ end
68
+ end
69
+ end
@@ -50,8 +50,8 @@ module RubySMB
50
50
  require 'ruby_smb/dcerpc/rpc_auth3'
51
51
  require 'ruby_smb/dcerpc/bind'
52
52
  require 'ruby_smb/dcerpc/bind_ack'
53
-
54
-
53
+ require 'ruby_smb/dcerpc/print_system'
54
+ require 'ruby_smb/dcerpc/encrypting_file_system'
55
55
 
56
56
  # Bind to the remote server interface endpoint.
57
57
  #
@@ -4,7 +4,26 @@ module RubySMB
4
4
  module Field
5
5
  # Represents an NTStatus code as defined in
6
6
  # [2.3.1 NTSTATUS values](https://msdn.microsoft.com/en-us/library/cc704588.aspx)
7
- class NtStatus < BinData::Uint32le
7
+ class NtStatus < BinData::Primitive
8
+ endian :little
9
+ uint32 :val
10
+
11
+ def get
12
+ val.to_i
13
+ end
14
+
15
+ def set(value)
16
+ case value
17
+ when WindowsError::ErrorCode
18
+ set(value.value)
19
+ when Integer
20
+ self.val = value
21
+ else
22
+ self.val = value.to_i
23
+ end
24
+ val
25
+ end
26
+
8
27
  # Returns a meaningful error code parsed from the numeric value
9
28
  #
10
29
  # @return [WindowsError::ErrorCode] the ErrorCode object for this code
@@ -0,0 +1,14 @@
1
+ module RubySMB
2
+ module Fscc
3
+ module FileInformation
4
+ # The FileEaInformation Class as defined in
5
+ # [2.4.12 FileEaInformation](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/db6cf109-ead8-441a-b29e-cb2032778b0f)
6
+ class FileEaInformation < BinData::Record
7
+ CLASS_LEVEL = FileInformation::FILE_EA_INFORMATION
8
+
9
+ endian :little
10
+ uint32 :ea_size, label: 'Extended Attributes Size'
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ module RubySMB
2
+ module Fscc
3
+ module FileInformation
4
+ # The FileNetworkOpenInformation Class as defined in
5
+ # [2.4.29 FileNetworkOpenInformation](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/26d261db-58d1-4513-a548-074448cbb146)
6
+ class FileNetworkOpenInformation < BinData::Record
7
+ CLASS_LEVEL = FileInformation::FILE_NETWORK_OPEN_INFORMATION
8
+
9
+ endian :little
10
+
11
+ file_time :create_time, label: 'Create Time'
12
+ file_time :last_access, label: 'Last Accessed Time'
13
+ file_time :last_write, label: 'Last Write Time'
14
+ file_time :last_change, label: 'Last Modified Time'
15
+ int64 :allocation_size, label: 'Allocated Size'
16
+ int64 :end_of_file, label: 'End of File'
17
+ file_attributes :file_attributes, label: 'File Attributes'
18
+ uint32 :reserved, label: 'Reserved Space'
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ module RubySMB
2
+ module Fscc
3
+ module FileInformation
4
+ # The FileStreamInformation
5
+ # [2.4.43 FileStreamInformation](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/f8762be6-3ab9-411e-a7d6-5cc68f70c78d)
6
+ class FileStreamInformation < BinData::Record
7
+ endian :little
8
+ uint32 :next_entry_offset, label: 'Next Entry Offset'
9
+ uint32 :stream_name_length, label: 'Stream Name Length', initial_value: -> { stream_name.do_num_bytes }
10
+ int64 :stream_size, label: 'Stream Size'
11
+ int64 :stream_allocation_size, label: 'Stream Allocation Size'
12
+ string16 :stream_name, label: 'Stream Name', read_length: -> { stream_name_length }
13
+ end
14
+ end
15
+ end
16
+ end
@@ -17,6 +17,10 @@ module RubySMB
17
17
  # contents of a directory.
18
18
  FILE_BOTH_DIRECTORY_INFORMATION = 0x03
19
19
 
20
+ # Information class used to query for the size of the extended attributes
21
+ # (EA) for a file.
22
+ FILE_EA_INFORMATION = 0x07
23
+
20
24
  # Information class used to rename a file.
21
25
  FILE_RENAME_INFORMATION = 0x0A
22
26
 
@@ -27,6 +31,14 @@ module RubySMB
27
31
  # Information class used to mark a file for deletion.
28
32
  FILE_DISPOSITION_INFORMATION = 0x0D
29
33
 
34
+ # Information class used to enumerate the data streams of a file or a
35
+ # directory.
36
+ FILE_STREAM_INFORMATION = 0x16
37
+
38
+ # This information class is used to query for information that is commonly
39
+ # needed when a file is opened across a network.
40
+ FILE_NETWORK_OPEN_INFORMATION = 0x22
41
+
30
42
  # Information class used in directory enumeration to return detailed
31
43
  # information (with extended attributes size, short names and file ID)
32
44
  # about the contents of a directory.
@@ -38,6 +50,13 @@ module RubySMB
38
50
  FILE_ID_FULL_DIRECTORY_INFORMATION = 0x26
39
51
 
40
52
 
53
+ # This information class is used to query the normalized name of a file. A
54
+ # normalized name is an absolute pathname where each short name component
55
+ # has been replaced with the corresponding long name component, and each
56
+ # name component uses the exact letter casing stored on disk.
57
+ FILE_NORMALIZED_NAME_INFORMATION = 0x30
58
+
59
+
41
60
  # These Information Classes can be used by SMB1 using the pass-through
42
61
  # Information Levels when available on the server (CAP_INFOLEVEL_PASSTHRU
43
62
  # capability flag in an SMB_COM_NEGOTIATE server response). The constant
@@ -46,6 +65,13 @@ module RubySMB
46
65
  # [2.2.2.3.5 Pass-through Information Level Codes](https://msdn.microsoft.com/en-us/library/ff470158.aspx)
47
66
  SMB_INFO_PASSTHROUGH = 0x03e8
48
67
 
68
+ # The FILE_NAME_INFORMATION type as defined in
69
+ # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/20406fb1-605f-4629-ba9a-c67ee25f23d2
70
+ class FileNameInformation < BinData::Record
71
+ endian :little
72
+ uint32 :file_name_length, label: 'File Name Length', initial_value: -> { file_name.do_num_bytes }
73
+ string16 :file_name, label: 'File Name', read_length: -> { file_name_length }
74
+ end
49
75
 
50
76
  require 'ruby_smb/fscc/file_information/file_directory_information'
51
77
  require 'ruby_smb/fscc/file_information/file_full_directory_information'
@@ -55,6 +81,9 @@ module RubySMB
55
81
  require 'ruby_smb/fscc/file_information/file_id_both_directory_information'
56
82
  require 'ruby_smb/fscc/file_information/file_names_information'
57
83
  require 'ruby_smb/fscc/file_information/file_rename_information'
84
+ require 'ruby_smb/fscc/file_information/file_network_open_information'
85
+ require 'ruby_smb/fscc/file_information/file_ea_information'
86
+ require 'ruby_smb/fscc/file_information/file_stream_information'
58
87
  end
59
88
  end
60
89
  end
@@ -0,0 +1,46 @@
1
+ module RubySMB
2
+ module Fscc
3
+ module FileSystemInformation
4
+ # The FileFsAttributeInformation
5
+ # [2.5.1 FileFsAttributeInformation](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/ebc7e6e5-4650-4e54-b17c-cf60f6fbeeaa)
6
+ class FileFsAttributeInformation < BinData::Record
7
+ CLASS_LEVEL = FileSystemInformation::FILE_FS_ATTRIBUTE_INFORMATION
8
+
9
+ endian :little
10
+ struct :file_system_attributes, label: 'File System Attributes' do
11
+ bit1 :file_supports_reparse_points, label: 'FS Supports Reparse Points'
12
+ bit1 :file_supports_sparse_files, label: 'FS Supports Sparse Files'
13
+ bit1 :file_volume_quotas, label: 'FS Supports Quotas'
14
+ bit1 :file_file_compression, label: 'FS Supports File Compression'
15
+ bit1 :file_persistent_acls, label: 'FS Supports Persistent ACLs'
16
+ bit1 :file_unicode_on_disk, label: 'FS Supports Unicode Names'
17
+ bit1 :file_case_preserved_names, label: 'FS Preserves Name Casing'
18
+ bit1 :file_case_sensitive_search, label: 'FS Supports Case-Sensitive Searching'
19
+ # byte boundary
20
+ bit1 :file_volume_is_compressed, label: 'FS Is Compressed'
21
+ bit6 :reserved0
22
+ bit1 :file_supports_remote_storage, label: 'FS Supports Remote Storage'
23
+ # byte boundary
24
+ bit1 :file_supports_extended_attributes, label: 'FS Supports Persistent Extended Attributes'
25
+ bit1 :file_supports_hard_links, label: 'FS Supports Hard Links'
26
+ bit1 :file_supports_transactions, label: 'FS Supports Transactions'
27
+ bit1 :file_sequential_write_once, label: 'FS Is Write Once'
28
+ bit1 :file_read_only_volume, label: 'FS Is Read-Only'
29
+ bit1 :file_named_streams, label: 'FS Supports Named Streams'
30
+ bit1 :file_supports_encryption, label: 'FS Supports Encryption'
31
+ bit1 :file_supports_object_ids, label: 'FS Supports Object IDs'
32
+ # byte boundary
33
+ bit3 :reserved1
34
+ bit1 :file_supports_sparse_vdl, label: 'FS Supports Sparse VDL'
35
+ bit1 :file_supports_block_refcounting, label: 'FS Supports Block Reference Counting'
36
+ bit1 :file_supports_integrity_streams, label: 'FS Supports Integrity Streams'
37
+ bit1 :file_supports_usn_journal, label: 'FS Supports USN Change Journal'
38
+ bit1 :file_supports_open_by_file_id, label: 'FS Supports Open By File ID'
39
+ end
40
+ int32 :maximum_component_name_length, label: 'Maximum Component Name Length'
41
+ uint32 :file_system_name_length, label: 'File System Name Length', initial_value: -> { file_system_name.do_num_bytes }
42
+ string16 :file_system_name, label: 'File System Name', read_length: -> { file_system_name_length }
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,19 @@
1
+ module RubySMB
2
+ module Fscc
3
+ module FileSystemInformation
4
+ # The FileFsVolumeInformation
5
+ # [2.5.9 FileFsVolumeInformation](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/bf691378-c34e-4a13-976e-404ea1a87738)
6
+ class FileFsVolumeInformation < BinData::Record
7
+ CLASS_LEVEL = FileSystemInformation::FILE_FS_VOLUME_INFORMATION
8
+
9
+ endian :little
10
+ file_time :volume_creation_time, label: 'Volume Creation Time'
11
+ uint32 :volume_serial_number, label: 'Volume Serial Number'
12
+ uint32 :volume_label_length, label: 'Volume Label Length', initial_value: -> { volume_label.do_num_bytes }
13
+ uint8 :supports_objects, label: 'Supports Objects'
14
+ uint8 :reserved, label: 'Reserved'
15
+ string16 :volume_label, label: 'Volume Label', read_length: -> { volume_label_length }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ module RubySMB
2
+ module Fscc
3
+ # Namespace and constant values for File System Information Classes, as defined in
4
+ # [2.5 File System Information Classes](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/ee12042a-9352-46e3-9f67-c094b75fe6c3)
5
+ module FileSystemInformation
6
+ FILE_FS_VOLUME_INFORMATION = 1
7
+ FILE_FS_LABEL_INFORMATION = 2
8
+ FILE_FS_SIZE_INFORMATION = 3
9
+ FILE_FS_DEVICE_INFORMATION = 4
10
+ FILE_FS_ATTRIBUTE_INFORMATION = 5
11
+ FILE_FS_CONTROL_INFORMATION = 6
12
+ FILE_FS_FULL_SIZE_INFORMATION = 7
13
+ FILE_FS_OBJECT_ID_INFORMATION = 8
14
+ FILE_FS_DRIVER_PATH_INFORMATION = 9
15
+ FILE_FS_VOLUME_FLAGS_INFORMATION = 10
16
+ FILE_FS_SECTOR_SIZE_INFORMATION = 11
17
+
18
+ require 'ruby_smb/fscc/file_system_information/file_fs_attribute_information'
19
+ require 'ruby_smb/fscc/file_system_information/file_fs_volume_information'
20
+ end
21
+ end
22
+ end
data/lib/ruby_smb/fscc.rb CHANGED
@@ -7,6 +7,7 @@ module RubySMB
7
7
  require 'ruby_smb/fscc/file_full_ea_info'
8
8
  require 'ruby_smb/fscc/ea_info_array'
9
9
  require 'ruby_smb/fscc/file_information'
10
+ require 'ruby_smb/fscc/file_system_information'
10
11
  require 'ruby_smb/fscc/control_codes'
11
12
  end
12
13
  end
@@ -43,6 +43,8 @@ module RubySMB
43
43
  begin
44
44
  super(val)
45
45
  rescue IOError => e
46
+ # $stderr.puts "#{e.class}: #{e.message}"
47
+ # $stderr.puts e.backtrace.join("\n")
46
48
  case self.to_s
47
49
  when /EmptyPacket|ErrorPacket/
48
50
  raise RubySMB::Error::InvalidPacket, 'Not a valid SMB packet'
@@ -68,6 +70,10 @@ module RubySMB
68
70
  end
69
71
  end
70
72
 
73
+ def self.from_hex(val)
74
+ self.read(val.scan(/../).map { |x| x.hex.chr }.join)
75
+ end
76
+
71
77
  def status_code
72
78
  value = -1
73
79
  smb_version = packet_smb_version
@@ -17,6 +17,10 @@ module RubySMB
17
17
  reset!
18
18
  end
19
19
 
20
+ def logger
21
+ @server_client.logger
22
+ end
23
+
20
24
  #
21
25
  # Process a GSS authentication buffer. If no buffer is specified, the request is assumed to be the first in
22
26
  # the negotiation sequence.
@@ -50,7 +50,8 @@ module RubySMB
50
50
 
51
51
  begin
52
52
  gss_api = OpenSSL::ASN1.decode(request_buffer)
53
- rescue OpenSSL::ASN1::ASN1Error
53
+ rescue OpenSSL::ASN1::ASN1Error => e
54
+ logger.error("Failed to parse the ASN1-encoded authentication request (#{e.message})")
54
55
  return
55
56
  end
56
57
 
@@ -114,11 +115,16 @@ module RubySMB
114
115
  return WindowsError::NTStatus::STATUS_LOGON_FAILURE
115
116
  end
116
117
 
118
+ dbg_string = "#{type3_msg.domain.encode(''.encoding)}\\#{type3_msg.user.encode(''.encoding)}"
119
+ logger.debug("NTLM authentication request received for #{dbg_string}")
117
120
  account = @provider.get_account(
118
121
  type3_msg.user,
119
122
  domain: type3_msg.domain
120
123
  )
121
- return WindowsError::NTStatus::STATUS_LOGON_FAILURE if account.nil?
124
+ if account.nil?
125
+ logger.info("NTLM authentication request failed for #{dbg_string} (no account)")
126
+ return WindowsError::NTStatus::STATUS_LOGON_FAILURE
127
+ end
122
128
 
123
129
  matches = false
124
130
  case type3_msg.ntlm_version
@@ -159,8 +165,12 @@ module RubySMB
159
165
  raise NotImplementedError, "authentication via ntlm version #{type3_msg.ntlm_version} is not supported"
160
166
  end
161
167
 
162
- return WindowsError::NTStatus::STATUS_LOGON_FAILURE unless matches
168
+ unless matches
169
+ logger.info("NTLM authentication request failed for #{dbg_string} (bad password)")
170
+ return WindowsError::NTStatus::STATUS_LOGON_FAILURE
171
+ end
163
172
 
173
+ logger.info("NTLM authentication request succeeded for #{dbg_string}")
164
174
  WindowsError::NTStatus::STATUS_SUCCESS
165
175
  end
166
176
 
@@ -73,7 +73,6 @@ module RubySMB
73
73
  response.data_block.server_guid = @server.guid
74
74
  response.data_block.security_blob = process_gss.buffer
75
75
 
76
- @state = :session_setup
77
76
  @dialect = dialect
78
77
  response
79
78
  end
@@ -146,7 +145,6 @@ module RubySMB
146
145
  update_preauth_hash(response)
147
146
  end
148
147
 
149
- @state = :session_setup
150
148
  @dialect = dialect
151
149
  response
152
150
  end
@@ -2,39 +2,26 @@ module RubySMB
2
2
  class Server
3
3
  class ServerClient
4
4
  module SessionSetup
5
- #
6
- # Setup a new session based on the negotiated dialect. Once session setup is complete, the state will be updated
7
- # to :authenticated.
8
- #
9
- # @param [String] raw_request the session setup request to process
10
- def handle_session_setup(raw_request)
11
- response = nil
12
-
13
- case metadialect.order
14
- when Dialect::ORDER_SMB1
15
- request = SMB1::Packet::SessionSetupRequest.read(raw_request)
16
- response = do_session_setup_smb1(request)
17
- when Dialect::ORDER_SMB2
18
- request = SMB2::Packet::SessionSetupRequest.read(raw_request)
19
- response = do_session_setup_smb2(request)
20
- end
21
-
22
- if response.nil?
23
- disconnect!
5
+ def do_session_setup_smb1(request, session)
6
+ session_id = request.smb_header.uid
7
+ if session_id == 0
8
+ session_id = rand(1..0x10000)
9
+ session = @session_table[session_id] = Server::Session.new(session_id)
24
10
  else
25
- send_packet(response)
11
+ session = @session_table[session_id]
12
+ if session.nil?
13
+ response = SMB1::Packet::EmptyPacket.new
14
+ response.smb_header.nt_status = SMBError::STATUS_SMB_BAD_UID
15
+ return response
16
+ end
26
17
  end
27
18
 
28
- nil
29
- end
30
-
31
- def do_session_setup_smb1(request)
32
19
  gss_result = process_gss(request.data_block.security_blob)
33
20
  return if gss_result.nil?
34
21
 
35
22
  response = SMB1::Packet::SessionSetupResponse.new
36
23
  response.smb_header.pid_low = request.smb_header.pid_low
37
- response.smb_header.uid = rand(0x10000)
24
+ response.smb_header.uid = session_id
38
25
  response.smb_header.mid = request.smb_header.mid
39
26
  response.smb_header.nt_status = gss_result.nt_status.value
40
27
  response.smb_header.flags.reply = true
@@ -46,14 +33,28 @@ module RubySMB
46
33
  end
47
34
 
48
35
  if gss_result.nt_status == WindowsError::NTStatus::STATUS_SUCCESS
49
- @state = :authenticated
50
- @identity = gss_result.identity
36
+ session.state = :valid
37
+ session.user_id = gss_result.identity
38
+ session.key = @gss_authenticator.session_key
51
39
  end
52
40
 
53
41
  response
54
42
  end
55
43
 
56
- def do_session_setup_smb2(request)
44
+ def do_session_setup_smb2(request, session)
45
+ session_id = request.smb2_header.session_id
46
+ if session_id == 0
47
+ session_id = rand(1..0xfffffffe)
48
+ session = @session_table[session_id] = Session.new(session_id)
49
+ else
50
+ session = @session_table[session_id]
51
+ if session.nil?
52
+ response = SMB2::Packet::ErrorPacket.new
53
+ response.smb2_header.nt_status = WindowsError::NTStatus::STATUS_USER_SESSION_DELETED
54
+ return response
55
+ end
56
+ end
57
+
57
58
  gss_result = process_gss(request.buffer)
58
59
  return if gss_result.nil?
59
60
 
@@ -61,20 +62,30 @@ module RubySMB
61
62
  response.smb2_header.nt_status = gss_result.nt_status.value
62
63
  response.smb2_header.credits = 1
63
64
  response.smb2_header.message_id = request.smb2_header.message_id
64
- response.smb2_header.session_id = @session_id = @session_id || SecureRandom.random_bytes(4).unpack1('V')
65
+ response.smb2_header.session_id = session_id
65
66
  response.buffer = gss_result.buffer
66
67
 
67
68
  update_preauth_hash(request) if @dialect == '0x0311'
68
69
  if gss_result.nt_status == WindowsError::NTStatus::STATUS_SUCCESS
69
- @state = :authenticated
70
- @identity = gss_result.identity
71
- @session_key = @gss_authenticator.session_key
70
+ response.smb2_header.credits = 32
71
+ session.state = :valid
72
+ session.user_id = gss_result.identity
73
+ session.key = @gss_authenticator.session_key
74
+ session.signing_required = request.security_mode.signing_required == 1
72
75
  elsif gss_result.nt_status == WindowsError::NTStatus::STATUS_MORE_PROCESSING_REQUIRED && @dialect == '0x0311'
73
76
  update_preauth_hash(response)
74
77
  end
75
78
 
76
79
  response
77
80
  end
81
+
82
+ def do_logoff_smb2(request, session)
83
+ session = @session_table.delete(session.id)
84
+ session.logoff!
85
+
86
+ response = SMB2::Packet::LogoffResponse.new
87
+ response
88
+ end
78
89
  end
79
90
  end
80
91
  end
@@ -0,0 +1,28 @@
1
+ module RubySMB
2
+ class Server
3
+ class ServerClient
4
+ module ShareIO
5
+ def proxy_share_io_smb2(request, session)
6
+ # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/9a639360-87be-4d49-a1dd-4c6be0c020bd
7
+ share_processor = session.tree_connect_table[request.smb2_header.tree_id]
8
+ if share_processor.nil?
9
+ response = SMB2::Packet::ErrorPacket.new
10
+ response.smb2_header.nt_status = WindowsError::NTStatus::STATUS_NETWORK_NAME_DELETED
11
+ return response
12
+ end
13
+
14
+ logger.debug("Received #{SMB2::Commands.name(request.smb2_header.command)} request for share: #{share_processor.provider.name}")
15
+ share_processor.send(__callee__, request)
16
+ end
17
+
18
+ alias :do_close_smb2 :proxy_share_io_smb2
19
+ alias :do_create_smb2 :proxy_share_io_smb2
20
+ alias :do_ioctl_smb2 :proxy_share_io_smb2
21
+ alias :do_query_directory_smb2 :proxy_share_io_smb2
22
+ alias :do_query_info_smb2 :proxy_share_io_smb2
23
+ alias :do_read_smb2 :proxy_share_io_smb2
24
+
25
+ end
26
+ end
27
+ end
28
+ end