ruby_smb 1.0.4 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.travis.yml +3 -2
  5. data/Gemfile +6 -2
  6. data/README.md +35 -47
  7. data/examples/enum_registry_key.rb +28 -0
  8. data/examples/enum_registry_values.rb +30 -0
  9. data/examples/negotiate.rb +51 -8
  10. data/examples/pipes.rb +2 -1
  11. data/examples/read_file_encryption.rb +56 -0
  12. data/examples/read_registry_key_value.rb +32 -0
  13. data/lib/ruby_smb.rb +4 -1
  14. data/lib/ruby_smb/client.rb +207 -18
  15. data/lib/ruby_smb/client/authentication.rb +27 -8
  16. data/lib/ruby_smb/client/encryption.rb +62 -0
  17. data/lib/ruby_smb/client/negotiation.rb +153 -12
  18. data/lib/ruby_smb/client/signing.rb +19 -0
  19. data/lib/ruby_smb/client/tree_connect.rb +4 -4
  20. data/lib/ruby_smb/client/utils.rb +8 -7
  21. data/lib/ruby_smb/client/winreg.rb +46 -0
  22. data/lib/ruby_smb/crypto.rb +30 -0
  23. data/lib/ruby_smb/dcerpc.rb +38 -0
  24. data/lib/ruby_smb/dcerpc/bind.rb +2 -2
  25. data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
  26. data/lib/ruby_smb/dcerpc/error.rb +3 -0
  27. data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
  28. data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
  29. data/lib/ruby_smb/dcerpc/request.rb +28 -9
  30. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
  31. data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
  32. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
  33. data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
  34. data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
  35. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
  36. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
  37. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
  38. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
  39. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
  40. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
  41. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
  42. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
  43. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
  44. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
  45. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
  46. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
  47. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
  48. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
  49. data/lib/ruby_smb/dispatcher/socket.rb +4 -3
  50. data/lib/ruby_smb/error.rb +28 -1
  51. data/lib/ruby_smb/smb1/commands.rb +1 -1
  52. data/lib/ruby_smb/smb1/file.rb +6 -4
  53. data/lib/ruby_smb/smb1/packet/empty_packet.rb +4 -2
  54. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +1 -1
  55. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +2 -2
  56. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
  57. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -2
  58. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +1 -1
  59. data/lib/ruby_smb/smb1/pipe.rb +79 -3
  60. data/lib/ruby_smb/smb1/tree.rb +12 -3
  61. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
  62. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
  63. data/lib/ruby_smb/smb2/file.rb +25 -43
  64. data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
  65. data/lib/ruby_smb/smb2/packet.rb +2 -0
  66. data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
  67. data/lib/ruby_smb/smb2/packet/error_packet.rb +9 -4
  68. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -14
  69. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +50 -4
  70. data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
  71. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +92 -6
  72. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +8 -26
  73. data/lib/ruby_smb/smb2/pipe.rb +77 -3
  74. data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
  75. data/lib/ruby_smb/smb2/tree.rb +23 -17
  76. data/lib/ruby_smb/version.rb +1 -1
  77. data/ruby_smb.gemspec +5 -3
  78. data/spec/lib/ruby_smb/client_spec.rb +1441 -61
  79. data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
  80. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
  81. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
  82. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
  83. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
  84. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
  85. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
  86. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
  87. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
  88. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
  89. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
  90. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
  91. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
  92. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
  93. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
  94. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
  95. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
  96. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
  97. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
  98. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
  99. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
  100. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
  101. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
  102. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
  103. data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
  104. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +2 -2
  105. data/spec/lib/ruby_smb/error_spec.rb +59 -0
  106. data/spec/lib/ruby_smb/smb1/file_spec.rb +9 -1
  107. data/spec/lib/ruby_smb/smb1/packet/empty_packet_spec.rb +10 -0
  108. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
  109. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
  110. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
  111. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
  112. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +210 -148
  113. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
  114. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
  115. data/spec/lib/ruby_smb/smb2/file_spec.rb +86 -62
  116. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
  117. data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
  118. data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +29 -2
  119. data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
  120. data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
  121. data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
  122. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
  123. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -30
  124. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +220 -149
  125. data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
  126. data/spec/lib/ruby_smb/smb2/tree_spec.rb +53 -8
  127. metadata +187 -81
  128. metadata.gz.sig +0 -0
  129. data/lib/ruby_smb/smb1/dcerpc.rb +0 -72
  130. data/lib/ruby_smb/smb2/dcerpc.rb +0 -75
