ruby_smb 0.0.8 → 0.0.9

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 (60) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/examples/tree_connect.rb +27 -0
  5. data/lib/ruby_smb/client.rb +25 -2
  6. data/lib/ruby_smb/client/authentication.rb +5 -6
  7. data/lib/ruby_smb/client/negotiation.rb +2 -3
  8. data/lib/ruby_smb/client/signing.rb +6 -2
  9. data/lib/ruby_smb/client/tree_connect.rb +86 -0
  10. data/lib/ruby_smb/generic_packet.rb +1 -1
  11. data/lib/ruby_smb/smb1.rb +1 -1
  12. data/lib/ruby_smb/smb1/bit_field.rb +4 -0
  13. data/lib/ruby_smb/smb1/bit_field/directory_access_mask.rb +38 -0
  14. data/lib/ruby_smb/smb1/bit_field/file_access_mask.rb +38 -0
  15. data/lib/ruby_smb/smb1/bit_field/optional_support.rb +19 -0
  16. data/lib/ruby_smb/smb1/bit_field/tree_connect_flags.rb +18 -0
  17. data/lib/ruby_smb/smb1/commands.rb +2 -0
  18. data/lib/ruby_smb/smb1/packet.rb +4 -0
  19. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +34 -0
  20. data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +74 -0
  21. data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +29 -0
  22. data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +30 -0
  23. data/lib/ruby_smb/smb1/tree.rb +55 -0
  24. data/lib/ruby_smb/smb2.rb +1 -0
  25. data/lib/ruby_smb/smb2/bit_field.rb +4 -0
  26. data/lib/ruby_smb/smb2/bit_field/directory_access_mask.rb +38 -0
  27. data/lib/ruby_smb/smb2/bit_field/file_access_mask.rb +38 -0
  28. data/lib/ruby_smb/smb2/bit_field/share_capabailities.rb +21 -0
  29. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +75 -0
  30. data/lib/ruby_smb/smb2/packet.rb +5 -0
  31. data/lib/ruby_smb/smb2/packet/error_packet.rb +15 -0
  32. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +27 -0
  33. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +50 -0
  34. data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +21 -0
  35. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +22 -0
  36. data/lib/ruby_smb/smb2/smb2_header.rb +3 -3
  37. data/lib/ruby_smb/smb2/tree.rb +51 -0
  38. data/lib/ruby_smb/version.rb +1 -1
  39. data/ruby_smb.gemspec +1 -1
  40. data/spec/lib/ruby_smb/client_spec.rb +114 -4
  41. data/spec/lib/ruby_smb/smb1/bit_field/directory_access_mask_spec.rb +190 -0
  42. data/spec/lib/ruby_smb/smb1/bit_field/file_access_mask_spec.rb +190 -0
  43. data/spec/lib/ruby_smb/smb1/bit_field/optional_support_spec.rb +52 -0
  44. data/spec/lib/ruby_smb/smb1/bit_field/tree_connect_flags_spec.rb +37 -0
  45. data/spec/lib/ruby_smb/smb1/packet/tree_connect_request_spec.rb +53 -0
  46. data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +86 -0
  47. data/spec/lib/ruby_smb/smb1/packet/tree_disconnect_request_spec.rb +40 -0
  48. data/spec/lib/ruby_smb/smb1/packet/tree_disconnect_response_spec.rb +40 -0
  49. data/spec/lib/ruby_smb/smb1/tree_spec.rb +55 -0
  50. data/spec/lib/ruby_smb/smb2/bit_field/directory_access_mask_spec.rb +190 -0
  51. data/spec/lib/ruby_smb/smb2/bit_field/file_access_mask_spec.rb +190 -0
  52. data/spec/lib/ruby_smb/smb2/bit_field/share_capabilities_spec.rb +54 -0
  53. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +184 -0
  54. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +49 -0
  55. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +57 -0
  56. data/spec/lib/ruby_smb/smb2/packet/tree_disconnect_request_spec.rb +30 -0
  57. data/spec/lib/ruby_smb/smb2/packet/tree_disconnect_response_spec.rb +30 -0
  58. data/spec/lib/ruby_smb/smb2/tree_spec.rb +54 -0
  59. metadata +63 -6
  60. metadata.gz.sig +0 -0
