ruby_smb 2.0.4 → 2.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 (51) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.github/workflows/verify.yml +56 -0
  5. data/README.md +0 -1
  6. data/examples/delete_file.rb +0 -0
  7. data/examples/net_share_enum_all.rb +0 -0
  8. data/examples/pipes.rb +0 -0
  9. data/examples/rename_file.rb +0 -0
  10. data/lib/ruby_smb.rb +3 -2
  11. data/lib/ruby_smb/client.rb +25 -21
  12. data/lib/ruby_smb/client/negotiation.rb +10 -12
  13. data/lib/ruby_smb/compression.rb +7 -0
  14. data/lib/ruby_smb/compression/lznt1.rb +164 -0
  15. data/lib/ruby_smb/dcerpc.rb +3 -1
  16. data/lib/ruby_smb/dcerpc/ndr.rb +97 -0
  17. data/lib/ruby_smb/dcerpc/netlogon.rb +101 -0
  18. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +37 -0
  19. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb +26 -0
  20. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +37 -0
  21. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response.rb +23 -0
  22. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +32 -0
  23. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb +24 -0
  24. data/lib/ruby_smb/dcerpc/request.rb +6 -0
  25. data/lib/ruby_smb/dispatcher/socket.rb +1 -1
  26. data/lib/ruby_smb/smb1/file.rb +1 -1
  27. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +0 -1
  28. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +0 -1
  29. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +1 -2
  30. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +1 -13
  31. data/lib/ruby_smb/smb1/pipe.rb +4 -2
  32. data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +4 -0
  33. data/lib/ruby_smb/smb2/pipe.rb +6 -4
  34. data/lib/ruby_smb/version.rb +1 -1
  35. data/spec/lib/ruby_smb/client_spec.rb +17 -7
  36. data/spec/lib/ruby_smb/compression/lznt1_spec.rb +32 -0
  37. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request_spec.rb +69 -0
  38. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response_spec.rb +53 -0
  39. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request_spec.rb +69 -0
  40. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response_spec.rb +37 -0
  41. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request_spec.rb +45 -0
  42. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response_spec.rb +37 -0
  43. data/spec/lib/ruby_smb/smb1/file_spec.rb +1 -1
  44. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +0 -1
  45. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +0 -1
  46. data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +0 -5
  47. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +0 -6
  48. data/spec/spec_helper.rb +1 -1
  49. metadata +42 -19
  50. metadata.gz.sig +0 -0
  51. data/.travis.yml +0 -6
@@ -44,8 +44,7 @@ module RubySMB
44
44
  class DataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
45
45
  string :pad1, length: -> { pad1_length }
46
46
  trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
47
- string :pad2, length: -> { pad2_length }
48
- string :trans2_data, label: 'Trans2 Data', length: 0
47
+ # trans2_data: No data is sent by this message.
49
48
  end
50
49
 
51
50
  smb_header :smb_header
@@ -23,23 +23,11 @@ module RubySMB
23
23
  end
24
24
  end
25
25
 
26
- # The Trans2 Data Block for this particular Subcommand
27
- class Trans2Data < BinData::Record
28
-
29
- # Returns the length of the Trans2Data struct
30
- # in number of bytes
31
- def length
32
- do_num_bytes
33
- end
34
- end
35
-
36
26
  # The {RubySMB::SMB1::DataBlock} specific to this packet type.
37
27
  class DataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
38
- uint8 :name, label: 'Name', initial_value: 0x00
39
28
  string :pad1, length: -> { pad1_length }
40
29
  trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
41
- string :pad2, length: -> { pad2_length }
42
- trans2_data :trans2_data, label: 'Trans2 Data'
30
+ # trans2_data: No data is sent by this message.
43
31
  end
44
32
 
45
33
  smb_header :smb_header
@@ -16,12 +16,14 @@ module RubySMB
16
16
  def initialize(tree:, response:, name:)
17
17
  raise ArgumentError, 'No Name Provided' if name.nil?
18
18
  case name
19
+ when 'netlogon', '\\netlogon'
20
+ extend RubySMB::Dcerpc::Netlogon
19
21
  when 'srvsvc', '\\srvsvc'
20
22
  extend RubySMB::Dcerpc::Srvsvc
21
- when 'winreg', '\\winreg'
22
- extend RubySMB::Dcerpc::Winreg
23
23
  when 'svcctl', '\\svcctl'