@@ -69,11 +69,51 @@ RSpec.describe RubySMB::Dcerpc::Request do
69
69
  expect(packet.stub).to be_a BinData::Choice
70
70
  end
71
71
 
72
- context 'with a NetShareEnumAll stub' do
72
+ context 'with a Srvsvc endpoint' do
73
+ let(:host) { '1.2.3.4' }
74
+ let(:packet) do
75
+ described_class.new(
76
+ { :opnum => RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL },
77
+ { :endpoint => 'Srvsvc', :host => host }
78
+ )
79
+ end
80
+
81
+ it 'uses endpoint parameter to select a Srvsvc stub packet' do
82
+ expect(packet.stub.selection).to eq('Srvsvc')
83
+ end
84
+
85
+ it 'selects the expected packet structure' do
86
+ expect(packet.stub).to eq(RubySMB::Dcerpc::Srvsvc::NetShareEnumAll.new(host: host))
87
+ end
88
+ end
89
+
90
+ context 'with a Winreg endpoint' do
91
+ let(:opnum) { RubySMB::Dcerpc::Winreg::OPEN_HKCR }
92
+ let(:packet) do
93
+ described_class.new(
94
+ { :opnum => opnum },
95
+ { :endpoint => 'Winreg' }
96
+ )
97
+ end
73
98
 
74
- it 'uses opnum as a selector' do
75
- packet = described_class.new({ :opnum => RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL }, host: '1.2.3.4')
76
- expect(packet.stub.selection).to eq(packet.opnum)
99
+ it 'uses endpoint parameter to select a Winreg stub packet' do
100
+ expect(packet.stub.selection).to eq('Winreg')
101
+ end
102
+
103
+ it 'selects the expected packet structure' do
104
+ expect(packet.stub).to eq(RubySMB::Dcerpc::Winreg::OpenRootKeyRequest.new(opnum: opnum))
105
+ end
106
+ end
107
+
108
+ context 'with an unknown endpoint' do
109
+ let(:packet) do
110
+ described_class.new(
111
+ { :endpoint => 'Unknown' }
112
+ )
113
+ end
114
+
115
+ it 'sets #stub to an empty string' do
116
+ expect(packet.stub).to eq('')
77
117
  end
78
118
  end
79
119
  end
@@ -102,13 +142,16 @@ RSpec.describe RubySMB::Dcerpc::Request do
102
142
  end
103
143
 
104
144
  it 'reads its own binary representation and output the same packet' do
105
- packet = described_class.new({ :opnum => RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL }, host: '1.2.3.4')
145
+ packet = described_class.new(
146
+ { :opnum => RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL },
147
+ { :endpoint => 'Srvsvc', :host => '1.2.3.4' }
148
+ )
106
149
  packet.pdu_header.pfc_flags.object_uuid = 1
107
150
  packet.object = '8a885d04-1ceb-11c9-9fe8-08002b104860'
108
151
  packet.auth_verifier = '123456'
109
152
  packet.pdu_header.auth_length = 6
110
153
  binary = packet.to_binary_s
111
- expect(described_class.read(binary)).to eq(packet)
154
+ packet2 = described_class.new( { :endpoint => 'Srvsvc' } )
155
+ expect(packet2.read(binary)).to eq(packet)
112
156
  end
113
157
  end
