ruby_smb 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
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