24
24
  extend RubySMB::Dcerpc::Svcctl
25
+ when 'winreg', '\\winreg'
26
+ extend RubySMB::Dcerpc::Winreg
25
27
  end
26
28
  super(tree: tree, response: response, name: name)
27
29
  end
@@ -3,6 +3,9 @@ module RubySMB
3
3
  module Packet
4
4
  # An SMB2 COMPRESSION_TRANSFORM_HEADER Packet as defined in
5
5
  # [2.2.42 SMB2 COMPRESSION_TRANSFORM_HEADER](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/1d435f21-9a21-4f4c-828e-624a176cf2a0)
6
+ # NOTE: On 2021-04-06 the official documentation split the definition of COMPRESSION_TRANSFORM_HEADER into the following two variants:
7
+ # * SMB2_COMPRESSION_TRANSFORM_HEADER_CHAINED
8
+ # * SMB2_COMPRESSION_TRANSFORM_HEADER_UNCHAINED
6
9
  class CompressionTransformHeader < BinData::Record
7
10
  endian :little
8
11
 
@@ -11,6 +14,7 @@ module RubySMB
11
14
  uint16 :compression_algorithm, label: 'Compression Algorithm'
12
15
  uint16 :flags, label: 'Flags'
13
16
  uint32 :offset, label: 'Offset / Length'
17
+ array :compressed_data, label: 'Compressed Data', type: :uint8, read_until: :eof
14
18
  end
15
19
 
16
20
  # An SMB2 SMB2_COMPRESSION_TRANSFORM_HEADER_PAYLOAD Packet as defined in
@@ -13,12 +13,14 @@ module RubySMB
13
13
  def initialize(tree:, response:, name:)
14
14
  raise ArgumentError, 'No Name Provided' if name.nil?
15
15
  case name
16
- when 'srvsvc'
16
+ when 'netlogon', '\\netlogon'
17
+ extend RubySMB::Dcerpc::Netlogon
18
+ when 'srvsvc', '\\srvsvc'
17
19
  extend RubySMB::Dcerpc::Srvsvc
18
- when 'winreg'
19
- extend RubySMB::Dcerpc::Winreg
20
- when 'svcctl'
20
+ when 'svcctl', '\\svcctl'
21
21
  extend RubySMB::Dcerpc::Svcctl
22
+ when 'winreg', '\\winreg'
23
+ extend RubySMB::Dcerpc::Winreg
22
24
  end
23
25
  super(tree: tree, response: response, name: name)
24
26
  end
@@ -1,3 +1,3 @@
1
1
  module RubySMB
2
- VERSION = '2.0.4'.freeze
2
+ VERSION = '2.0.9'.freeze
3
3
  end
@@ -809,6 +809,18 @@ RSpec.describe RubySMB::Client do
809
809
  smb1_extended_response.to_binary_s
810
810
  }
811
811
 
812
+ let(:smb1_response) {
813
+ packet = RubySMB::SMB1::Packet::NegotiateResponse.new
814
+ smb1_capabilities_dup = smb1_capabilities.dup
815
+ smb1_capabilities_dup[:extended_security] = 0
816
+
817
+ packet.parameter_block.capabilities = smb1_capabilities_dup
818
+ packet
819
+ }
820
+ let(:smb1_response_raw) {
821
+ smb1_response.to_binary_s
822
+ }
823
+
812
824
  let(:smb2_response) { RubySMB::SMB2::Packet::NegotiateResponse.new(dialect_revision: 0x200) }
813
825
  let(:smb3_response) { RubySMB::SMB2::Packet::NegotiateResponse.new(dialect_revision: 0x300) }
814
826
 
@@ -997,10 +1009,14 @@ RSpec.describe RubySMB::Client do
997
1009
 
998
1010
  describe '#negotiate_response' do
999
1011
  context 'with only SMB1' do
1000
- it 'returns a properly formed packet' do
1012
+ it 'returns a properly formed NegotiateResponseExtended packet if extended_security is set as 1' do
1001
1013
  expect(smb1_client.negotiate_response(smb1_extended_response_raw)).to eq smb1_extended_response
1002
1014
  end
1003
1015
 
1016
+ it 'returns a properly formed NegotiateResponse packet if extended_security is set as 0' do
1017
+ expect(smb1_client.negotiate_response(smb1_response_raw)).to eq smb1_response
1018
+ end
1019
+
1004
1020
  it 'raises an exception if the response is not a SMB packet' do
