ruby_smb 1.0.3 → 2.0.1
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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.travis.yml +3 -2
- data/Gemfile +6 -2
- data/README.md +35 -47
- data/examples/enum_registry_key.rb +28 -0
- data/examples/enum_registry_values.rb +30 -0
- data/examples/negotiate.rb +51 -8
- data/examples/pipes.rb +2 -1
- data/examples/read_file_encryption.rb +56 -0
- data/examples/read_registry_key_value.rb +32 -0
- data/lib/ruby_smb.rb +4 -1
- data/lib/ruby_smb/client.rb +233 -22
- data/lib/ruby_smb/client/authentication.rb +70 -33
- data/lib/ruby_smb/client/echo.rb +20 -2
- data/lib/ruby_smb/client/encryption.rb +62 -0
- data/lib/ruby_smb/client/negotiation.rb +172 -24
- data/lib/ruby_smb/client/signing.rb +19 -0
- data/lib/ruby_smb/client/tree_connect.rb +24 -18
- data/lib/ruby_smb/client/utils.rb +8 -7
- data/lib/ruby_smb/client/winreg.rb +46 -0
- data/lib/ruby_smb/crypto.rb +30 -0
- data/lib/ruby_smb/dcerpc.rb +38 -0
- data/lib/ruby_smb/dcerpc/bind.rb +2 -2
- data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
- data/lib/ruby_smb/dcerpc/error.rb +3 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
- data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
- data/lib/ruby_smb/dcerpc/request.rb +28 -9
- data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
- data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
- data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
- data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
- data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
- data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
- data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
- data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
- data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
- data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
- data/lib/ruby_smb/dispatcher/socket.rb +4 -3
- data/lib/ruby_smb/error.rb +68 -2
- data/lib/ruby_smb/generic_packet.rb +33 -4
- data/lib/ruby_smb/smb1/commands.rb +1 -1
- data/lib/ruby_smb/smb1/file.rb +66 -15
- data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/empty_packet.rb +10 -1
- data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
- data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
- data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +3 -2
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/session_setup_response.rb +3 -2
- data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
- data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
- data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
- data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
- data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/write_andx_request.rb +3 -6
- data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/pipe.rb +87 -6
- data/lib/ruby_smb/smb1/tree.rb +50 -3
- data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
- data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
- data/lib/ruby_smb/smb2/file.rb +103 -25
- data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
- data/lib/ruby_smb/smb2/packet.rb +2 -0
- data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
- data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/error_packet.rb +15 -3
- data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -17
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +52 -5
- data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
- data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
- data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +93 -10
- data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +10 -22
- data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
- data/lib/ruby_smb/smb2/pipe.rb +86 -12
- data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
- data/lib/ruby_smb/smb2/tree.rb +65 -21
- data/lib/ruby_smb/version.rb +1 -1
- data/ruby_smb.gemspec +5 -3
- data/spec/lib/ruby_smb/client_spec.rb +1612 -108
- data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
- data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
- data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
- data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
- data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
- data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
- data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
- data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +2 -2
- data/spec/lib/ruby_smb/error_spec.rb +59 -0
- data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
- data/spec/lib/ruby_smb/smb1/file_spec.rb +191 -2
- data/spec/lib/ruby_smb/smb1/packet/empty_packet_spec.rb +68 -0
- data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
- data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +272 -149
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
- data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
- data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
- data/spec/lib/ruby_smb/smb2/file_spec.rb +323 -6
- data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
- data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
- data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -0
- data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
- data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
- data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
- data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -22
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +286 -149
- data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +261 -2
- metadata +191 -83
- metadata.gz.sig +0 -0
- data/lib/ruby_smb/smb1/dcerpc.rb +0 -67
- data/lib/ruby_smb/smb2/dcerpc.rb +0 -70
- data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +0 -37
@@ -48,7 +48,7 @@ module RubySMB
|
|
48
48
|
end
|
49
49
|
|
50
50
|
rescue IOError, Errno::ECONNABORTED, Errno::ECONNRESET => e
|
51
|
-
raise RubySMB::Error::CommunicationError, "An error
|
51
|
+
raise RubySMB::Error::CommunicationError, "An error occurred writing to the Socket: #{e.message}"
|
52
52
|
end
|
53
53
|
nil
|
54
54
|
end
|
@@ -61,13 +61,14 @@ module RubySMB
|
|
61
61
|
# which are assumed to be the NetBiosSessionService header.
|
62
62
|
# @raise [RubySMB::Error::CommunicationError] if the read timeout expires or an error occurs when reading the socket
|
63
63
|
def recv_packet(full_response: false)
|
64
|
+
raise RubySMB::Error::CommunicationError, 'Connection has already been closed' if @tcp_socket.closed?
|
64
65
|
if IO.select([@tcp_socket], nil, nil, @read_timeout).nil?
|
65
66
|
raise RubySMB::Error::CommunicationError, "Read timeout expired when reading from the Socket (timeout=#{@read_timeout})"
|
66
67
|
end
|
67
68
|
|
68
69
|
begin
|
69
70
|
nbss_data = @tcp_socket.read(4)
|
70
|
-
raise
|
71
|
+
raise RubySMB::Error::CommunicationError, 'Socket read returned nil' if nbss_data.nil?
|
71
72
|
nbss_header = RubySMB::Nbss::SessionHeader.read(nbss_data)
|
72
73
|
rescue IOError
|
73
74
|
raise ::RubySMB::Error::NetBiosSessionService, 'NBSS Header is missing'
|
@@ -84,7 +85,7 @@ module RubySMB
|
|
84
85
|
end
|
85
86
|
data
|
86
87
|
rescue Errno::EINVAL, Errno::ECONNABORTED, Errno::ECONNRESET, TypeError, NoMethodError => e
|
87
|
-
raise RubySMB::Error::CommunicationError, "An error
|
88
|
+
raise RubySMB::Error::CommunicationError, "An error occurred reading from the Socket #{e.message}"
|
88
89
|
end
|
89
90
|
end
|
90
91
|
end
|
data/lib/ruby_smb/error.rb
CHANGED
@@ -15,10 +15,66 @@ module RubySMB
|
|
15
15
|
|
16
16
|
# Raised when trying to parse raw binary into a Packet and the data
|
17
17
|
# is invalid.
|
18
|
-
class InvalidPacket < RubySMBError
|
18
|
+
class InvalidPacket < RubySMBError
|
19
|
+
def initialize(args = nil)
|
20
|
+
if args.nil?
|
21
|
+
super
|
22
|
+
elsif args.is_a? String
|
23
|
+
super(args)
|
24
|
+
elsif args.is_a? Hash
|
25
|
+
expected_proto = args[:expected_proto] ? translate_protocol(args[:expected_proto]) : "???"
|
26
|
+
expected_cmd = args[:expected_cmd] || "???"
|
27
|
+
received_proto = args[:received_proto] ? translate_protocol(args[:received_proto]) : "???"
|
28
|
+
received_cmd = args[:received_cmd] || "???"
|
29
|
+
super(
|
30
|
+
"Expecting #{expected_proto} protocol "\
|
31
|
+
"with command=#{expected_cmd}"\
|
32
|
+
"#{(" (" + args[:expected_custom] + ")") if args[:expected_custom]}, "\
|
33
|
+
"got #{received_proto} protocol "\
|
34
|
+
"with command=#{received_cmd}"\
|
35
|
+
"#{(" (" + args[:received_custom] + ")") if args[:received_custom]}"
|
36
|
+
)
|
37
|
+
else
|
38
|
+
raise ArgumentError, "InvalidPacket expects a String or a Hash, got a #{args.class}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def translate_protocol(proto)
|
43
|
+
case proto
|
44
|
+
when RubySMB::SMB1::SMB_PROTOCOL_ID
|
45
|
+
'SMB1'
|
46
|
+
when RubySMB::SMB2::SMB2_PROTOCOL_ID
|
47
|
+
'SMB2'
|
48
|
+
else
|
49
|
+
raise ArgumentError, 'Unknown SMB protocol'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
private :translate_protocol
|
53
|
+
end
|
19
54
|
|
20
55
|
# Raised when a response packet has a NTStatus code that was unexpected.
|
21
|
-
class UnexpectedStatusCode < RubySMBError
|
56
|
+
class UnexpectedStatusCode < RubySMBError
|
57
|
+
attr_reader :status_code
|
58
|
+
|
59
|
+
def initialize(status_code)
|
60
|
+
case status_code
|
61
|
+
when WindowsError::ErrorCode
|
62
|
+
@status_code = status_code
|
63
|
+
when Integer
|
64
|
+
@status_code = WindowsError::NTStatus.find_by_retval(status_code).first
|
65
|
+
if @status_code.nil?
|
66
|
+
@status_code = WindowsError::ErrorCode.new("0x#{status_code.to_s(16)}", status_code, "Unknown 0x#{status_code.to_s(16)}")
|
67
|
+
end
|
68
|
+
else
|
69
|
+
raise ArgumentError, "Status code must be a WindowsError::ErrorCode or an Integer, got #{status_code.class}"
|
70
|
+
end
|
71
|
+
super
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_s
|
75
|
+
"The server responded with an unexpected status code: #{status_code.name}"
|
76
|
+
end
|
77
|
+
end
|
22
78
|
|
23
79
|
# Raised when an error occurs with the underlying socket.
|
24
80
|
class CommunicationError < RubySMBError; end
|
@@ -26,5 +82,15 @@ module RubySMB
|
|
26
82
|
# Raised when Protocol Negotiation fails, possibly due to an
|
27
83
|
# unsupported protocol.
|
28
84
|
class NegotiationFailure < RubySMBError; end
|
85
|
+
|
86
|
+
# Raised when trying to parse raw binary into a BitField and the data
|
87
|
+
# is invalid.
|
88
|
+
class InvalidBitField < RubySMBError; end
|
89
|
+
|
90
|
+
# Raised when an encryption operation fails
|
91
|
+
class EncryptionError < RubySMBError; end
|
92
|
+
|
93
|
+
# Raised when an signing operation fails
|
94
|
+
class SigningError < RubySMBError; end
|
29
95
|
end
|
30
96
|
end
|
@@ -45,14 +45,16 @@ module RubySMB
|
|
45
45
|
rescue IOError => e
|
46
46
|
case self.to_s
|
47
47
|
when /EmptyPacket|ErrorPacket/
|
48
|
-
raise
|
48
|
+
raise RubySMB::Error::InvalidPacket, 'Not a valid SMB packet'
|
49
49
|
when /SMB1/
|
50
|
-
RubySMB::SMB1::Packet::EmptyPacket.read(val)
|
50
|
+
packet = RubySMB::SMB1::Packet::EmptyPacket.read(val)
|
51
51
|
when /SMB2/
|
52
|
-
RubySMB::SMB2::Packet::ErrorPacket.read(val)
|
52
|
+
packet = RubySMB::SMB2::Packet::ErrorPacket.read(val)
|
53
53
|
else
|
54
|
-
raise
|
54
|
+
raise RubySMB::Error::InvalidPacket, 'Not a valid SMB packet'
|
55
55
|
end
|
56
|
+
packet.original_command = self::COMMAND
|
57
|
+
packet
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
@@ -72,6 +74,33 @@ module RubySMB
|
|
72
74
|
status_code
|
73
75
|
end
|
74
76
|
|
77
|
+
# Validates the packet protocol ID and the SMB command
|
78
|
+
#
|
79
|
+
# @return [TrueClass, FalseClass] true if the packet is valid, false otherwise
|
80
|
+
def valid?
|
81
|
+
case packet_smb_version
|
82
|
+
when 'SMB1'
|
83
|
+
return smb_header.protocol == RubySMB::SMB1::SMB_PROTOCOL_ID &&
|
84
|
+
smb_header.command == self.class::COMMAND
|
85
|
+
when 'SMB2'
|
86
|
+
return smb2_header.protocol == RubySMB::SMB2::SMB2_PROTOCOL_ID &&
|
87
|
+
smb2_header.command == self.class::COMMAND
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def initialize_instance
|
92
|
+
super
|
93
|
+
|
94
|
+
unless [RubySMB::SMB1::Packet::EmptyPacket, RubySMB::SMB2::Packet::ErrorPacket].any? {|klass| self.is_a? klass}
|
95
|
+
case packet_smb_version
|
96
|
+
when 'SMB1'
|
97
|
+
smb_header.command = self.class::COMMAND
|
98
|
+
when 'SMB2'
|
99
|
+
smb2_header.command = self.class::COMMAND
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
75
104
|
# Returns an array of hashes representing the
|
76
105
|
# fields for this record.
|
77
106
|
#
|
@@ -10,7 +10,7 @@ module RubySMB
|
|
10
10
|
SMB_COM_TRANSACTION2_SECONDARY = 0x33
|
11
11
|
SMB_COM_TREE_DISCONNECT = 0x71
|
12
12
|
SMB_COM_NEGOTIATE = 0x72
|
13
|
-
|
13
|
+
SMB_COM_SESSION_SETUP_ANDX = 0x73
|
14
14
|
SMB_COM_LOGOFF = 0x74
|
15
15
|
SMB_COM_TREE_CONNECT = 0x75
|
16
16
|
SMB_COM_NT_TRANSACT = 0xA0
|
data/lib/ruby_smb/smb1/file.rb
CHANGED
@@ -76,17 +76,22 @@ module RubySMB
|
|
76
76
|
# Closes the handle to the remote file.
|
77
77
|
#
|
78
78
|
# @return [WindowsError::ErrorCode] the NTStatus code returned by the operation
|
79
|
-
# @raise [RubySMB::Error::InvalidPacket] if the response
|
79
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response packet is not valid
|
80
80
|
# @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
|
81
81
|
def close
|
82
82
|
close_request = set_header_fields(RubySMB::SMB1::Packet::CloseRequest.new)
|
83
83
|
raw_response = @tree.client.send_recv(close_request)
|
84
84
|
response = RubySMB::SMB1::Packet::CloseResponse.read(raw_response)
|
85
|
-
unless response.
|
86
|
-
raise RubySMB::Error::InvalidPacket
|
85
|
+
unless response.valid?
|
86
|
+
raise RubySMB::Error::InvalidPacket.new(
|
87
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
88
|
+
expected_cmd: RubySMB::SMB1::Packet::CloseResponse::COMMAND,
|
89
|
+
received_proto: response.smb_header.protocol,
|
90
|
+
received_cmd: response.smb_header.command
|
91
|
+
)
|
87
92
|
end
|
88
93
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
89
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
94
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
90
95
|
end
|
91
96
|
response.status_code
|
92
97
|
end
|
@@ -98,7 +103,7 @@ module RubySMB
|
|
98
103
|
# @param bytes [Integer] the number of bytes to read
|
99
104
|
# @param offset [Integer] the byte offset in the file to start reading from
|
100
105
|
# @return [String] the data read from the file
|
101
|
-
# @raise [RubySMB::Error::InvalidPacket] if the response
|
106
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response packet is not valid
|
102
107
|
# @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
|
103
108
|
def read(bytes: @size, offset: 0)
|
104
109
|
atomic_read_size = if bytes > @tree.client.max_buffer_size
|
@@ -113,11 +118,16 @@ module RubySMB
|
|
113
118
|
read_request = read_packet(read_length: atomic_read_size, offset: offset)
|
114
119
|
raw_response = @tree.client.send_recv(read_request)
|
115
120
|
response = RubySMB::SMB1::Packet::ReadAndxResponse.read(raw_response)
|
116
|
-
unless response.
|
117
|
-
raise RubySMB::Error::InvalidPacket
|
121
|
+
unless response.valid?
|
122
|
+
raise RubySMB::Error::InvalidPacket.new(
|
123
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
124
|
+
expected_cmd: RubySMB::SMB1::Packet::ReadAndxResponse::COMMAND,
|
125
|
+
received_proto: response.smb_header.protocol,
|
126
|
+
received_cmd: response.smb_header.command
|
127
|
+
)
|
118
128
|
end
|
119
129
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
120
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
130
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
121
131
|
end
|
122
132
|
|
123
133
|
if response.is_a?(RubySMB::SMB1::Packet::ReadAndxResponse)
|
@@ -146,17 +156,27 @@ module RubySMB
|
|
146
156
|
def read_packet(read_length: 0, offset: 0)
|
147
157
|
read_request = set_header_fields(RubySMB::SMB1::Packet::ReadAndxRequest.new)
|
148
158
|
read_request.parameter_block.max_count_of_bytes_to_return = read_length
|
159
|
+
read_request.parameter_block.min_count_of_bytes_to_return = read_length
|
160
|
+
read_request.parameter_block.remaining = read_length
|
149
161
|
read_request.parameter_block.offset = offset
|
150
162
|
read_request
|
151
163
|
end
|
152
|
-
|
164
|
+
|
153
165
|
def send_recv_read(read_length: 0, offset: 0)
|
154
166
|
read_request = read_packet(read_length: read_length, offset: offset)
|
155
167
|
raw_response = tree.client.send_recv(read_request)
|
156
168
|
|
157
169
|
response = RubySMB::SMB1::Packet::ReadAndxResponse.read(raw_response)
|
170
|
+
unless response.valid?
|
171
|
+
raise RubySMB::Error::InvalidPacket.new(
|
172
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
173
|
+
expected_cmd: RubySMB::SMB1::Packet::ReadAndxResponse::COMMAND,
|
174
|
+
received_proto: response.smb_header.protocol,
|
175
|
+
received_cmd: response.smb_header.command
|
176
|
+
)
|
177
|
+
end
|
158
178
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
159
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
179
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
160
180
|
end
|
161
181
|
|
162
182
|
response.data_block.data.to_binary_s
|
@@ -165,9 +185,18 @@ module RubySMB
|
|
165
185
|
# Delete a file on close
|
166
186
|
#
|
167
187
|
# @return [WindowsError::ErrorCode] the NTStatus Response code
|
188
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response packet is not valid
|
168
189
|
def delete
|
169
190
|
raw_response = @tree.client.send_recv(delete_packet)
|
170
191
|
response = RubySMB::SMB1::Packet::Trans2::SetFileInformationResponse.read(raw_response)
|
192
|
+
unless response.valid?
|
193
|
+
raise RubySMB::Error::InvalidPacket.new(
|
194
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
195
|
+
expected_cmd: RubySMB::SMB1::Packet::Trans2::SetFileInformationResponse::COMMAND,
|
196
|
+
received_proto: response.smb_header.protocol,
|
197
|
+
received_cmd: response.smb_header.command
|
198
|
+
)
|
199
|
+
end
|
171
200
|
response.status_code
|
172
201
|
end
|
173
202
|
|
@@ -190,7 +219,7 @@ module RubySMB
|
|
190
219
|
# @param data [String] the data to write to the file
|
191
220
|
# @param offset [Integer] the offset in the file to start writing from
|
192
221
|
# @return [Integer] the count of bytes written
|
193
|
-
# @raise [RubySMB::Error::InvalidPacket] if the response
|
222
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response packet is not valid
|
194
223
|
# @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
|
195
224
|
def write(data:, offset: 0)
|
196
225
|
buffer = data.dup
|
@@ -206,11 +235,16 @@ module RubySMB
|
|
206
235
|
write_request = write_packet(data: buffer.slice!(0, atomic_write_size), offset: offset)
|
207
236
|
raw_response = @tree.client.send_recv(write_request)
|
208
237
|
response = RubySMB::SMB1::Packet::WriteAndxResponse.read(raw_response)
|
209
|
-
unless response.
|
210
|
-
raise RubySMB::Error::InvalidPacket
|
238
|
+
unless response.valid?
|
239
|
+
raise RubySMB::Error::InvalidPacket.new(
|
240
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
241
|
+
expected_cmd: RubySMB::SMB1::Packet::WriteAndxResponse::COMMAND,
|
242
|
+
received_proto: response.smb_header.protocol,
|
243
|
+
received_cmd: response.smb_header.command
|
244
|
+
)
|
211
245
|
end
|
212
246
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
213
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
247
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
214
248
|
end
|
215
249
|
bytes_written = response.parameter_block.count_low + (response.parameter_block.count_high << 16)
|
216
250
|
total_bytes_written += bytes_written
|
@@ -235,12 +269,20 @@ module RubySMB
|
|
235
269
|
write_request.parameter_block.remaining = write_request.parameter_block.data_length
|
236
270
|
write_request
|
237
271
|
end
|
238
|
-
|
272
|
+
|
239
273
|
def send_recv_write(data:'', offset: 0)
|
240
274
|
pkt = write_packet(data: data, offset: offset)
|
241
275
|
pkt.set_64_bit_offset(true)
|
242
276
|
raw_response = @tree.client.send_recv(pkt)
|
243
277
|
response = RubySMB::SMB1::Packet::WriteAndxResponse.read(raw_response)
|
278
|
+
unless response.valid?
|
279
|
+
raise RubySMB::Error::InvalidPacket.new(
|
280
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
281
|
+
expected_cmd: RubySMB::SMB1::Packet::WriteAndxResponse::COMMAND,
|
282
|
+
received_proto: response.smb_header.protocol,
|
283
|
+
received_cmd: response.smb_header.command
|
284
|
+
)
|
285
|
+
end
|
244
286
|
response.parameter_block.count_low
|
245
287
|
end
|
246
288
|
|
@@ -248,9 +290,18 @@ module RubySMB
|
|
248
290
|
#
|
249
291
|
# @param new_file_name [String] the new name
|
250
292
|
# @return [WindowsError::ErrorCode] the NTStatus Response code
|
293
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response packet is not valid
|
251
294
|
def rename(new_file_name)
|
252
295
|
raw_response = tree.client.send_recv(rename_packet(new_file_name))
|
253
296
|
response = RubySMB::SMB1::Packet::Trans2::SetFileInformationResponse.read(raw_response)
|
297
|
+
unless response.valid?
|
298
|
+
raise RubySMB::Error::InvalidPacket.new(
|
299
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
300
|
+
expected_cmd: RubySMB::SMB1::Packet::Trans2::SetFileInformationResponse::COMMAND,
|
301
|
+
received_proto: response.smb_header.protocol,
|
302
|
+
received_cmd: response.smb_header.command
|
303
|
+
)
|
304
|
+
end
|
254
305
|
response.status_code
|
255
306
|
end
|
256
307
|
|
@@ -4,6 +4,8 @@ module RubySMB
|
|
4
4
|
# A SMB1 SMB_COM_CLOSE Request Packet as defined in
|
5
5
|
# [2.2.4.5.1 Request](https://msdn.microsoft.com/en-us/library/ee442151.aspx)
|
6
6
|
class CloseRequest < RubySMB::GenericPacket
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_CLOSE
|
8
|
+
|
7
9
|
# A SMB1 Parameter Block as defined by the {CloseRequest}
|
8
10
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
9
11
|
endian :little
|
@@ -20,11 +22,6 @@ module RubySMB
|
|
20
22
|
parameter_block :parameter_block
|
21
23
|
data_block :data_block
|
22
24
|
|
23
|
-
def initialize_instance
|
24
|
-
super
|
25
|
-
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_CLOSE
|
26
|
-
end
|
27
|
-
|
28
25
|
end
|
29
26
|
end
|
30
27
|
end
|
@@ -4,6 +4,8 @@ module RubySMB
|
|
4
4
|
# A SMB1 SMB_COM_CLOSE Response Packet as defined in
|
5
5
|
# [2.2.4.5.2 Response](https://msdn.microsoft.com/en-us/library/ee441667.aspx)
|
6
6
|
class CloseResponse < RubySMB::GenericPacket
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_CLOSE
|
8
|
+
|
7
9
|
# A SMB1 Parameter Block as defined by the {CloseResponse}
|
8
10
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
9
11
|
end
|
@@ -18,7 +20,6 @@ module RubySMB
|
|
18
20
|
|
19
21
|
def initialize_instance
|
20
22
|
super
|
21
|
-
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_CLOSE
|
22
23
|
smb_header.flags.reply = 1
|
23
24
|
end
|
24
25
|
|
@@ -4,6 +4,8 @@ module RubySMB
|
|
4
4
|
# This class represents an SMB1 Echo Request Packet as defined in
|
5
5
|
# [2.2.4.39.1 Request](https://msdn.microsoft.com/en-us/library/ee441746.aspx)
|
6
6
|
class EchoRequest < RubySMB::GenericPacket
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_ECHO
|
8
|
+
|
7
9
|
# The {RubySMB::SMB1::ParameterBlock} specific to this packet type.
|
8
10
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
9
11
|
uint16 :echo_count, label: 'Echo Count', initial_value: 1
|
@@ -18,10 +20,6 @@ module RubySMB
|
|
18
20
|
parameter_block :parameter_block
|
19
21
|
data_block :data_block
|
20
22
|
|
21
|
-
def initialize_instance
|
22
|
-
super
|
23
|
-
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_ECHO
|
24
|
-
end
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
@@ -4,6 +4,8 @@ module RubySMB
|
|
4
4
|
# This class represents an SMB1 Echo Request Packet as defined in
|
5
5
|
# [2.2.4.39.2 Response](https://msdn.microsoft.com/en-us/library/ee441626.aspx)
|
6
6
|
class EchoResponse < RubySMB::GenericPacket
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_ECHO
|
8
|
+
|
7
9
|
# The {RubySMB::SMB1::ParameterBlock} specific to this packet type.
|
8
10
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
9
11
|
uint16 :sequence_number, label: 'Sequence Number'
|
@@ -20,7 +22,6 @@ module RubySMB
|
|
20
22
|
|
21
23
|
def initialize_instance
|
22
24
|
super
|
23
|
-
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_ECHO
|
24
25
|
smb_header.flags.reply = 1
|
25
26
|
end
|
26
27
|
end
|
@@ -1,12 +1,21 @@
|
|
1
1
|
module RubySMB
|
2
2
|
module SMB1
|
3
3
|
module Packet
|
4
|
-
# This packet represent an SMB1 Response Packet when the parameter and
|
4
|
+
# This packet represent an SMB1 Error Response Packet when the parameter and
|
5
5
|
# data blocks will be empty.
|
6
6
|
class EmptyPacket < RubySMB::GenericPacket
|
7
|
+
attr_accessor :original_command
|
8
|
+
|
7
9
|
smb_header :smb_header
|
8
10
|
parameter_block :parameter_block
|
9
11
|
data_block :data_block
|
12
|
+
|
13
|
+
def valid?
|
14
|
+
return smb_header.protocol == RubySMB::SMB1::SMB_PROTOCOL_ID &&
|
15
|
+
smb_header.command == @original_command &&
|
16
|
+
parameter_block.word_count == 0 &&
|
17
|
+
data_block.byte_count == 0
|
18
|
+
end
|
10
19
|
end
|
11
20
|
end
|
12
21
|
end
|