114
-
@@ -0,0 +1,98 @@
1
+ RSpec.describe RubySMB::Dcerpc::RrpUnicodeString do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :buffer_length }
5
+ it { is_expected.to respond_to :maximum_length }
6
+ it { is_expected.to respond_to :buffer }
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 '#buffer_length' do
13
+ it 'should be a 16-bit unsigned integer' do
14
+ expect(packet.buffer_length).to be_a BinData::Uint16le
15
+ end
16
+
17
+ it 'is set to 0 when #buffer in empty' do
18
+ expect(packet.buffer_length).to eq(0)
19
+ end
20
+ end
21
+
22
+ describe '#maximum_length' do
23
+ it 'should be a 16-bit unsigned integer' do
24
+ expect(packet.maximum_length).to be_a BinData::Uint16le
25
+ end
26
+ end
27
+
28
+ describe '#buffer' do
29
+ it 'should be a NdrLpStr' do
30
+ expect(packet.buffer).to be_a RubySMB::Dcerpc::Ndr::NdrLpStr
31
+ end
32
+ end
33
+
34
+ describe '#get' do
35
+ it 'returns #buffer' do
36
+ packet.buffer = 'spec_test'
37
+ expect(packet.get).to eq(RubySMB::Dcerpc::Ndr::NdrLpStr.new('spec_test'))
38
+ end
39
+ end
40
+
41
+ describe '#set' do
42
+ it 'sets #buffer to the expected value' do
43
+ packet.set('spec_test')
44
+ expect(packet.buffer).to eq(RubySMB::Dcerpc::Ndr::NdrLpStr.new('spec_test'))
45
+ end
46
+
47
+ it 'sets #buffer_length to the expected value' do
48
+ packet.set('spec_test')
49
+ expect(packet.buffer_length).to eq(('spec_test'.size + 1) * 2)
50
+ end
51
+
52
+ it 'sets #maximum_length to the expected value' do
53
+ packet.set('spec_test')
54
+ expect(packet.maximum_length).to eq(('spec_test'.size + 1) * 2)
55
+ end
56
+
57
+ context 'when the value is 0' do
58
+ it 'sets #buffer_length to 0' do
59
+ packet.set(0)
60
+ expect(packet.buffer_length).to eq(0)
61
+ end
62
+
63
+ it 'sets #maximum_length to 0' do
64
+ packet.set(0)
65
+ expect(packet.maximum_length).to eq(0)
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ RSpec.describe RubySMB::Dcerpc::PrrpUnicodeString do
72
+ it 'is NdrTopLevelFullPointer subclass' do
73
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrTopLevelFullPointer
74
+ end
75
+
76
+ subject(:packet) { described_class.new }
77
+
78
+ it { is_expected.to respond_to :referent }
79
+
80
+ it 'is little endian' do
81
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
82
+ end
83
+
84
+ describe '#referent' do
85
+ it 'is a RrpUnicodeString' do
86
+ expect(packet.referent).to be_a RubySMB::Dcerpc::RrpUnicodeString
87
+ end
88
+
89
+ it 'exists if superclass #referent_identifier is not zero' do
90
+ expect(packet.referent?).to be true
91
+ end
92
+
93
+ it 'does not exist if superclass #referent_identifier is zero' do
94
+ packet.referent_identifier = 0
95
+ expect(packet.referent?).to be false
96
+ end
97
+ end
98
+ end
@@ -15,11 +15,18 @@ RSpec.describe RubySMB::Dcerpc::Srvsvc::NetShareEnumAll do
15
15
  it { is_expected.to respond_to :max_buffer }
16
16
  it { is_expected.to respond_to :resume_referent_id }
17
17
  it { is_expected.to respond_to :resume_handle }
18
+ it { is_expected.to respond_to :opnum }
18
19
 
19
20
  it 'is little endian' do
20
21
  expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
21
22
  end
22
23
 
24
+ context 'when \'host\' parameter is not provided' do
25
+ it 'raises an ArgumentError' do
26
+ expect { described_class.new }.to raise_error(ArgumentError)
27
+ end
28
+ end
29
+
23
30
  describe '#referent_id' do
24
31
  it 'should be a 32-bit unsigned integer' do
25
32
  expect(packet.referent_id).to be_a BinData::Uint32le
@@ -156,6 +163,12 @@ RSpec.describe RubySMB::Dcerpc::Srvsvc::NetShareEnumAll do
156
163
  end
157
164
  end
158
165
 
166
+ describe '#initialize_instance' do
167
+ it 'sets #opnum to REG_CLOSE_KEY constant' do
168
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL)
169
+ end
170
+ end
171
+
159
172
  describe '#pad_length' do
160
173
  it 'returns 0 when #level is already 4-byte aligned' do
161
174
  expect(packet.pad_length).to eq 0
