1 # Blackbox tests for ndrdump
2 # Copyright (C) 2008 Andrew Tridgell <tridge@samba.org>
3 # Copyright (C) 2008 Andrew Bartlett <abartlet@samba.org>
4 # Copyright (C) 2010 Jelmer Vernooij <jelmer@samba.org>
5 # based on test_smbclient.sh
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 from __future__ import print_function
22 """Blackbox tests for ndrdump."""
25 from samba.tests import BlackboxTestCase, BlackboxProcessError
27 for p in ["../../../../../source4/librpc/tests",
28 "../../../../../librpc/tests"]:
29 data_path_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), p))
31 if os.path.exists(data_path_dir):
35 class NdrDumpTests(BlackboxTestCase):
36 """Blackbox tests for ndrdump."""
38 def data_path(self, name):
39 return os.path.join(data_path_dir, name)
41 def test_ndrdump_with_in(self):
42 self.check_run(("ndrdump samr samr_CreateUser in %s" %
43 (self.data_path("samr-CreateUser-in.dat"))))
45 def test_ndrdump_with_out(self):
46 self.check_run(("ndrdump samr samr_CreateUser out %s" %
47 (self.data_path("samr-CreateUser-out.dat"))))
49 def test_ndrdump_context_file(self):
51 ("ndrdump --context-file %s samr samr_CreateUser out %s" %
52 (self.data_path("samr-CreateUser-in.dat"),
53 self.data_path("samr-CreateUser-out.dat"))))
55 def test_ndrdump_with_validate(self):
56 self.check_run(("ndrdump --validate samr samr_CreateUser in %s" %
57 (self.data_path("samr-CreateUser-in.dat"))))
59 def test_ndrdump_with_hex_decode_function(self):
61 ("ndrdump dns decode_dns_name_packet in --hex-input %s" %
62 self.data_path("dns-decode_dns_name_packet-hex.dat")))
64 def test_ndrdump_with_hex_struct_name(self):
65 expected = open(self.data_path("dns-decode_dns_name_packet-hex.txt")).read()
67 actual = self.check_output(
68 "ndrdump dns dns_name_packet struct --hex-input %s" %
69 self.data_path("dns-decode_dns_name_packet-hex.dat"))
70 except BlackboxProcessError as e:
73 # check_output will return bytes
74 # convert expected to bytes for python 3
75 self.assertEqual(actual, expected.encode('utf-8'))
77 def test_ndrdump_with_binary_struct_name(self):
78 # Prefix of the expected unparsed PAC data (without times, as
80 expected = '''pull returned Success
81 PAC_DATA: struct PAC_DATA
82 num_buffers : 0x00000005 (5)
83 version : 0x00000000 (0)
86 actual = self.check_output(
87 "ndrdump krb5pac PAC_DATA struct %s" %
88 self.data_path("krb5pac-PAC_DATA.dat"))
89 except BlackboxProcessError as e:
92 # check_output will return bytes
93 # convert expected to bytes for python 3
94 self.assertEqual(actual[:len(expected)],
95 expected.encode('utf-8'))
96 self.assertTrue(actual.endswith(b"dump OK\n"))
98 def test_ndrdump_with_binary_struct_number(self):
99 expected = '''pull returned Success
100 GUID : 33323130-3534-3736-3839-616263646566
104 actual = self.check_output(
105 "ndrdump misc 0 struct %s" %
106 self.data_path("misc-GUID.dat"))
107 except BlackboxProcessError as e:
110 # check_output will return bytes
111 # convert expected to bytes for python 3
112 self.assertEqual(actual, expected.encode('utf-8'))
114 def test_ndrdump_with_enum_not_struct(self):
115 expected = '''Public structure 'netr_SchannelType' not found
118 actual = self.check_exit_code(
119 "ndrdump misc netr_SchannelType --input=x struct",
121 except BlackboxProcessError as e:
124 # check_output will return bytes
125 # convert expected to bytes for python 3
126 self.assertEqual(actual, expected.encode('utf-8'))
128 def test_ndrdump_input_cmdline_short_struct_name(self):
129 expected = '''pull returned Buffer Size Error
132 actual = self.check_exit_code(
133 "ndrdump -d0 misc GUID struct --input=abcdefg", 2)
134 except BlackboxProcessError as e:
137 # check_output will return bytes
138 # convert expected to bytes for python 3
139 self.assertEqual(actual, expected.encode('utf-8'))
141 def test_ndrdump_input_cmdline_short_struct_name_dump(self):
142 expected = '''pull returned Buffer Size Error
144 [0000] 61 62 63 64 65 66 67 abcdefg ''' \
148 actual = self.check_exit_code(
149 "ndrdump -d0 misc GUID struct --input=abcdefg --dump-data", 2)
150 except BlackboxProcessError as e:
153 # check_output will return bytes
154 # convert expected to bytes for python 3
155 self.assertEqual(actual, expected.encode('utf-8'))
157 def test_ndrdump_input_cmdline_short_struct_name_print_fail(self):
158 expected = '''pull returned Buffer Size Error
160 [0000] 61 62 63 64 65 66 67 abcdefg ''' \
162 WARNING! 1 unread bytes
165 WARNING: pull of GUID was incomplete, therefore the parse below may SEGFAULT
166 GUID : 64636261-6665-0000-0000-000000000000
167 dump of failed-to-parse GUID complete
170 actual = self.check_exit_code(
171 "ndrdump -d0 misc GUID struct --input=abcdefg --dump-data --print-after-parse-failure", 2)
172 except BlackboxProcessError as e:
175 # check_output will return bytes
176 # convert expected to bytes for python 3
177 self.assertEqual(actual, expected.encode('utf-8'))
179 def test_ndrdump_fuzzed_clusapi_QueryAllValues(self):
180 expected = b'''pull returned Success
181 WARNING! 53 unread bytes
182 [0000] 00 FF 00 00 FF 00 00 00 00 09 00 00 00 08 00 33 ........ .......3
183 [0010] 33 32 37 36 32 36 39 33 32 37 36 38 34 01 00 00 32762693 27684...
184 [0020] 80 32 0D FF 00 00 FF 00 00 00 00 08 00 00 00 1C .2...... ........
185 [0030] F1 29 08 00 00 .)... ''' \
187 clusapi_QueryAllValues: struct clusapi_QueryAllValues
188 out: struct clusapi_QueryAllValues
190 pcbData : 0x01000000 (16777216)
196 result : WERR_NOT_ENOUGH_MEMORY
200 actual = self.check_output(
201 'ndrdump clusapi clusapi_QueryAllValues out ' +\
202 '--base64-input --input=' +\
203 'AAAAAQEAAAAAAAAAAAAAAAgAAAAA/wAA/wAAAAAJAAAACAAzMzI3NjI2OTMyNzY4NAEAAIAyDf8AAP8AAAAACAAAABzxKQgAAA==')
204 except BlackboxProcessError as e:
206 self.assertEqual(actual, expected)
208 def test_ndrdump_fuzzed_IOXIDResolver_ResolveOxid(self):
209 expected = '''pull returned Character Conversion Error
212 actual = self.check_exit_code(
213 'ndrdump IOXIDResolver ResolveOxid out ' +\
214 '--base64-input --input=' +\
215 'c87PMf7CBAUAAAAADgQMBASjfPqKw0KPld6DY87PMfQ=',
217 except BlackboxProcessError as e:
219 self.assertRegex(actual.decode('utf8'), expected + "$")
221 def test_ndrdump_fuzzed_IOXIDResolver_ResolveOxid2(self):
222 expected = '''pull returned Buffer Size Error
225 actual = self.check_exit_code(
226 'ndrdump IOXIDResolver ResolveOxid2 out ' +\
227 '--base64-input --input=' +\
228 'AAAAAQ0K9Q0AAAAAAAAAA6ampqampqampqampqampqampqampqamNAAAAAAtNDQ=',
230 except BlackboxProcessError as e:
232 self.assertRegex(actual.decode('utf8'), expected + "$")
234 def test_ndrdump_fuzzed_IOXIDResolver_ServerAlive2(self):
235 expected = b'''pull returned Success
236 WARNING! 46 unread bytes
237 [0000] 0D 36 0A 0A 0A 0A 0A 00 00 00 00 00 00 00 03 00 .6...... ........
238 [0010] 00 00 01 00 00 33 39 36 31 36 31 37 37 36 38 34 .....396 16177684
239 [0020] 32 34 FC 85 AC 49 0B 61 87 0A 0A 0A F5 00 24...I.a ......
240 ServerAlive: struct ServerAlive
241 out: struct ServerAlive
242 result : DOS code 0x01000000
246 actual = self.check_output(
247 'ndrdump IOXIDResolver ServerAlive out ' +\
248 '--base64-input --input=' +\
249 'AAAAAQ02CgoKCgoAAAAAAAAAAwAAAAEAADM5NjE2MTc3Njg0MjT8haxJC2GHCgoK9QA=')
250 except BlackboxProcessError as e:
252 self.assertEqual(actual, expected)
254 def test_ndrdump_fuzzed_IRemoteActivation_RemoteActivation(self):
255 expected = '''pull returned Buffer Size Error
258 actual = self.check_exit_code(
259 'ndrdump IRemoteActivation RemoteActivation out ' +\
260 '--base64-input --input=' +\
261 'AAAAAQAAAAAAAABKAAD/AAAAAP4AAAAAAAAASgAAAAAAAAABIiIjIiIiIiIiIiIiIiMiAAAAAAD/AAAAAAAA',
263 except BlackboxProcessError as e:
265 self.assertRegex(actual.decode('utf8'), expected + "$")
267 def test_ndrdump_fuzzed_ntlmsssp_AUTHENTICATE_MESSAGE(self):
268 expected = open(self.data_path("fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.txt")).read()
270 actual = self.check_output(
271 "ndrdump ntlmssp AUTHENTICATE_MESSAGE struct --base64-input %s --validate" %
272 self.data_path("fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.b64.txt"))
273 except BlackboxProcessError as e:
275 # check_output will return bytes
276 # convert expected to bytes for python 3
277 self.assertEqual(actual, expected.encode('utf-8'))
279 def test_ndrdump_fuzzed_PackagesBlob(self):
280 expected = 'ndr_pull_string: ndr_pull_error\\(Buffer Size Error\\):'
282 "ndrdump drsblobs package_PackagesBlob struct --input='aw=='"
285 actual = self.check_exit_code(command, 2)
286 except BlackboxProcessError as e:
288 # check_output will return bytes
289 # convert expected to bytes for python 3
290 self.assertRegex(actual.decode('utf8'), expected)
292 def test_ndrdump_fuzzed_drsuapi_DsAddEntry_1(self):
293 expected = open(self.data_path("fuzzed_drsuapi_DsAddEntry_1.txt")).read()
295 actual = self.check_output(
296 "ndrdump drsuapi drsuapi_DsAddEntry in --base64-input --validate %s" %
297 self.data_path("fuzzed_drsuapi_DsAddEntry_1.b64.txt"))
298 except BlackboxProcessError as e:
300 # check_output will return bytes
301 # convert expected to bytes for python 3
302 self.assertEqual(actual, expected.encode('utf-8'))
304 def test_ndrdump_fuzzed_drsuapi_DsReplicaAttribute(self):
305 expected = open(self.data_path("fuzzed_drsuapi_DsReplicaAttribute.txt")).read()
307 actual = self.check_output(
308 "ndrdump drsuapi drsuapi_DsReplicaAttribute struct --base64-input --validate %s" %
309 self.data_path("fuzzed_drsuapi_DsReplicaAttribute.b64.txt"))
310 except BlackboxProcessError as e:
312 # check_output will return bytes
313 # convert expected to bytes for python 3
314 self.assertEqual(actual, expected.encode('utf-8'))
316 # This is a good example of a union with an empty default
317 # and no buffers to parse.
318 def test_ndrdump_fuzzed_spoolss_EnumForms(self):
319 expected_head = b'''pull returned Success
320 WARNING! 2 unread bytes
321 [0000] 00 00 .. ''' b'''
322 spoolss_EnumForms: struct spoolss_EnumForms
323 out: struct spoolss_EnumForms
325 count : 0x00000100 (256)
329 info : union spoolss_FormInfo(case 0)
330 info : union spoolss_FormInfo(case 0)
332 expected_tail = b'''info : union spoolss_FormInfo(case 0)
333 info : union spoolss_FormInfo(case 0)
334 info : union spoolss_FormInfo(case 0)
335 info : union spoolss_FormInfo(case 0)
336 info : union spoolss_FormInfo(case 0)
337 info : union spoolss_FormInfo(case 0)
339 needed : 0x00000000 (0)
340 result : DOS code 0xa9a9a900
344 actual = self.check_output(
345 "ndrdump spoolss spoolss_EnumForms out --base64-input " +\
346 "--input AAAAAQAAAAAAAAAAAAEAAACpqakAAA="
348 except BlackboxProcessError as e:
350 self.assertEqual(actual[:len(expected_head)],
352 self.assertTrue(actual.endswith(expected_tail))
354 # This is a good example of a union with scalars and buffers
355 def test_ndrdump_xattr_NTACL(self):
357 expected_head = open(self.data_path("xattr_NTACL.txt")).read().encode('utf8')
358 expected_tail = b'''dump OK
361 actual = self.check_output(
362 "ndrdump xattr xattr_NTACL struct --hex-input %s --validate" %
363 self.data_path("xattr_NTACL.dat"))
364 except BlackboxProcessError as e:
367 self.assertEqual(actual[:len(expected_head)],
369 self.assertTrue(actual.endswith(expected_tail))
371 # Test a --validate push of a NULL union pointer
372 def test_ndrdump_fuzzed_NULL_union_PAC_BUFFER(self):
373 expected = b'''pull returned Success
374 WARNING! 13 unread bytes
375 [0000] F5 FF 00 3C 3C 25 FF 70 16 1F A0 12 84 ...<<%.p .....
376 PAC_BUFFER: struct PAC_BUFFER
377 type : UNKNOWN_ENUM_VALUE (1094251328)
378 _ndr_size : 0x048792c6 (75993798)
380 _pad : 0x06000000 (100663296)
381 push returned Success
382 pull returned Success
383 PAC_BUFFER: struct PAC_BUFFER
384 type : UNKNOWN_ENUM_VALUE (1094251328)
385 _ndr_size : 0x00000000 (0)
387 _pad : 0x00000000 (0)
388 WARNING! orig bytes:29 validated pushed bytes:16
389 WARNING! orig and validated differ at byte 0x04 (4)
390 WARNING! orig byte[0x04] = 0xC6 validated byte[0x04] = 0x00
394 actual = self.check_output(
395 "ndrdump krb5pac PAC_BUFFER struct --validate --input " +\
396 "QPM4QcaShwQAAAAAAAAABvX/ADw8Jf9wFh+gEoQ= --base64-input")
397 except BlackboxProcessError as e:
400 self.assertEqual(actual, expected)