1005
1021
  expect { smb1_client.negotiate_response(random_junk) }.to raise_error(RubySMB::Error::InvalidPacket)
1006
1022
  end
@@ -1015,12 +1031,6 @@ RSpec.describe RubySMB::Client do
1015
1031
  bogus_response.smb_header.command = 0xff
1016
1032
  expect { smb1_client.negotiate_response(bogus_response.to_binary_s) }.to raise_error(RubySMB::Error::InvalidPacket)
1017
1033
  end
1018
-
1019
- it 'considers the response invalid if Extended Security is not enabled' do
1020
- bogus_response = smb1_extended_response
1021
- bogus_response.parameter_block.capabilities.extended_security = 0
1022
- expect { smb1_client.negotiate_response(bogus_response.to_binary_s) }.to raise_error(RubySMB::Error::InvalidPacket)
1023
- end
1024
1034
  end
1025
1035
 
1026
1036
  context 'with only SMB2' do
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::Compression::LZNT1 do
4
+ describe '.compress' do
5
+ it 'generates an empty blob when provided an empty blob' do
6
+ expected = "".b
7
+ expect(described_class.compress('')).to eq(expected)
8
+ end
9
+
10
+ it 'generates a compressed blob when provided a string with non-reoccurring characters' do
11
+ expect(described_class.compress('RubySMB')).to eq("\x060RubySMB".b)
12
+ end
13
+
14
+ it 'generates a compressed blob when provided a string of reoccurring characters' do
15
+ expect(described_class.compress("\x01" * 0x200)).to eq("\x03\xB0\x02\x01\xFC\x01".b)
16
+ end
17
+ end
18
+
19
+ describe '.decompress' do
20
+ it 'generates a decompressed blob for a string with non-reoccurring characters' do
21
+ expect(described_class.decompress("\x060RubySMB".b)).to eq('RubySMB')
22
+ end
23
+
24
+ it 'generates a decompressed blob for a string of reoccurring characters' do
25
+ expect(described_class.decompress("\x03\xB0\x02\x01\xFC\x01".b)).to eq("\x01" * 0x200)
26
+ end
27
+
28
+ it 'raises an EncodingError when the length is invalid' do
29
+ expect { described_class.decompress("\x010".b) }.to raise_error(EncodingError)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,69 @@
1
+ RSpec.describe RubySMB::Dcerpc::Netlogon::NetrServerAuthenticate3Request do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :primary_name }
5
+ it { is_expected.to respond_to :account_name }
6
+ it { is_expected.to respond_to :secure_channel_type }
7
+ it { is_expected.to respond_to :computer_name }
8
+ it { is_expected.to respond_to :client_credential }
9
+ it { is_expected.to respond_to :flags }
10
+
11
+ it 'is little endian' do
12
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
13
+ end
14
+
15
+ describe '#primary_name' do
16
+ it 'is a LogonsrvHandle structure' do
17
+ expect(packet.primary_name).to be_a RubySMB::Dcerpc::Netlogon::LogonsrvHandle
18
+ end
19
+ end
20
+
21
+ describe '#account_name' do
22
+ it 'is a NdrString structure' do
23
+ expect(packet.account_name).to be_a RubySMB::Dcerpc::Ndr::NdrString
24
+ end
25
+ end
26
+
27
+ describe '#secure_channel_type' do
28
+ it 'is a NetlogonSecureChannelType enum' do
29
+ expect(packet.secure_channel_type).to be_a RubySMB::Dcerpc::Netlogon::NetlogonSecureChannelType
30
+ end
31
+ end
32
+
33
+ describe '#computer_name' do
34
+ it 'is a NdrString structure' do
35
+ expect(packet.computer_name).to be_a RubySMB::Dcerpc::Ndr::NdrString
36
+ end
37
+ end
38
+
39
+ describe '#client_credential' do
40
+ it 'is a NetlogonCredential structure' do
41
+ expect(packet.client_credential).to be_a RubySMB::Dcerpc::Netlogon::NetlogonCredential
42
+ end
43
+ end
44
+
45
+ describe '#flags' do
46
+ it 'is a 32-bit unsigned integer' do
47
+ expect(packet.flags).to be_a BinData::Uint32le
48
+ end
49
+ end
50
+
51
+ describe '#initialize_instance' do
52
+ it 'sets #opnum to NETR_SERVER_AUTHENTICATE3 constant' do
53
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Netlogon::NETR_SERVER_AUTHENTICATE3)
54
+ end
55
+ end
56
+
57
+ it 'reads its own binary representation and outputs the same packet' do
58
+ packet = described_class.new(
59
+ primary_name: 'primary_name',
60
+ account_name: 'account_name',
61
+ secure_channel_type: 0,
62
+ computer_name: 'computer_name',
63
+ client_credential: "\x00" * 8,
64
+ flags: rand(0xffffffff)
65
+ )
66
+ binary = packet.to_binary_s
67
+ expect(described_class.read(binary)).to eq(packet)
68
+ end
69
+ end
@@ -0,0 +1,53 @@
1
+ RSpec.describe RubySMB::Dcerpc::Netlogon::NetrServerAuthenticate3Response do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :server_credential }
5
+ it { is_expected.to respond_to :negotiate_flags }
6
+ it { is_expected.to respond_to :account_rid }
7
+ it { is_expected.to respond_to :error_status }
8
+
9
+ it 'is little endian' do
10
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
11
+ end
12
+
13
+ describe '#server_credential' do
14
+ it 'is a NetlogonCredential structure' do
15
+ expect(packet.server_credential).to be_a RubySMB::Dcerpc::Netlogon::NetlogonCredential
16
+ end
17
+ end
18
+
19
+ describe '#negotiate_flags' do
20
+ it 'is a 32-bit unsigned integer' do
21
+ expect(packet.negotiate_flags).to be_a BinData::Uint32le
22
+ end
23
+ end
24
+
25
+ describe '#account_rid' do
26
+ it 'is a 32-bit unsigned integer' do
27
+ expect(packet.account_rid).to be_a BinData::Uint32le
28
+ end
29
+ end
30
+
31
+ describe '#error_status' do
32
+ it 'is a 32-bit unsigned integer' do
33
+ expect(packet.error_status).to be_a BinData::Uint32le
34
+ end
35
+ end
36
+
37
+ describe '#initialize_instance' do
38
+ it 'sets #opnum to NETR_SERVER_AUTHENTICATE3 constant' do
39
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Netlogon::NETR_SERVER_AUTHENTICATE3)
40
+ end
41
+ end
42
+
43
+ it 'reads its own binary representation and outputs the same packet' do
44
+ packet = described_class.new(
45
+ server_credential: "\x00" * 8,
46
+ negotiate_flags: rand(0xffffffff),
47
+ account_rid: rand(0xffffffff),
48
+ error_status: rand(0xffffffff)
49
+ )
50
+ binary = packet.to_binary_s
51
+ expect(described_class.read(binary)).to eq(packet)
52
+ end
53
+ end
@@ -0,0 +1,69 @@
1
+ RSpec.describe RubySMB::Dcerpc::Netlogon::NetrServerPasswordSet2Request do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :primary_name }
5
+ it { is_expected.to respond_to :account_name }
6
+ it { is_expected.to respond_to :secure_channel_type }
7
+ it { is_expected.to respond_to :computer_name }
8
+ it { is_expected.to respond_to :authenticator }
9
+ it { is_expected.to respond_to :clear_new_password }
10
+
11
+ it 'is little endian' do
12
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
13
+ end
14
+
15
+ describe '#primary_name' do
16
+ it 'is a LogonsrvHandle structure' do
17
+ expect(packet.primary_name).to be_a RubySMB::Dcerpc::Netlogon::LogonsrvHandle
18
+ end
19
+ end
20
+
21
+ describe '#account_name' do
22
+ it 'is a NdrString structure' do
23
+ expect(packet.account_name).to be_a RubySMB::Dcerpc::Ndr::NdrString
24
+ end
25
+ end
26
+
27
+ describe '#secure_channel_type' do
28
+ it 'is a NetlogonSecureChannelType enum' do
29
+ expect(packet.secure_channel_type).to be_a RubySMB::Dcerpc::Netlogon::NetlogonSecureChannelType
30
+ end
31
+ end
32
+
33
+ describe '#computer_name' do
34
+ it 'is a NdrString structure' do
35
+ expect(packet.computer_name).to be_a RubySMB::Dcerpc::Ndr::NdrString
36
+ end
37
+ end
38
+
39
+ describe '#authenticator' do
40
+ it 'is a NetlogonAuthenticator structure' do
41
+ expect(packet.authenticator).to be_a RubySMB::Dcerpc::Netlogon::NetlogonAuthenticator
42
+ end
43
+ end
44
+
45
+ describe '#clear_new_password' do
46
+ it 'is a NdrFixedByteArray structure' do
47
+ expect(packet.clear_new_password).to be_a RubySMB::Dcerpc::Ndr::NdrFixedByteArray
48
+ end
49
+ end
50
+
51
+ describe '#initialize_instance' do
52
+ it 'sets #opnum to NETR_SERVER_PASSWORD_SET2 constant' do
53
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Netlogon::NETR_SERVER_PASSWORD_SET2)
54
+ end
55
+ end
56
+
57
+ it 'reads its own binary representation and outputs the same packet' do
58
+ packet = described_class.new(
59
+ primary_name: 'primary_name',
60
+ account_name: 'account_name',
61
+ secure_channel_type: 0,
62
+ computer_name: 'computer_name',
63
+ authenticator: RubySMB::Dcerpc::Netlogon::NetlogonAuthenticator.new,
64
+ clear_new_password: "\x00" * 516
65
+ )
66
+ binary = packet.to_binary_s
67
+ expect(described_class.read(binary)).to eq(packet)
68
+ end
69
+ end
@@ -0,0 +1,37 @@
1
+ RSpec.describe RubySMB::Dcerpc::Netlogon::NetrServerPasswordSet2Response do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :return_authenticator }
5
+ it { is_expected.to respond_to :error_status }
6
+
7
+ it 'is little endian' do
8
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
9
+ end
10
+
11
+ describe '#return_authenticator' do
12
+ it 'is a NetlogonAuthenticator structure' do
13
+ expect(packet.return_authenticator).to be_a RubySMB::Dcerpc::Netlogon::NetlogonAuthenticator
14
+ end
15
+ end
16
+
17
+ describe '#error_status' do
18
+ it 'is a 32-bit unsigned integer' do
19
+ expect(packet.error_status).to be_a BinData::Uint32le
20
+ end
21
+ end
22
+
23
+ describe '#initialize_instance' do
24
+ it 'sets #opnum to NETR_SERVER_PASSWORD_SET2 constant' do
25
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Netlogon::NETR_SERVER_PASSWORD_SET2)
26
+ end
27
+ end
28
+
29
+ it 'reads its own binary representation and outputs the same packet' do
30
+ packet = described_class.new(
31
+ return_authenticator: RubySMB::Dcerpc::Netlogon::NetlogonAuthenticator.new,
32
+ error_status: rand(0xffffffff)
33
+ )
34
+ binary = packet.to_binary_s
35
+ expect(described_class.read(binary)).to eq(packet)
36
+ end
37
+ end
@@ -0,0 +1,45 @@
1
+ RSpec.describe RubySMB::Dcerpc::Netlogon::NetrServerReqChallengeRequest do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :primary_name }
5
+ it { is_expected.to respond_to :computer_name }
6
+ it { is_expected.to respond_to :client_challenge }
7
+
8
+ it 'is little endian' do
9
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
10
+ end
11
+
12
+ describe '#primary_name' do
13
+ it 'is a LogonsrvHandle structure' do
14
+ expect(packet.primary_name).to be_a RubySMB::Dcerpc::Netlogon::LogonsrvHandle
15
+ end
16
+ end
17
+
18
+ describe '#computer_name' do
19
+ it 'is a NdrString structure' do
20
+ expect(packet.computer_name).to be_a RubySMB::Dcerpc::Ndr::NdrString
21
+ end
22
+ end
23
+
24
+ describe '#client_challenge' do
25
+ it 'is a NetlogonCredential structure' do
26
+ expect(packet.client_challenge).to be_a RubySMB::Dcerpc::Netlogon::NetlogonCredential
27
+ end
28
+ end
29
+
30
+ describe '#initialize_instance' do
31
+ it 'sets #opnum to NETR_SERVER_REQ_CHALLENGE constant' do
32
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Netlogon::NETR_SERVER_REQ_CHALLENGE)
33
+ end
34
+ end
35
+
36
+ it 'reads its own binary representation and outputs the same packet' do
37
+ packet = described_class.new(
38
+ primary_name: 'primary_name',
39
+ computer_name: 'computer_name',
40
+ client_challenge: "\x00" * 8,
41
+ )
42
+ binary = packet.to_binary_s
43
+ expect(described_class.read(binary)).to eq(packet)
44
+ end
45
+ end