@@ -0,0 +1,60 @@
1
+ RSpec.describe RubySMB::Dcerpc::Srvsvc do
2
+ let(:srvsvc) do
3
+ RubySMB::SMB1::Pipe.new(
4
+ tree: double('Tree'),
5
+ response: RubySMB::SMB1::Packet::NtCreateAndxResponse.new,
6
+ name: 'srvsvc'
7
+ )
8
+ end
9
+
10
+ describe '#net_share_enum_all' do
11
+ let(:host) { '1.2.3.4' }
12
+ let(:request_packet) { double('NetShareEnumAll request packet') }
13
+ let(:dcerpc_response) { double('DCERPC response') }
14
+ let(:shares) do
15
+ [
16
+ ["C$", "DISK", "Default share"],
17
+ ["Shared", "DISK", ""],
18
+ ["IPC$", "IPC", "Remote IPC"],
19
+ ["ADMIN$", "DISK", "Remote Admin"]
20
+ ]
21
+ end
22
+
23
+ before :example do
24
+ allow(srvsvc).to receive(:bind)
25
+ allow(RubySMB::Dcerpc::Srvsvc::NetShareEnumAll).to receive(:new).and_return(request_packet)
26
+ allow(srvsvc).to receive(:dcerpc_request).and_return(dcerpc_response)
27
+ allow(RubySMB::Dcerpc::Srvsvc::NetShareEnumAll).to receive(:parse_response).and_return(shares)
28
+ end
29
+
30
+ it 'calls #bind with the expected arguments' do
31
+ srvsvc.net_share_enum_all(host)
32
+ expect(srvsvc).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Srvsvc)
33
+ end
34
+
35
+ it 'creates the expected NetShareEnumAll packet' do
36
+ srvsvc.net_share_enum_all(host)
37
+ expect(RubySMB::Dcerpc::Srvsvc::NetShareEnumAll).to have_received(:new).with(host: host)
38
+ end
39
+
40
+ it 'calls #request with the expected arguments' do
41
+ srvsvc.net_share_enum_all(host)
42
+ expect(srvsvc).to have_received(:dcerpc_request).with(request_packet)
43
+ end
44
+
45
+ it 'parse the response with NetShareEnumAll #parse_response method' do
46
+ srvsvc.net_share_enum_all(host)
47
+ expect(RubySMB::Dcerpc::Srvsvc::NetShareEnumAll).to have_received(:parse_response).with(dcerpc_response)
48
+ end
49
+
50
+ it 'returns the remote shares' do
51
+ output = [
52
+ {:name=>"C$", :type=>"DISK", :comment=>"Default share"},
53
+ {:name=>"Shared", :type=>"DISK", :comment=>""},
54
+ {:name=>"IPC$", :type=>"IPC", :comment=>"Remote IPC"},
55
+ {:name=>"ADMIN$", :type=>"DISK", :comment=>"Remote Admin"},
56
+ ]
57
+ expect(srvsvc.net_share_enum_all(host)).to eq(output)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,28 @@
1
+ RSpec.describe RubySMB::Dcerpc::Winreg::RpcHkey do
2
+ it 'is NdrContextHandle subclass' do
3
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrContextHandle
4
+ end
5
+ end
6
+
7
+ RSpec.describe RubySMB::Dcerpc::Winreg::CloseKeyRequest do
8
+ subject(:packet) { described_class.new }
9
+
10
+ it { is_expected.to respond_to :hkey }
11
+ it { is_expected.to respond_to :opnum }
12
+
13
+ it 'is little endian' do
14
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
15
+ end
16
+
17
+ describe '#hkey' do
18
+ it 'is a RpcHkey structure' do
19
+ expect(packet.hkey).to be_a RubySMB::Dcerpc::Winreg::RpcHkey
20
+ end
21
+ end
22
+
23
+ describe '#initialize_instance' do
24
+ it 'sets #opnum to REG_CLOSE_KEY constant' do
25
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Winreg::REG_CLOSE_KEY)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,36 @@
1
+ RSpec.describe RubySMB::Dcerpc::Winreg::RpcHkey do
2
+ it 'is NdrContextHandle subclass' do
3
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrContextHandle
4
+ end
5
+ end
6
+
7
+ RSpec.describe RubySMB::Dcerpc::Winreg::CloseKeyResponse do
8
+ subject(:packet) { described_class.new }
9
+
10
+ it { is_expected.to respond_to :hkey }
11
+ it { is_expected.to respond_to :error_status }
12
+ it { is_expected.to respond_to :opnum }
13
+
14
+ it 'is little endian' do
15
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
16
+ end
17
+
18
+ describe '#hkey' do
19
+ it 'is a RpcHkey structure' do
20
+ expect(packet.hkey).to be_a RubySMB::Dcerpc::Winreg::RpcHkey
21
+ end
22
+ end
23
+
24
+ describe '#error_status' do
25
+ it 'is a 32-bit unsigned integer' do
26
+ expect(packet.error_status).to be_a BinData::Uint32le
27
+ end
28
+ end
29
+
30
+ describe '#initialize_instance' do
31
+ it 'sets #opnum to REG_CLOSE_KEY constant' do
32
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Winreg::REG_CLOSE_KEY)
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,108 @@
1
+ RSpec.describe RubySMB::Dcerpc::Winreg::RpcHkey do
2
+ it 'is NdrContextHandle subclass' do
3
+ expect(described_class).to be < RubySMB::Dcerpc::Ndr::NdrContextHandle
4
+ end
5
+ end
6
+
7
+ RSpec.describe RubySMB::Dcerpc::Winreg::EnumKeyRequest do
8
+ subject(:packet) { described_class.new }
9
+
10
+ it { is_expected.to respond_to :hkey }
11
+ it { is_expected.to respond_to :dw_index }
12
+ it { is_expected.to respond_to :lp_name }
13
+ it { is_expected.to respond_to :pad1 }
14
+ it { is_expected.to respond_to :lp_class }
15
+ it { is_expected.to respond_to :pad2 }
16
+ it { is_expected.to respond_to :lpft_last_write_time }
17
+ it { is_expected.to respond_to :opnum }
18
+
19
+ it 'is little endian' do
20
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
21
+ end
22
+
23
+ describe '#hkey' do
24
+ it 'is a RpcHkey structure' do
25
+ expect(packet.hkey).to be_a RubySMB::Dcerpc::Winreg::RpcHkey
26
+ end
27
+ end
28
+
29
+ describe '#dw_index' do
30
+ it 'is a 32-bit unsigned integer' do
31
+ expect(packet.dw_index).to be_a BinData::Uint32le
32
+ end
33
+ end
34
+
35
+ describe '#lp_name' do
36
+ it 'is a RrpUnicodeString structure' do
37
+ expect(packet.lp_name).to be_a RubySMB::Dcerpc::RrpUnicodeString
38
+ end
39
+ end
40
+
41
+ describe '#pad1' do
42
+ it 'is a string' do
43
+ expect(packet.pad1).to be_a BinData::String
44
+ end
45
+
46
+ it 'should keep #lp_class 4-byte aligned' do
47
+ packet.lp_name = "test"
48
+ expect(packet.lp_class.abs_offset % 4).to eq 0
49
+ end
50
+ end
51
+
52
+ describe '#lp_class' do
53
+ it 'is a PrrpUnicodeString structure' do
54
+ expect(packet.lp_class).to be_a RubySMB::Dcerpc::PrrpUnicodeString
55
+ end
56
+
57
+ it 'has a initial value of 0' do
58
+ expect(packet.lp_class).to eq(0)
59
+ end
60
+ end
61
+
62
+ describe '#pad2' do
63
+ it 'is a string' do
64
+ expect(packet.pad2).to be_a BinData::String
65
+ end
66
+
67
+ it 'should keep #lpft_last_write_time 4-byte aligned' do
68
+ packet.lp_class = "test"
69
+ expect(packet.lpft_last_write_time.abs_offset % 4).to eq 0
70
+ end
71
+ end
72
+
73
+ describe '#lpft_last_write_time' do
74
+ it 'is a NdrLpFileTime structure' do
75
+ expect(packet.lpft_last_write_time).to be_a RubySMB::Dcerpc::Ndr::NdrLpFileTime
76
+ end
77
+ end
78
+
79
+ describe '#initialize_instance' do
80
+ it 'sets #opnum to REG_ENUM_KEY constant' do
81
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Winreg::REG_ENUM_KEY)
82
+ end
83
+ end
84
+
85
+ describe '#pad_length1' do
86
+ it 'returns 0 when #lp_class is already 4-byte aligned' do
87
+ packet.lp_name = 'align'
88
+ expect(packet.pad_length1).to eq 0
89
+ end
90
+
91
+ it 'returns 2 when #lp_class is only 2-byte aligned' do
92
+ packet.lp_name = 'align' + 'A'
93
+ expect(packet.pad_length1).to eq 2
94
+ end
95
+ end
96
+
97
+ describe '#pad_length2' do
98
+ it 'returns 0 when #lpft_last_write_time is already 4-byte aligned' do
99
+ packet.lp_class = 'align'
100
+ expect(packet.pad_length2).to eq 0
101
+ end
102
+
103
+ it 'returns 2 when #lpft_last_write_time is only 2-byte aligned' do
104
+ packet.lp_class = 'align' + 'A'
105
+ expect(packet.pad_length2).to eq 2
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,97 @@
1
+ RSpec.describe RubySMB::Dcerpc::Winreg::EnumKeyResponse do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :lp_name }
5
+ it { is_expected.to respond_to :pad1 }
6
+ it { is_expected.to respond_to :lp_class }
7
+ it { is_expected.to respond_to :pad2 }
8
+ it { is_expected.to respond_to :lpft_last_write_time }
9
+ it { is_expected.to respond_to :error_status }
10
+ it { is_expected.to respond_to :opnum }
11
+
12
+ it 'is little endian' do
13
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
14
+ end
15
+
16
+
17
+ describe '#lp_name' do
18
+ it 'is a RrpUnicodeString structure' do
19
+ expect(packet.lp_name).to be_a RubySMB::Dcerpc::RrpUnicodeString
20
+ end
21
+ end
22
+
23
+ describe '#pad1' do
24
+ it 'is a string' do
25
+ expect(packet.pad1).to be_a BinData::String
26
+ end
27
+
28
+ it 'should keep #lp_class 4-byte aligned' do
29
+ packet.lp_name = "test"
30
+ expect(packet.lp_class.abs_offset % 4).to eq 0
31
+ end
32
+ end
33
+
34
+ describe '#lp_class' do
35
+ it 'is a PrrpUnicodeString structure' do
36
+ expect(packet.lp_class).to be_a RubySMB::Dcerpc::PrrpUnicodeString
37
+ end
38
+
39
+ it 'has a initial value of 0' do
40
+ expect(packet.lp_class).to eq(0)
41
+ end
42
+ end
43
+
44
+ describe '#pad2' do
45
+ it 'is a string' do
46
+ expect(packet.pad2).to be_a BinData::String
47
+ end
48
+
49
+ it 'should keep #lpft_last_write_time 4-byte aligned' do
50
+ packet.lp_class = "test"
51
+ expect(packet.lpft_last_write_time.abs_offset % 4).to eq 0
52
+ end
53
+ end
54
+
55
+ describe '#lpft_last_write_time' do
56
+ it 'is a NdrLpFileTime structure' do
57
+ expect(packet.lpft_last_write_time).to be_a RubySMB::Dcerpc::Ndr::NdrLpFileTime
58
+ end
59
+ end
60
+
61
+ describe '#error_status' do
62
+ it 'is a 32-bit unsigned integer' do
63
+ expect(packet.error_status).to be_a BinData::Uint32le
64
+ end
65
+ end
66
+
67
+ describe '#initialize_instance' do
68
+ it 'sets #opnum to REG_ENUM_KEY constant' do
69
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Winreg::REG_ENUM_KEY)
70
+ end
71
+ end
72
+
73
+ describe '#pad_length1' do
74
+ it 'returns 0 when #lp_class is already 4-byte aligned' do
75
+ packet.lp_name = 'align'
76
+ expect(packet.pad_length1).to eq 0
77
+ end
78
+
79
+ it 'returns 2 when #lp_class is only 2-byte aligned' do
80
+ packet.lp_name = 'align' + 'A'
81
+ expect(packet.pad_length1).to eq 2
82
+ end
83
+ end
84
+
85
+ describe '#pad_length2' do
86
+ it 'returns 0 when #lpft_last_write_time is already 4-byte aligned' do
87
+ packet.lp_class = 'align'
88
+ expect(packet.pad_length2).to eq 0
89
+ end
90
+
91
+ it 'returns 2 when #lpft_last_write_time is only 2-byte aligned' do
92
+ packet.lp_class = 'align' + 'A'
93
+ expect(packet.pad_length2).to eq 2
94
+ end
95
+ end
96
+ end
97
+