@@ -0,0 +1,74 @@
1
+ module RubySMB
2
+ module SMB1
3
+ module Packet
4
+
5
+ # A SMB1 TreeConnect Response Packet as defined in
6
+ # [2.2.4.7.2 Server Response Extensions](https://msdn.microsoft.com/en-us/library/cc246331.aspx)
7
+ class TreeConnectResponse < RubySMB::GenericPacket
8
+
9
+ # A SMB1 Parameter Block as defined by the {SessionSetupResponse}
10
+ class ParameterBlock < RubySMB::SMB1::ParameterBlock
11
+ and_x_block :andx_block
12
+ optional_support :optional_support
13
+ directory_access_mask :access_rights, label: 'Maximal Share Access Rights'
14
+ directory_access_mask :guest_access_rights, label: 'Guest Share Access Rights'
15
+ end
16
+
17
+ # Represents the specific layout of the DataBlock for a {SessionSetupResponse} Packet.
18
+ class DataBlock < RubySMB::SMB1::DataBlock
19
+ stringz :service, label: 'Service Type'
20
+ stringz :native_file_system, label: 'Native File System'
21
+ end
22
+
23
+ smb_header :smb_header
24
+ parameter_block :parameter_block
25
+ data_block :data_block
26
+
27
+ def initialize_instance
28
+ super
29
+ smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
30
+ smb_header.flags.reply = 1
31
+ end
32
+
33
+ # Returns the ACCESS_MASK for the Maximal Share Access Rights. The packet
34
+ # defaults this to a {RubySMB::SMB1::BitField::DirectoryAccessMask}. If it is anything other than
35
+ # a directory that has been connected to, it will re-cast it as a {}RubySMB::SMB1::BitField::FileAccessMask}
36
+ #
37
+ # @return [RubySMB::SMB1::BitField::DirectoryAccessMask] if a directory was connected to
38
+ # @return [RubySMB::SMB1::BitField::FileAccessMask] if anything else was connected to
39
+ def access_rights
40
+ if is_directory?
41
+ self.parameter_block.access_rights
42
+ else
43
+ mask = self.parameter_block.access_rights.to_binary_s
44
+ RubySMB::SMB1::BitField::FileAccessMask.read(mask)
45
+ end
46
+ end
47
+
48
+ # Returns the ACCESS_MASK for the Guest Share Access Rights. The packet
49
+ # defaults this to a {RubySMB::SMB1::BitField::DirectoryAccessMask}. If it is anything other than
50
+ # a directory that has been connected to, it will re-cast it as a {RubySMB::SMB1::BitField::FileAccessMask}
51
+ #
52
+ # @return [RubySMB::SMB1::BitField::DirectoryAccessMask] if a directory was connected to
53
+ # @return [RubySMB::SMB1::BitField::FileAccessMask] if anything else was connected to
54
+ def guest_access_rights
55
+ if is_directory?
56
+ self.parameter_block.guest_access_rights
57
+ else
58
+ mask = self.parameter_block.guest_access_rights.to_binary_s
59
+ RubySMB::SMB1::BitField::FileAccessMask.read(mask)
60
+ end
61
+ end
62
+
63
+ # Checks whether the response is for a Directory
64
+ # This alters the type of access mask that is used.
65
+ #
66
+ # @return [TrueClass] if service is 'A:'
67
+ # @return [FalseClass] if service is NOT 'A:'
68
+ def is_directory?
69
+ self.data_block.service == 'A:'
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,29 @@
1
+ module RubySMB
2
+ module SMB1
3
+ module Packet
4
+
5
+ # This class represents an SMB1 TreeDisonnect Request Packet as defined in
6
+ # [2.2.4.51.1 Request](https://msdn.microsoft.com/en-us/library/ee441622.aspx)
7
+ class TreeDisconnectRequest < RubySMB::GenericPacket
8
+
9
+ # The Parameter Block for this packet is empty save the Word Count
10
+ class ParameterBlock < RubySMB::SMB1::ParameterBlock
11
+ end
12
+
13
+ # The Data Block for this packet is empty save the Byte Count
14
+ class DataBlock < RubySMB::SMB1::DataBlock
15
+ end
16
+
17
+ smb_header :smb_header
18
+ parameter_block :parameter_block
19
+ data_block :data_block
20
+
21
+ def initialize_instance
22
+ super
23
+ smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ module RubySMB
2
+ module SMB1
3
+ module Packet
4
+
5
+ # This class represents an SMB1 TreeDisonnect Response Packet as defined in
6
+ # [2.2.4.51.2 Response](https://msdn.microsoft.com/en-us/library/ee441823.aspx)
7
+ class TreeDisconnectResponse < RubySMB::GenericPacket
8
+
9
+ # The Parameter Block for this packet is empty save the Word Count
10
+ class ParameterBlock < RubySMB::SMB1::ParameterBlock
11
+ end
12
+
13
+ # The Data Block for this packet is empty save the Byte Count
14
+ class DataBlock < RubySMB::SMB1::DataBlock
15
+ end
16
+
17
+ smb_header :smb_header
18
+ parameter_block :parameter_block
19
+ data_block :data_block
20
+
21
+ def initialize_instance
22
+ super
23
+ smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
24
+ smb_header.flags.reply = 1
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,55 @@
1
+ module RubySMB
2
+ module SMB1
3
+
4
+ # An SMB1 connected remote Tree, as returned by a
5
+ # [RubySMB::SMB1::Packet::TreeConnectRequest]
6
+ class Tree
7
+
8
+ # The client this Tree is connected through
9
+ # @!attribute [rw] client
10
+ # @return [RubySMB::Client]
11
+ attr_accessor :client
12
+
13
+ # The current Guest Share Permissions
14
+ # @!attribute [rw] guest_permissions
15
+ # @return [RubySMB::SMB1::BitField::DirectoryAccessMask]
16
+ attr_accessor :guest_permissions
17
+
18
+ # The current Maximal Share Permissions
19
+ # @!attribute [rw] permissions
20
+ # @return [RubySMB::SMB1::BitField::DirectoryAccessMask]
21
+ attr_accessor :permissions
22
+
23
+ # The share path associated with this Tree
24
+ # @!attribute [rw] share
25
+ # @return [String]
26
+ attr_accessor :share
27
+
28
+ # The Tree ID for this Tree
29
+ # @!attribute [rw] id
30
+ # @return [Integer]
31
+ attr_accessor :id
32
+
33
+ def initialize(client:, share:, response:)
34
+ @client = client
35
+ @share = share
36
+ @id = response.smb_header.tid
37
+ @guest_permissions = response.parameter_block.guest_access_rights
38
+ @permissions = response.parameter_block.access_rights
39
+ end
40
+
41
+ # Disconnects this Tree from the current session
42
+ #
43
+ # @return [WindowsError::ErrorCode] the NTStatus sent back by the server.
44
+ def disconnect!
45
+ request = RubySMB::SMB1::Packet::TreeDisconnectRequest.new
46
+ request.smb_header.tid = self.id
47
+ raw_response = self.client.send_recv(request)
48
+ response = RubySMB::SMB1::Packet::TreeDisconnectResponse.read(raw_response)
49
+ response.status_code
50
+ end
51
+
52
+
53
+ end
54
+ end
55
+ end
data/lib/ruby_smb/smb2.rb CHANGED
@@ -9,4 +9,5 @@ module RubySMB::SMB2
9
9
  require 'ruby_smb/smb2/bit_field'
