CVE-2021-23192: python/tests/dcerpc: fix do_single_request(send_req=False)
[samba.git] / python / samba / tests / dcerpc / raw_testcase.py
1 # Unix SMB/CIFS implementation.
2 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2010
3 # Copyright (C) Stefan Metzmacher 2014,2015
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18
19 import sys
20 import socket
21 import samba.dcerpc.dcerpc as dcerpc
22 import samba.dcerpc.base
23 import samba.dcerpc.epmapper
24 import samba.dcerpc.security as security
25 import samba.tests
26 from samba import gensec
27 from samba.credentials import Credentials
28 from samba.tests import TestCase
29 from samba.ndr import ndr_pack, ndr_unpack, ndr_unpack_out
30 from samba.ntstatus import (
31     NT_STATUS_CONNECTION_DISCONNECTED,
32     NT_STATUS_PIPE_DISCONNECTED,
33     NT_STATUS_IO_TIMEOUT
34 )
35 from samba import NTSTATUSError
36 from samba.samba3 import param as s3param
37 from samba.samba3 import libsmb_samba_internal as libsmb
38 from samba.credentials import SMB_SIGNING_REQUIRED
39
40 class smb_pipe_socket(object):
41
42     def __init__(self, target_hostname, pipename, creds, impersonation_level, lp):
43         lp3 = s3param.get_context()
44         lp3.load(lp.configfile)
45         saved_signing_state = creds.get_smb_ipc_signing()
46         creds.set_smb_ipc_signing(SMB_SIGNING_REQUIRED)
47         self.smbconn = libsmb.Conn(target_hostname, 'IPC$', lp3,
48                                    creds=creds, ipc=True)
49         creds.set_smb_ipc_signing(saved_signing_state)
50         self.smbfid = self.smbconn.create(pipename,
51                                           DesiredAccess=0x12019f,
52                                           ShareAccess=0x7,
53                                           CreateDisposition=1,
54                                           CreateOptions=0x400040,
55                                           ImpersonationLevel=impersonation_level)
56         return
57
58     def close(self):
59         self.smbconn.close(self.smbfid)
60         del self.smbconn
61
62     def settimeout(self, timeo):
63         # The socket module we simulate there
64         # specifies the timeo as seconds as float.
65         msecs = int(timeo * 1000)
66         assert msecs >= 0
67         self.smbconn.settimeout(msecs)
68         return
69
70     def send(self, buf, flags=0):
71         return self.smbconn.write(self.smbfid, buffer=buf, offset=0, mode=8)
72
73     def recv(self, len, flags=0):
74         try:
75             return self.smbconn.read(self.smbfid, offset=0, size=len)
76         except NTSTATUSError as e:
77             if e.args[0] == NT_STATUS_CONNECTION_DISCONNECTED:
78                 return b'\0' * 0
79             if e.args[0] == NT_STATUS_PIPE_DISCONNECTED:
80                 return b'\0' * 0
81             if e.args[0] == NT_STATUS_IO_TIMEOUT:
82                 raise socket.timeout(str(e))
83             raise e
84
85 class RawDCERPCTest(TestCase):
86     """A raw DCE/RPC Test case."""
87
88     def _disconnect(self, reason):
89         if self.s is None:
90             return
91         self.s.close()
92         self.s = None
93         if self.do_hexdump:
94             sys.stderr.write("disconnect[%s]\n" % reason)
95
96     def _connect_tcp(self):
97         tcp_port = int(self.primary_address)
98         try:
99             self.a = socket.getaddrinfo(self.host, tcp_port, socket.AF_UNSPEC,
100                                         socket.SOCK_STREAM, socket.SOL_TCP,
101                                         0)
102             self.s = socket.socket(self.a[0][0], self.a[0][1], self.a[0][2])
103             self.s.settimeout(10)
104             self.s.connect(self.a[0][4])
105         except socket.error as e:
106             self.s.close()
107             raise
108         except IOError as e:
109             self.s.close()
110             raise
111         except Exception as e:
112             raise
113         finally:
114             pass
115         self.max_xmit_frag = 5840
116         self.max_recv_frag = 5840
117         if self.secondary_address is None:
118             self.secondary_address = self.primary_address
119         # compat for older tests
120         self.tcp_port = tcp_port
121
122     def _connect_smb(self):
123         a = self.primary_address.split('\\')
124         self.assertEqual(len(a), 3)
125         self.assertEqual(a[0], "")
126         self.assertEqual(a[1], "pipe")
127         pipename = a[2]
128         self.s = smb_pipe_socket(self.target_hostname,
129                                  pipename,
130                                  self.transport_creds,
131                                  self.transport_impersonation,
132                                  self.lp_ctx)
133         self.max_xmit_frag = 4280
134         self.max_recv_frag = 4280
135         if self.secondary_address is None:
136             self.secondary_address = self.primary_address
137
138     def connect(self):
139         self.assertNotConnected()
140         if self.primary_address.startswith("\\pipe\\"):
141             self._connect_smb()
142         else:
143             self._connect_tcp()
144         if self.secondary_address is None:
145             self.secondary_address = self.primary_address
146         return
147
148     def setUp(self):
149         super(RawDCERPCTest, self).setUp()
150         self.do_ndr_print = False
151         self.do_hexdump = False
152
153         self.ignore_random_pad = samba.tests.env_get_var_value('IGNORE_RANDOM_PAD',
154                                                                allow_missing=True)
155         self.host = samba.tests.env_get_var_value('SERVER')
156         self.target_hostname = samba.tests.env_get_var_value('TARGET_HOSTNAME', allow_missing=True)
157         if self.target_hostname is None:
158             self.target_hostname = self.host
159         self.primary_address = "135"
160         self.secondary_address = None
161         self.transport_creds = self.get_anon_creds()
162         self.transport_impersonation = 0x2
163
164         self.settings = {}
165         self.settings["lp_ctx"] = self.lp_ctx = samba.tests.env_loadparm()
166         self.settings["target_hostname"] = self.target_hostname
167
168         self.s = None
169         self.connect()
170
171     def tearDown(self):
172         self._disconnect("tearDown")
173         super(TestCase, self).tearDown()
174
175     def noop(self):
176         return
177
178     def reconnect_smb_pipe(self, primary_address, secondary_address=None,
179                            transport_creds=None, transport_impersonation=None):
180         self._disconnect("reconnect_smb_pipe")
181         self.assertIsNotNone(primary_address)
182         self.primary_address = primary_address
183         if secondary_address is not None:
184             self.secondary_address = secondary_address
185         else:
186             self.secondary_address = None
187
188         if transport_creds is not None:
189             self.transport_creds = transport_creds
190
191         if transport_impersonation is not None:
192             self.transport_impersonation = transport_impersonation
193
194         self.connect()
195         return
196
197     def second_connection(self, primary_address=None, secondary_address=None,
198                           transport_creds=None, transport_impersonation=None):
199         c = RawDCERPCTest(methodName='noop')
200         c.do_ndr_print = self.do_ndr_print
201         c.do_hexdump = self.do_hexdump
202         c.ignore_random_pad = self.ignore_random_pad
203
204         c.host = self.host
205         c.target_hostname = self.target_hostname
206         if primary_address is not None:
207             c.primary_address = primary_address
208             if secondary_address is not None:
209                 c.secondary_address = secondary_address
210             else:
211                 c.secondary_address = None
212         else:
213             self.assertIsNone(secondary_address)
214             c.primary_address = self.primary_address
215             c.secondary_address = self.secondary_address
216
217         if transport_creds is not None:
218             c.transport_creds = transport_creds
219         else:
220             c.transport_creds = self.transport_creds
221
222         if transport_impersonation is not None:
223             c.transport_impersonation = transport_impersonation
224         else:
225             c.transport_impersonation = self.transport_impersonation
226
227         c.lp_ctx = self.lp_ctx
228         c.settings = self.settings
229
230         c.s = None
231         c.connect()
232         return c
233
234     def get_user_creds(self):
235         c = Credentials()
236         c.guess()
237         domain = samba.tests.env_get_var_value('DOMAIN')
238         realm = samba.tests.env_get_var_value('REALM')
239         username = samba.tests.env_get_var_value('USERNAME')
240         password = samba.tests.env_get_var_value('PASSWORD')
241         c.set_domain(domain)
242         c.set_realm(realm)
243         c.set_username(username)
244         c.set_password(password)
245         return c
246
247     def get_anon_creds(self):
248         c = Credentials()
249         c.set_anonymous()
250         return c
251
252     def get_auth_context_creds(self, creds, auth_type, auth_level,
253                                auth_context_id,
254                                g_auth_level=None,
255                                hdr_signing=False):
256
257         if g_auth_level is None:
258             g_auth_level = auth_level
259
260         g = gensec.Security.start_client(self.settings)
261         g.set_credentials(creds)
262         g.want_feature(gensec.FEATURE_DCE_STYLE)
263         g.start_mech_by_authtype(auth_type, g_auth_level)
264
265         if auth_type == dcerpc.DCERPC_AUTH_TYPE_KRB5:
266             expect_3legs = True
267         elif auth_type == dcerpc.DCERPC_AUTH_TYPE_NTLMSSP:
268             expect_3legs = True
269         else:
270             expect_3legs = False
271
272         auth_context = {}
273         auth_context["auth_type"] = auth_type
274         auth_context["auth_level"] = auth_level
275         auth_context["auth_context_id"] = auth_context_id
276         auth_context["g_auth_level"] = g_auth_level
277         auth_context["gensec"] = g
278         auth_context["hdr_signing"] = hdr_signing
279         auth_context["expect_3legs"] = expect_3legs
280
281         return auth_context
282
283     def do_generic_bind(self, ctx, auth_context=None,
284                         pfc_flags=samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
285                         samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
286                         assoc_group_id=0, call_id=0,
287                         nak_reason=None, alter_fault=None,
288                         start_with_alter=False,
289                         pfc_flags_2nd=samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
290                         samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
291                         use_auth3=False):
292         ctx_list = [ctx]
293
294         if auth_context is not None:
295             if auth_context['hdr_signing']:
296                 pfc_flags |= dcerpc.DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
297
298             expect_3legs = auth_context["expect_3legs"]
299
300             from_server = b""
301             (finished, to_server) = auth_context["gensec"].update(from_server)
302             self.assertFalse(finished)
303
304             auth_info = self.generate_auth(auth_type=auth_context["auth_type"],
305                                            auth_level=auth_context["auth_level"],
306                                            auth_context_id=auth_context["auth_context_id"],
307                                            auth_blob=to_server)
308         else:
309             auth_info = b""
310
311         if start_with_alter:
312             req = self.generate_alter(call_id=call_id,
313                                       pfc_flags=pfc_flags,
314                                       ctx_list=ctx_list,
315                                       assoc_group_id=0xffffffff - assoc_group_id,
316                                       auth_info=auth_info)
317             self.send_pdu(req)
318             rep = self.recv_pdu()
319             if alter_fault is not None:
320                 self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_FAULT, req.call_id,
321                                 pfc_flags=req.pfc_flags |
322                                 samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
323                                 auth_length=0)
324                 self.assertNotEqual(rep.u.alloc_hint, 0)
325                 self.assertEqual(rep.u.context_id, 0)
326                 self.assertEqual(rep.u.cancel_count, 0)
327                 self.assertEqual(rep.u.flags, 0)
328                 self.assertEqual(rep.u.status, alter_fault)
329                 self.assertEqual(rep.u.reserved, 0)
330                 self.assertEqual(len(rep.u.error_and_verifier), 0)
331                 return None
332             self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id,
333                             pfc_flags=req.pfc_flags)
334             self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag)
335             self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag)
336             self.assertEqual(rep.u.assoc_group_id, assoc_group_id)
337             self.assertEqual(rep.u.secondary_address_size, 0)
338             self.assertEqual(rep.u.secondary_address, '')
339             self.assertPadding(rep.u._pad1, 2)
340         else:
341             req = self.generate_bind(call_id=call_id,
342                                      pfc_flags=pfc_flags,
343                                      ctx_list=ctx_list,
344                                      assoc_group_id=assoc_group_id,
345                                      auth_info=auth_info)
346             self.send_pdu(req)
347             rep = self.recv_pdu()
348             if nak_reason is not None:
349                 self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_BIND_NAK, req.call_id,
350                                 auth_length=0)
351                 self.assertEqual(rep.u.reject_reason, nak_reason)
352                 self.assertEqual(rep.u.num_versions, 1)
353                 self.assertEqual(rep.u.versions[0].rpc_vers, req.rpc_vers)
354                 self.assertEqual(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor)
355                 self.assertPadding(rep.u._pad, 3)
356                 return
357             self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_BIND_ACK, req.call_id,
358                             pfc_flags=pfc_flags)
359             self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag)
360             self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag)
361             if assoc_group_id != 0:
362                 self.assertEqual(rep.u.assoc_group_id, assoc_group_id)
363             else:
364                 self.assertNotEqual(rep.u.assoc_group_id, 0)
365                 assoc_group_id = rep.u.assoc_group_id
366             sda_str = self.secondary_address
367             sda_len = len(sda_str) + 1
368             mod_len = (2 + sda_len) % 4
369             if mod_len != 0:
370                 sda_pad = 4 - mod_len
371             else:
372                 sda_pad = 0
373             self.assertEqual(rep.u.secondary_address_size, sda_len)
374             self.assertEqual(rep.u.secondary_address, sda_str)
375             self.assertPadding(rep.u._pad1, sda_pad)
376
377         self.assertEqual(rep.u.num_results, 1)
378         self.assertEqual(rep.u.ctx_list[0].result,
379                           samba.dcerpc.dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
380         self.assertEqual(rep.u.ctx_list[0].reason,
381                           samba.dcerpc.dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
382         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ctx.transfer_syntaxes[0])
383         ack = rep
384         if auth_context is None:
385             self.assertEqual(rep.auth_length, 0)
386             self.assertEqual(len(rep.u.auth_info), 0)
387             return ack
388         self.assertNotEqual(rep.auth_length, 0)
389         self.assertGreater(len(rep.u.auth_info), samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH)
390         self.assertEqual(rep.auth_length, len(rep.u.auth_info) - samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH)
391
392         a = self.parse_auth(rep.u.auth_info, auth_context=auth_context)
393
394         from_server = a.credentials
395         (finished, to_server) = auth_context["gensec"].update(from_server)
396         if expect_3legs:
397             self.assertTrue(finished)
398             if auth_context['hdr_signing']:
399                 auth_context["gensec"].want_feature(gensec.FEATURE_SIGN_PKT_HEADER)
400         else:
401             self.assertFalse(use_auth3)
402             self.assertFalse(finished)
403
404         auth_info = self.generate_auth(auth_type=auth_context["auth_type"],
405                                        auth_level=auth_context["auth_level"],
406                                        auth_context_id=auth_context["auth_context_id"],
407                                        auth_blob=to_server)
408         if use_auth3:
409             req = self.generate_auth3(call_id=call_id,
410                                       pfc_flags=pfc_flags_2nd,
411                                       auth_info=auth_info)
412             self.send_pdu(req)
413             rep = self.recv_pdu(timeout=0.01)
414             self.assertIsNone(rep)
415             self.assertIsConnected()
416             return ack
417         req = self.generate_alter(call_id=call_id,
418                                   ctx_list=ctx_list,
419                                   pfc_flags=pfc_flags_2nd,
420                                   assoc_group_id=0xffffffff - assoc_group_id,
421                                   auth_info=auth_info)
422         self.send_pdu(req)
423         rep = self.recv_pdu()
424         if alter_fault is not None:
425             self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_FAULT, req.call_id,
426                             pfc_flags=req.pfc_flags |
427                             samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
428                             auth_length=0)
429             self.assertNotEqual(rep.u.alloc_hint, 0)
430             self.assertEqual(rep.u.context_id, 0)
431             self.assertEqual(rep.u.cancel_count, 0)
432             self.assertEqual(rep.u.flags, 0)
433             self.assertEqual(rep.u.status, alter_fault)
434             self.assertEqual(rep.u.reserved, 0)
435             self.assertEqual(len(rep.u.error_and_verifier), 0)
436             return None
437         self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id,
438                         pfc_flags=req.pfc_flags)
439         self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag)
440         self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag)
441         self.assertEqual(rep.u.assoc_group_id, assoc_group_id)
442         self.assertEqual(rep.u.secondary_address_size, 0)
443         self.assertEqual(rep.u.secondary_address, '')
444         self.assertPadding(rep.u._pad1, 2)
445         self.assertEqual(rep.u.num_results, 1)
446         self.assertEqual(rep.u.ctx_list[0].result,
447                           samba.dcerpc.dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
448         self.assertEqual(rep.u.ctx_list[0].reason,
449                           samba.dcerpc.dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
450         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ctx.transfer_syntaxes[0])
451         if finished:
452             self.assertEqual(rep.auth_length, 0)
453         else:
454             self.assertNotEqual(rep.auth_length, 0)
455         self.assertGreaterEqual(len(rep.u.auth_info), samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH)
456         self.assertEqual(rep.auth_length, len(rep.u.auth_info) - samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH)
457
458         a = self.parse_auth(rep.u.auth_info, auth_context=auth_context)
459
460         if finished:
461             return ack
462
463         from_server = a.credentials
464         (finished, to_server) = auth_context["gensec"].update(from_server)
465         self.assertTrue(finished)
466         if auth_context['hdr_signing']:
467             auth_context["gensec"].want_feature(gensec.FEATURE_SIGN_PKT_HEADER)
468
469         return ack
470
471     def prepare_presentation(self, abstract, transfer, object=None,
472                              context_id=0xffff, epmap=False, auth_context=None,
473                              pfc_flags=samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
474                              samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
475                              assoc_group_id=0,
476                              return_ack=False):
477         if epmap:
478             self.epmap_reconnect(abstract, transfer=transfer, object=object)
479
480         tsf1_list = [transfer]
481         ctx = samba.dcerpc.dcerpc.ctx_list()
482         ctx.context_id = context_id
483         ctx.num_transfer_syntaxes = len(tsf1_list)
484         ctx.abstract_syntax = abstract
485         ctx.transfer_syntaxes = tsf1_list
486
487         ack = self.do_generic_bind(ctx=ctx,
488                                    auth_context=auth_context,
489                                    pfc_flags=pfc_flags,
490                                    assoc_group_id=assoc_group_id)
491         if ack is None:
492             ctx = None
493
494         if return_ack:
495             return (ctx, ack)
496         return ctx
497
498     def do_single_request(self, call_id, ctx, io,
499                           auth_context=None,
500                           object=None,
501                           bigendian=False, ndr64=False,
502                           allow_remaining=False,
503                           send_req=True,
504                           recv_rep=True,
505                           fault_pfc_flags=(
506                               samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
507                               samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST),
508                           fault_status=None,
509                           fault_context_id=None,
510                           timeout=None,
511                           ndr_print=None,
512                           hexdump=None):
513
514         if fault_context_id is None:
515             fault_context_id = ctx.context_id
516
517         if ndr_print is None:
518             ndr_print = self.do_ndr_print
519         if hexdump is None:
520             hexdump = self.do_hexdump
521
522         if send_req:
523             if ndr_print:
524                 sys.stderr.write("in: %s" % samba.ndr.ndr_print_in(io))
525             stub_in = samba.ndr.ndr_pack_in(io, bigendian=bigendian, ndr64=ndr64)
526             if hexdump:
527                 sys.stderr.write("stub_in: %d\n%s" % (len(stub_in), self.hexdump(stub_in)))
528
529             pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST
530             pfc_flags |= samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST
531             if object is not None:
532                 pfc_flags |= samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_OBJECT_UUID
533
534             req = self.generate_request_auth(call_id=call_id,
535                                              context_id=ctx.context_id,
536                                              pfc_flags=pfc_flags,
537                                              object=object,
538                                              opnum=io.opnum(),
539                                              stub=stub_in,
540                                              auth_context=auth_context)
541             self.send_pdu(req, ndr_print=ndr_print, hexdump=hexdump)
542         if recv_rep:
543             (rep, rep_blob) = self.recv_pdu_raw(timeout=timeout,
544                                                 ndr_print=ndr_print,
545                                                 hexdump=hexdump)
546             if fault_status:
547                 self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_FAULT, call_id,
548                                 pfc_flags=fault_pfc_flags, auth_length=0)
549                 self.assertNotEqual(rep.u.alloc_hint, 0)
550                 self.assertEqual(rep.u.context_id, fault_context_id)
551                 self.assertEqual(rep.u.cancel_count, 0)
552                 self.assertEqual(rep.u.flags, 0)
553                 self.assertEqual(rep.u.status, fault_status)
554                 self.assertEqual(rep.u.reserved, 0)
555                 self.assertEqual(len(rep.u.error_and_verifier), 0)
556                 return
557
558             expected_auth_length = 0
559             if auth_context is not None and \
560                auth_context["auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PACKET:
561                 if send_req:
562                     expected_auth_length = req.auth_length
563                 else:
564                     expected_auth_length = rep.auth_length
565
566
567             self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_RESPONSE, call_id,
568                             auth_length=expected_auth_length)
569             self.assertNotEqual(rep.u.alloc_hint, 0)
570             self.assertEqual(rep.u.context_id, ctx.context_id & 0xff)
571             self.assertEqual(rep.u.cancel_count, 0)
572             self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
573             stub_out = self.check_response_auth(rep, rep_blob, auth_context)
574             self.assertEqual(len(stub_out), rep.u.alloc_hint)
575
576             if hexdump:
577                 sys.stderr.write("stub_out: %d\n%s" % (len(stub_out), self.hexdump(stub_out)))
578             ndr_unpack_out(io, stub_out, bigendian=bigendian, ndr64=ndr64,
579                            allow_remaining=allow_remaining)
580             if ndr_print:
581                 sys.stderr.write("out: %s" % samba.ndr.ndr_print_out(io))
582
583     def epmap_reconnect(self, abstract, transfer=None, object=None):
584         ndr32 = samba.dcerpc.base.transfer_syntax_ndr()
585
586         if transfer is None:
587             transfer = ndr32
588
589         if object is None:
590             object = samba.dcerpc.misc.GUID()
591
592         ctx = self.prepare_presentation(samba.dcerpc.epmapper.abstract_syntax(),
593                                         transfer, context_id=0)
594
595         data1 = ndr_pack(abstract)
596         lhs1 = samba.dcerpc.epmapper.epm_lhs()
597         lhs1.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_UUID
598         lhs1.lhs_data = data1[:18]
599         rhs1 = samba.dcerpc.epmapper.epm_rhs_uuid()
600         rhs1.unknown = data1[18:]
601         floor1 = samba.dcerpc.epmapper.epm_floor()
602         floor1.lhs = lhs1
603         floor1.rhs = rhs1
604         data2 = ndr_pack(transfer)
605         lhs2 = samba.dcerpc.epmapper.epm_lhs()
606         lhs2.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_UUID
607         lhs2.lhs_data = data2[:18]
608         rhs2 = samba.dcerpc.epmapper.epm_rhs_uuid()
609         rhs2.unknown = data1[18:]
610         floor2 = samba.dcerpc.epmapper.epm_floor()
611         floor2.lhs = lhs2
612         floor2.rhs = rhs2
613         lhs3 = samba.dcerpc.epmapper.epm_lhs()
614         lhs3.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_NCACN
615         lhs3.lhs_data = b""
616         floor3 = samba.dcerpc.epmapper.epm_floor()
617         floor3.lhs = lhs3
618         floor3.rhs.minor_version = 0
619         lhs4 = samba.dcerpc.epmapper.epm_lhs()
620         lhs4.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_TCP
621         lhs4.lhs_data = b""
622         floor4 = samba.dcerpc.epmapper.epm_floor()
623         floor4.lhs = lhs4
624         floor4.rhs.port = int(self.primary_address)
625         lhs5 = samba.dcerpc.epmapper.epm_lhs()
626         lhs5.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_IP
627         lhs5.lhs_data = b""
628         floor5 = samba.dcerpc.epmapper.epm_floor()
629         floor5.lhs = lhs5
630         floor5.rhs.ipaddr = "0.0.0.0"
631
632         floors = [floor1, floor2, floor3, floor4, floor5]
633         req_tower = samba.dcerpc.epmapper.epm_tower()
634         req_tower.num_floors = len(floors)
635         req_tower.floors = floors
636         req_twr = samba.dcerpc.epmapper.epm_twr_t()
637         req_twr.tower = req_tower
638
639         epm_map = samba.dcerpc.epmapper.epm_Map()
640         epm_map.in_object = object
641         epm_map.in_map_tower = req_twr
642         epm_map.in_entry_handle = samba.dcerpc.misc.policy_handle()
643         epm_map.in_max_towers = 4
644
645         self.do_single_request(call_id=2, ctx=ctx, io=epm_map)
646
647         self.assertGreaterEqual(epm_map.out_num_towers, 1)
648         rep_twr = epm_map.out_towers[0].twr
649         self.assertIsNotNone(rep_twr)
650         self.assertEqual(rep_twr.tower_length, 75)
651         self.assertEqual(rep_twr.tower.num_floors, 5)
652         self.assertEqual(len(rep_twr.tower.floors), 5)
653         self.assertEqual(rep_twr.tower.floors[3].lhs.protocol,
654                          samba.dcerpc.epmapper.EPM_PROTOCOL_TCP)
655         self.assertEqual(rep_twr.tower.floors[3].lhs.protocol,
656                          samba.dcerpc.epmapper.EPM_PROTOCOL_TCP)
657
658         # reconnect to the given port
659         self._disconnect("epmap_reconnect")
660         self.primary_address = "%d" % rep_twr.tower.floors[3].rhs.port
661         self.secondary_address = None
662         self.connect()
663
664     def send_pdu(self, req, ndr_print=None, hexdump=None):
665         if ndr_print is None:
666             ndr_print = self.do_ndr_print
667         if hexdump is None:
668             hexdump = self.do_hexdump
669         try:
670             req_pdu = ndr_pack(req)
671             if ndr_print:
672                 sys.stderr.write("send_pdu: %s" % samba.ndr.ndr_print(req))
673             if hexdump:
674                 sys.stderr.write("send_pdu: %d\n%s" % (len(req_pdu), self.hexdump(req_pdu)))
675             while True:
676                 sent = self.s.send(req_pdu, 0)
677                 if sent == len(req_pdu):
678                     break
679                 req_pdu = req_pdu[sent:]
680         except socket.error as e:
681             self._disconnect("send_pdu: %s" % e)
682             raise
683         except IOError as e:
684             self._disconnect("send_pdu: %s" % e)
685             raise
686         except NTSTATUSError as e:
687             self._disconnect("send_pdu: %s" % e)
688             raise
689         finally:
690             pass
691
692     def recv_raw(self, hexdump=None, timeout=None):
693         rep_pdu = None
694         if hexdump is None:
695             hexdump = self.do_hexdump
696         try:
697             if timeout is not None:
698                 self.s.settimeout(timeout)
699             rep_pdu = self.s.recv(0xffff, 0)
700             self.s.settimeout(10)
701             if len(rep_pdu) == 0:
702                 self._disconnect("recv_raw: EOF")
703                 return None
704             if hexdump:
705                 sys.stderr.write("recv_raw: %d\n%s" % (len(rep_pdu), self.hexdump(rep_pdu)))
706         except socket.timeout as e:
707             self.s.settimeout(10)
708             sys.stderr.write("recv_raw: TIMEOUT\n")
709             pass
710         except socket.error as e:
711             self._disconnect("recv_raw: %s" % e)
712             raise
713         except IOError as e:
714             self._disconnect("recv_raw: %s" % e)
715             raise
716         finally:
717             pass
718         return rep_pdu
719
720     def recv_pdu_raw(self, ndr_print=None, hexdump=None, timeout=None):
721         rep_pdu = None
722         rep = None
723         if ndr_print is None:
724             ndr_print = self.do_ndr_print
725         if hexdump is None:
726             hexdump = self.do_hexdump
727         try:
728             rep_pdu = self.recv_raw(hexdump=hexdump, timeout=timeout)
729             if rep_pdu is None:
730                 return (None, None)
731             rep = ndr_unpack(samba.dcerpc.dcerpc.ncacn_packet, rep_pdu, allow_remaining=True)
732             if ndr_print:
733                 sys.stderr.write("recv_pdu: %s" % samba.ndr.ndr_print(rep))
734             self.assertEqual(rep.frag_length, len(rep_pdu))
735         finally:
736             pass
737         return (rep, rep_pdu)
738
739     def recv_pdu(self, ndr_print=None, hexdump=None, timeout=None):
740         (rep, rep_pdu) = self.recv_pdu_raw(ndr_print=ndr_print,
741                                            hexdump=hexdump,
742                                            timeout=timeout)
743         return rep
744
745     def generate_auth(self,
746                       auth_type=None,
747                       auth_level=None,
748                       auth_pad_length=0,
749                       auth_context_id=None,
750                       auth_blob=None,
751                       ndr_print=None, hexdump=None):
752         if ndr_print is None:
753             ndr_print = self.do_ndr_print
754         if hexdump is None:
755             hexdump = self.do_hexdump
756
757         if auth_type is not None:
758             a = samba.dcerpc.dcerpc.auth()
759             a.auth_type = auth_type
760             a.auth_level = auth_level
761             a.auth_pad_length = auth_pad_length
762             a.auth_context_id = auth_context_id
763             a.credentials = auth_blob
764
765             ai = ndr_pack(a)
766             if ndr_print:
767                 sys.stderr.write("generate_auth: %s" % samba.ndr.ndr_print(a))
768             if hexdump:
769                 sys.stderr.write("generate_auth: %d\n%s" % (len(ai), self.hexdump(ai)))
770         else:
771             ai = b""
772
773         return ai
774
775     def parse_auth(self, auth_info, ndr_print=None, hexdump=None,
776                    auth_context=None, stub_len=0):
777         if ndr_print is None:
778             ndr_print = self.do_ndr_print
779         if hexdump is None:
780             hexdump = self.do_hexdump
781
782         if (len(auth_info) <= samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH):
783             return None
784
785         if hexdump:
786             sys.stderr.write("parse_auth: %d\n%s" % (len(auth_info), self.hexdump(auth_info)))
787         a = ndr_unpack(samba.dcerpc.dcerpc.auth, auth_info, allow_remaining=True)
788         if ndr_print:
789             sys.stderr.write("parse_auth: %s" % samba.ndr.ndr_print(a))
790
791         if auth_context is not None:
792             self.assertEqual(a.auth_type, auth_context["auth_type"])
793             self.assertEqual(a.auth_level, auth_context["auth_level"])
794             self.assertEqual(a.auth_reserved, 0)
795             self.assertEqual(a.auth_context_id, auth_context["auth_context_id"])
796
797             self.assertLessEqual(a.auth_pad_length, dcerpc.DCERPC_AUTH_PAD_ALIGNMENT)
798             self.assertLessEqual(a.auth_pad_length, stub_len)
799
800         return a
801
802     def check_response_auth(self, rep, rep_blob, auth_context=None,
803                             auth_pad_length=None):
804
805         if auth_context is None:
806             self.assertEqual(rep.auth_length, 0)
807             return rep.u.stub_and_verifier
808
809         if auth_context["auth_level"] == dcerpc.DCERPC_AUTH_LEVEL_CONNECT:
810             self.assertEqual(rep.auth_length, 0)
811             return rep.u.stub_and_verifier
812
813         self.assertGreater(rep.auth_length, 0)
814
815         ofs_stub = dcerpc.DCERPC_REQUEST_LENGTH
816         ofs_sig = rep.frag_length - rep.auth_length
817         ofs_trailer = ofs_sig - dcerpc.DCERPC_AUTH_TRAILER_LENGTH
818         rep_data = rep_blob[ofs_stub:ofs_trailer]
819         rep_whole = rep_blob[0:ofs_sig]
820         rep_sig = rep_blob[ofs_sig:]
821         rep_auth_info_blob = rep_blob[ofs_trailer:]
822
823         rep_auth_info = self.parse_auth(rep_auth_info_blob,
824                                         auth_context=auth_context,
825                                         stub_len=len(rep_data))
826         if auth_pad_length is not None:
827             self.assertEqual(rep_auth_info.auth_pad_length, auth_pad_length)
828         self.assertEqual(rep_auth_info.credentials, rep_sig)
829
830         if auth_context["auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PRIVACY:
831             # TODO: not yet supported here
832             self.assertTrue(False)
833         elif auth_context["auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PACKET:
834             auth_context["gensec"].check_packet(rep_data, rep_whole, rep_sig)
835
836         stub_out = rep_data[0:len(rep_data)-rep_auth_info.auth_pad_length]
837
838         return stub_out
839
840     def generate_pdu(self, ptype, call_id, payload,
841                      rpc_vers=5,
842                      rpc_vers_minor=0,
843                      pfc_flags=(samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
844                                 samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST),
845                      drep=[samba.dcerpc.dcerpc.DCERPC_DREP_LE, 0, 0, 0],
846                      ndr_print=None, hexdump=None):
847
848         if getattr(payload, 'auth_info', None):
849             ai = payload.auth_info
850         else:
851             ai = b""
852
853         p = samba.dcerpc.dcerpc.ncacn_packet()
854         p.rpc_vers = rpc_vers
855         p.rpc_vers_minor = rpc_vers_minor
856         p.ptype = ptype
857         p.pfc_flags = pfc_flags
858         p.drep = drep
859         p.frag_length = 0
860         if len(ai) > samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH:
861             p.auth_length = len(ai) - samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH
862         else:
863             p.auth_length = 0
864         p.call_id = call_id
865         p.u = payload
866
867         pdu = ndr_pack(p)
868         p.frag_length = len(pdu)
869
870         return p
871
872     def generate_request_auth(self, call_id,
873                               pfc_flags=(dcerpc.DCERPC_PFC_FLAG_FIRST |
874                                          dcerpc.DCERPC_PFC_FLAG_LAST),
875                               alloc_hint=None,
876                               context_id=None,
877                               opnum=None,
878                               object=None,
879                               stub=None,
880                               auth_context=None,
881                               ndr_print=None, hexdump=None):
882
883         if stub is None:
884             stub = b""
885
886         sig_size = 0
887         if auth_context is not None:
888             mod_len = len(stub) % dcerpc.DCERPC_AUTH_PAD_ALIGNMENT
889             auth_pad_length = 0
890             if mod_len > 0:
891                 auth_pad_length = dcerpc.DCERPC_AUTH_PAD_ALIGNMENT - mod_len
892             stub += b'\x00' * auth_pad_length
893
894             if auth_context["g_auth_level"] >= samba.dcerpc.dcerpc.DCERPC_AUTH_LEVEL_PACKET:
895                 sig_size = auth_context["gensec"].sig_size(len(stub))
896             else:
897                 sig_size = 16
898
899             zero_sig = b"\x00" * sig_size
900             auth_info = self.generate_auth(auth_type=auth_context["auth_type"],
901                                            auth_level=auth_context["auth_level"],
902                                            auth_pad_length=auth_pad_length,
903                                            auth_context_id=auth_context["auth_context_id"],
904                                            auth_blob=zero_sig)
905         else:
906             auth_info = b""
907
908         req = self.generate_request(call_id=call_id,
909                                     pfc_flags=pfc_flags,
910                                     alloc_hint=alloc_hint,
911                                     context_id=context_id,
912                                     opnum=opnum,
913                                     object=object,
914                                     stub=stub,
915                                     auth_info=auth_info,
916                                     ndr_print=ndr_print,
917                                     hexdump=hexdump)
918         if auth_context is None:
919             return req
920
921         req_blob = samba.ndr.ndr_pack(req)
922         ofs_stub = dcerpc.DCERPC_REQUEST_LENGTH
923         ofs_sig = len(req_blob) - req.auth_length
924         ofs_trailer = ofs_sig - dcerpc.DCERPC_AUTH_TRAILER_LENGTH
925         req_data = req_blob[ofs_stub:ofs_trailer]
926         req_whole = req_blob[0:ofs_sig]
927
928         if auth_context["g_auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PRIVACY:
929             # TODO: not yet supported here
930             self.assertTrue(False)
931         elif auth_context["g_auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PACKET:
932             req_sig = auth_context["gensec"].sign_packet(req_data, req_whole)
933         elif auth_context["g_auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_CONNECT:
934             self.assertEqual(auth_context["auth_type"],
935                               dcerpc.DCERPC_AUTH_TYPE_NTLMSSP)
936             req_sig = b"\x01" +b"\x00" *15
937         else:
938             return req
939         self.assertEqual(len(req_sig), req.auth_length)
940         self.assertEqual(len(req_sig), sig_size)
941
942         stub_sig_ofs = len(req.u.stub_and_verifier) - sig_size
943         stub = req.u.stub_and_verifier[0:stub_sig_ofs] + req_sig
944         req.u.stub_and_verifier = stub
945
946         return req
947
948     def verify_pdu(self, p, ptype, call_id,
949                    rpc_vers=5,
950                    rpc_vers_minor=0,
951                    pfc_flags=(samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
952                               samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST),
953                    drep=[samba.dcerpc.dcerpc.DCERPC_DREP_LE, 0, 0, 0],
954                    auth_length=None):
955
956         self.assertIsNotNone(p, "No valid pdu")
957
958         if getattr(p.u, 'auth_info', None):
959             ai = p.u.auth_info
960         else:
961             ai = b""
962
963         self.assertEqual(p.rpc_vers, rpc_vers)
964         self.assertEqual(p.rpc_vers_minor, rpc_vers_minor)
965         self.assertEqual(p.ptype, ptype)
966         self.assertEqual(p.pfc_flags, pfc_flags)
967         self.assertEqual(p.drep, drep)
968         self.assertGreaterEqual(p.frag_length,
969                                 samba.dcerpc.dcerpc.DCERPC_NCACN_PAYLOAD_OFFSET)
970         if len(ai) > samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH:
971             self.assertEqual(p.auth_length,
972                              len(ai) - samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH)
973         elif auth_length is not None:
974             self.assertEqual(p.auth_length, auth_length)
975         else:
976             self.assertEqual(p.auth_length, 0)
977         self.assertEqual(p.call_id, call_id)
978
979         return
980
981     def generate_bind(self, call_id,
982                       pfc_flags=(samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
983                                  samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST),
984                       max_xmit_frag=None,
985                       max_recv_frag=None,
986                       assoc_group_id=0,
987                       ctx_list=[],
988                       auth_info=b"",
989                       ndr_print=None, hexdump=None):
990
991         if max_xmit_frag is None:
992             max_xmit_frag=self.max_xmit_frag
993         if max_recv_frag is None:
994             max_recv_frag=self.max_recv_frag
995
996         b = samba.dcerpc.dcerpc.bind()
997         b.max_xmit_frag = max_xmit_frag
998         b.max_recv_frag = max_recv_frag
999         b.assoc_group_id = assoc_group_id
1000         b.num_contexts = len(ctx_list)
1001         b.ctx_list = ctx_list
1002         b.auth_info = auth_info
1003
1004         p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_BIND,
1005                               pfc_flags=pfc_flags,
1006                               call_id=call_id,
1007                               payload=b,
1008                               ndr_print=ndr_print, hexdump=hexdump)
1009
1010         return p
1011
1012     def generate_alter(self, call_id,
1013                        pfc_flags=(samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
1014                                   samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST),
1015                        max_xmit_frag=None,
1016                        max_recv_frag=None,
1017                        assoc_group_id=0,
1018                        ctx_list=[],
1019                        auth_info=b"",
1020                        ndr_print=None, hexdump=None):
1021
1022         if max_xmit_frag is None:
1023             max_xmit_frag=self.max_xmit_frag
1024         if max_recv_frag is None:
1025             max_recv_frag=self.max_recv_frag
1026
1027         a = samba.dcerpc.dcerpc.bind()
1028         a.max_xmit_frag = max_xmit_frag
1029         a.max_recv_frag = max_recv_frag
1030         a.assoc_group_id = assoc_group_id
1031         a.num_contexts = len(ctx_list)
1032         a.ctx_list = ctx_list
1033         a.auth_info = auth_info
1034
1035         p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_ALTER,
1036                               pfc_flags=pfc_flags,
1037                               call_id=call_id,
1038                               payload=a,
1039                               ndr_print=ndr_print, hexdump=hexdump)
1040
1041         return p
1042
1043     def generate_auth3(self, call_id,
1044                        pfc_flags=(samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
1045                                   samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST),
1046                        auth_info=b"",
1047                        ndr_print=None, hexdump=None):
1048
1049         a = samba.dcerpc.dcerpc.auth3()
1050         a.auth_info = auth_info
1051
1052         p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_AUTH3,
1053                               pfc_flags=pfc_flags,
1054                               call_id=call_id,
1055                               payload=a,
1056                               ndr_print=ndr_print, hexdump=hexdump)
1057
1058         return p
1059
1060     def generate_request(self, call_id,
1061                          pfc_flags=(samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
1062                                     samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST),
1063                          alloc_hint=None,
1064                          context_id=None,
1065                          opnum=None,
1066                          object=None,
1067                          stub=None,
1068                          auth_info=b"",
1069                          ndr_print=None, hexdump=None):
1070
1071         if alloc_hint is None:
1072             alloc_hint = len(stub)
1073
1074         r = samba.dcerpc.dcerpc.request()
1075         r.alloc_hint = alloc_hint
1076         r.context_id = context_id
1077         r.opnum = opnum
1078         if object is not None:
1079             r.object = object
1080         r.stub_and_verifier = stub + auth_info
1081
1082         p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_REQUEST,
1083                               pfc_flags=pfc_flags,
1084                               call_id=call_id,
1085                               payload=r,
1086                               ndr_print=ndr_print, hexdump=hexdump)
1087
1088         if len(auth_info) > samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH:
1089             p.auth_length = len(auth_info) - samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH
1090
1091         return p
1092
1093     def generate_co_cancel(self, call_id,
1094                            pfc_flags=(samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
1095                                       samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST),
1096                            auth_info=b"",
1097                            ndr_print=None, hexdump=None):
1098
1099         c = samba.dcerpc.dcerpc.co_cancel()
1100         c.auth_info = auth_info
1101
1102         p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_CO_CANCEL,
1103                               pfc_flags=pfc_flags,
1104                               call_id=call_id,
1105                               payload=c,
1106                               ndr_print=ndr_print, hexdump=hexdump)
1107
1108         return p
1109
1110     def generate_orphaned(self, call_id,
1111                           pfc_flags=(samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
1112                                      samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST),
1113                           auth_info=b"",
1114                           ndr_print=None, hexdump=None):
1115
1116         o = samba.dcerpc.dcerpc.orphaned()
1117         o.auth_info = auth_info
1118
1119         p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_ORPHANED,
1120                               pfc_flags=pfc_flags,
1121                               call_id=call_id,
1122                               payload=o,
1123                               ndr_print=ndr_print, hexdump=hexdump)
1124
1125         return p
1126
1127     def generate_shutdown(self, call_id,
1128                           pfc_flags=(samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
1129                                      samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST),
1130                           ndr_print=None, hexdump=None):
1131
1132         s = samba.dcerpc.dcerpc.shutdown()
1133
1134         p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_SHUTDOWN,
1135                               pfc_flags=pfc_flags,
1136                               call_id=call_id,
1137                               payload=s,
1138                               ndr_print=ndr_print, hexdump=hexdump)
1139
1140         return p
1141
1142     def assertIsConnected(self):
1143         self.assertIsNotNone(self.s, msg="Not connected")
1144         return
1145
1146     def assertNotConnected(self):
1147         self.assertIsNone(self.s, msg="Is connected")
1148         return
1149
1150     def assertNDRSyntaxEquals(self, s1, s2):
1151         self.assertEqual(s1.uuid, s2.uuid)
1152         self.assertEqual(s1.if_version, s2.if_version)
1153         return
1154
1155     def assertPadding(self, pad, length):
1156         self.assertEqual(len(pad), length)
1157         #
1158         # sometimes windows sends random bytes
1159         #
1160         # we have IGNORE_RANDOM_PAD=1 to
1161         # disable the check
1162         #
1163         if self.ignore_random_pad:
1164             return
1165         zero_pad = b'\0' * length
1166         self.assertEqual(pad, zero_pad)
1167
1168     def assertEqualsStrLower(self, s1, s2):
1169         self.assertEqual(str(s1).lower(), str(s2).lower())