10
10
  require 'ruby_smb/smb2/smb2_header'
11
11
  require 'ruby_smb/smb2/packet'
12
+ require 'ruby_smb/smb2/tree'
12
13
  end
@@ -6,6 +6,10 @@ module RubySMB
6
6
  require 'ruby_smb/smb2/bit_field/smb2_security_mode_single'
7
7
  require 'ruby_smb/smb2/bit_field/smb2_capabailities'
8
8
  require 'ruby_smb/smb2/bit_field/session_flags'
9
+ require 'ruby_smb/smb2/bit_field/directory_access_mask'
10
+ require 'ruby_smb/smb2/bit_field/file_access_mask'
11
+ require 'ruby_smb/smb2/bit_field/share_flags'
12
+ require 'ruby_smb/smb2/bit_field/share_capabailities'
9
13
  end
10
14
  end
11
15
  end
@@ -0,0 +1,38 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module BitField
4
+ # An Access Mask bit field used to describe the permissions on a Directory, as defined in
5
+ # [2.2.13.1.2 Directory_Access_Mask](https://msdn.microsoft.com/en-us/library/cc246801.aspx)
6
+ class DirectoryAccessMask < BinData::Record
7
+ endian :little
8
+ bit1 :read_attr, label: 'Read Attributes'
9
+ bit1 :delete_child, label: 'Delete Child'
10
+ bit1 :traverse, label: 'Traverse'
11
+ bit1 :write_ea, label: 'Write Extended Attributes'
12
+ bit1 :read_ea, label: 'Read Extended Attributes'
13
+ bit1 :add_subdir, label: 'Add Subdirectory'
14
+ bit1 :add_file, label: 'Add File'
15
+ bit1 :list, label: 'List Directory'
16
+ # byte boundary
17
+ bit7 :reserved, label: 'Reserved Space'
18
+ bit1 :write_attr, label: 'Write Attributes'
19
+
20
+ # byte boundary
21
+ bit3 :reserved2, label: 'Reserved Space'
22
+ bit1 :synchronize, label: 'Synchronize'
23
+ bit1 :write_owner, label: 'Write Owner'
24
+ bit1 :write_dac, label: 'Write DAC'
25
+ bit1 :read_control, label: 'Read Control'
26
+ bit1 :delete_access, label: 'Delete'
27
+ # byte boundary
28
+ bit1 :generic_read, label: 'Generic Read'
29
+ bit1 :generic_write, label: 'Generic Write'
30
+ bit1 :generic_execute, label: 'Generic Execute'
31
+ bit1 :generic_all, label: 'Generic All'
32
+ bit2 :reserved3
33
+ bit1 :maximum, label: 'Maximum Allowed'
34
+ bit1 :system_security, label: 'System Security'
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module BitField
4
+ # An Access Mask bit field used to describe the permissions on a File, Printer, or named Pipe. As defined in
5
+ # [2.2.13.1.1 File_Pipe_Printer_Access_Mask](https://msdn.microsoft.com/en-us/library/cc246802.aspx)
6
+ class FileAccessMask < BinData::Record
7
+ endian :little
8
+ bit1 :read_attr, label: 'Read Attributes'
9
+ bit1 :delete_child, label: 'Delete Child'
10
+ bit1 :execute, label: 'Traverse'
11
+ bit1 :write_ea, label: 'Write Extended Attributes'
12
+ bit1 :read_ea, label: 'Read Extended Attributes'
13
+ bit1 :append_data, label: 'Append Data'
14
+ bit1 :write_data, label: 'Write Data'
15
+ bit1 :read_data, label: 'Read Data'
16
+ # byte boundary
17
+ bit7 :reserved, label: 'Reserved Space'
18
+ bit1 :write_attr, label: 'Write Attributes'
19
+
20
+ # byte boundary
21
+ bit3 :reserved2, label: 'Reserved Space'
22
+ bit1 :synchronize, label: 'Synchronize'
23
+ bit1 :write_owner, label: 'Write Owner'
24
+ bit1 :write_dac, label: 'Write DAC'
25
+ bit1 :read_control, label: 'Read Control'
26
+ bit1 :delete_access, label: 'Delete'
27
+ # byte boundary
28
+ bit1 :generic_read, label: 'Generic Read'
29
+ bit1 :generic_write, label: 'Generic Write'
30
+ bit1 :generic_execute, label: 'Generic Execute'
31
+ bit1 :generic_all, label: 'Generic All'
32
+ bit2 :reserved3
33
+ bit1 :maximum, label: 'Maximum Allowed'
34
+ bit1 :system_security, label: 'System Security'
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module BitField
4
+ # Represents a Share Capabilities BitField as defined by
5
+ # [2.2.10 SMB2 TREE_CONNECT Response](https://msdn.microsoft.com/en-us/library/cc246499.aspx)
6
+ class ShareCapabilities < BinData::Record
7
+ endian :little
8
+ bit1 :asymmetric, label: 'Asymmetric'
9
+ bit1 :cluster, label: 'Cluster'
10
+ bit1 :scaleout, label: 'Scale Out'
11
+ bit1 :continuous, label: 'Continuous Availability'
12
+ bit1 :dfs, label: 'DFS'
13
+ bit3 :reserved2, label: 'Reserved Space'
14
+ # byte border
15
+ uint8 :reserved3, label: 'Reserved'
16
+ uint8 :reserved4, label: 'Reserved'
17
+ uint8 :reserved5, label: 'Reserved'
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,75 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module BitField
4
+
5
+ # A Share Flags BitField Mask as defined in
6
+ # [2.2.10 SMB2 TREE_CONNECT Response](https://msdn.microsoft.com/en-us/library/cc246499.aspx)
7
+ class ShareFlags < BinData::Record
8
+ endian :little
9
+ bit2 :reserved1, label: 'Reserved Space'
10
+ bit1 :vdo_caching, label: 'VDO Caching'
11
+ bit1 :auto_caching, label: 'Auto Caching'
12
+ bit2 :reserved2
13
+ bit1 :dfs_root, label: 'DFS Root'
14
+ bit1 :dfs, label: 'DFS'
15
+ # byte boundary
16
+ bit1 :encrypt, label: 'Encrypted Data Required'
17
+ bit1 :hash_v2, label: 'Hash Generation V2'
18
+ bit1 :hash_v1, label: 'Hash Generation V1'
19
+ bit1 :force_oplock, label: 'Force Lvl2 OpLocks'
20
+ bit1 :access_based_enum, label: 'Access Based Directory Enumeration'
21
+ bit1 :namespace_caching, label: 'Namespace Caching'
22
+ bit1 :shared_delete, label: 'Force Shared Delete'
23
+ bit1 :restrict_exclusive_opens, label: 'Restrict Exclusive Opens'
24
+
25
+ bit8 :reserved3, label: 'Reserved Space'
26
+ bit8 :reserved4, label: 'Reserved Space'
27
+
28
+ def caching_type
29
+ if self.vdo_caching == 1 && self.auto_caching == 0
30
+ :vdo
31
+ elsif self.vdo_caching == 0 && self.auto_caching == 1
32
+ :auto
33
+ elsif self.vdo_caching == 1 && self.auto_caching == 1
34
+ :no_caching
35
+ else
36
+ :manual
37
+ end
38
+ end
39
+
40
+ # Sets the Bit Mask for Manual Caching
41
+ #
42
+ # @return [void]
43
+ def set_manual_caching
44
+ self.vdo_caching = 0
45
+ self.auto_caching = 0
46
+ end
47
+
48
+ # Sets the Bit Mask for Auto Caching
49
+ #
50
+ # @return [void]
51
+ def set_auto_caching
52
+ self.vdo_caching = 0
53
+ self.auto_caching = 1
54
+ end
55
+
56
+ # Sets the Bit Mask for VDO Caching
57
+ #
58
+ # @return [void]
59
+ def set_vdo_caching
60
+ self.vdo_caching = 1
61
+ self.auto_caching = 0
62
+ end
63
+
64
+ # Sets the Bit Mask for No Caching
65
+ #
66
+ # @return [void]
67
+ def set_no_caching
68
+ self.vdo_caching = 1
69
+ self.auto_caching = 1
70
+ end
71
+
72
+ end
73
+ end
74
+ end
75
+ end
@@ -1,10 +1,15 @@
1
1
  module RubySMB
2
2
  module SMB2
3
3
  module Packet
4
+ require 'ruby_smb/smb2/packet/error_packet'
4
5
  require 'ruby_smb/smb2/packet/negotiate_request'
5
6
  require 'ruby_smb/smb2/packet/negotiate_response'
6
7
  require 'ruby_smb/smb2/packet/session_setup_request'
7
8
  require 'ruby_smb/smb2/packet/session_setup_response'
9
+ require 'ruby_smb/smb2/packet/tree_connect_request'
10
+ require 'ruby_smb/smb2/packet/tree_connect_response'
11
+ require 'ruby_smb/smb2/packet/tree_disconnect_request'
12
+ require 'ruby_smb/smb2/packet/tree_disconnect_response'
8
13
  end
9
14
  end
10
15
  end
@@ -0,0 +1,15 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module Packet
4
+
5
+ # An SMB2 Error packet for when an incomplete response comes back
6
+
7
+ class ErrorPacket < RubySMB::GenericPacket
8
+ endian :little
9
+ smb2_header :smb2_header
10
+ uint16 :structure_size, label: 'Structure Size', initial_value: 4
11
+ uint8 :error_data
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module Packet
4
+
5
+ # An SMB2 TreeConnectRequest Packet as defined in
6
+ # [2.2.9 SMB2 TREE_CONNECT Request](https://msdn.microsoft.com/en-us/library/cc246567.aspx)
7
+ class TreeConnectRequest < RubySMB::GenericPacket
8
+ endian :little
9
+ smb2_header :smb2_header
10
+ uint16 :structure_size, label: 'Structure Size', initial_value: 9
11
+ uint16 :flags, label: 'Flags', initial_value: 0x00
12
+ uint16 :path_offset, label: 'Path Offset', initial_value: 0x48
13
+ uint16 :path_length, label: 'Path Length', value: lambda { self.path.length }
14
+ string :path, label: 'Path Buffer'
15
+
16
+ def initialize_instance
17
+ super
18
+ smb2_header.command = RubySMB::SMB2::Commands::TREE_CONNECT
19
+ end
20
+
21
+ def encode_path(path)
22
+ self.path = path.encode("utf-16le")
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end