1 # Unix SMB/CIFS implementation.
2 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2010
3 # Copyright (C) Stefan Metzmacher 2014,2015
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.
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.
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/>.
21 import samba.dcerpc.dcerpc as dcerpc
22 import samba.dcerpc.base
23 import samba.dcerpc.epmapper
24 import samba.dcerpc.security as security
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,
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
40 class smb_pipe_socket(object):
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,
54 CreateOptions=0x400040,
55 ImpersonationLevel=impersonation_level)
59 self.smbconn.close(self.smbfid)
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)
67 self.smbconn.settimeout(msecs)
70 def send(self, buf, flags=0):
71 return self.smbconn.write(self.smbfid, buffer=buf, offset=0, mode=8)
73 def recv(self, len, flags=0):
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:
79 if e.args[0] == NT_STATUS_PIPE_DISCONNECTED:
81 if e.args[0] == NT_STATUS_IO_TIMEOUT:
82 raise socket.timeout(str(e))
85 class RawDCERPCTest(TestCase):
86 """A raw DCE/RPC Test case."""
88 def _disconnect(self, reason):
94 sys.stderr.write("disconnect[%s]\n" % reason)
96 def _connect_tcp(self):
97 tcp_port = int(self.primary_address)
99 self.a = socket.getaddrinfo(self.host, tcp_port, socket.AF_UNSPEC,
100 socket.SOCK_STREAM, socket.SOL_TCP,
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:
111 except Exception as e:
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
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")
128 self.s = smb_pipe_socket(self.target_hostname,
130 self.transport_creds,
131 self.transport_impersonation,
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
139 self.assertNotConnected()
140 if self.primary_address.startswith("\\pipe\\"):
144 if self.secondary_address is None:
145 self.secondary_address = self.primary_address
149 super(RawDCERPCTest, self).setUp()
150 self.do_ndr_print = False
151 self.do_hexdump = False
153 self.ignore_random_pad = samba.tests.env_get_var_value('IGNORE_RANDOM_PAD',
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
165 self.settings["lp_ctx"] = self.lp_ctx = samba.tests.env_loadparm()
166 self.settings["target_hostname"] = self.target_hostname
172 self._disconnect("tearDown")
173 super(TestCase, self).tearDown()
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
186 self.secondary_address = None
188 if transport_creds is not None:
189 self.transport_creds = transport_creds
191 if transport_impersonation is not None:
192 self.transport_impersonation = transport_impersonation
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
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
211 c.secondary_address = None
213 self.assertIsNone(secondary_address)
214 c.primary_address = self.primary_address
215 c.secondary_address = self.secondary_address
217 if transport_creds is not None:
218 c.transport_creds = transport_creds
220 c.transport_creds = self.transport_creds
222 if transport_impersonation is not None:
223 c.transport_impersonation = transport_impersonation
225 c.transport_impersonation = self.transport_impersonation
227 c.lp_ctx = self.lp_ctx
228 c.settings = self.settings
234 def get_user_creds(self):
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')
243 c.set_username(username)
244 c.set_password(password)
247 def get_anon_creds(self):
252 def get_auth_context_creds(self, creds, auth_type, auth_level,
257 if g_auth_level is None:
258 g_auth_level = auth_level
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)
265 if auth_type == dcerpc.DCERPC_AUTH_TYPE_KRB5:
267 elif auth_type == dcerpc.DCERPC_AUTH_TYPE_NTLMSSP:
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
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,
294 if auth_context is not None:
295 if auth_context['hdr_signing']:
296 pfc_flags |= dcerpc.DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
298 expect_3legs = auth_context["expect_3legs"]
301 (finished, to_server) = auth_context["gensec"].update(from_server)
302 self.assertFalse(finished)
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"],
312 req = self.generate_alter(call_id=call_id,
315 assoc_group_id=0xffffffff - assoc_group_id,
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,
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)
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)
341 req = self.generate_bind(call_id=call_id,
344 assoc_group_id=assoc_group_id,
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,
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)
357 self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_BIND_ACK, req.call_id,
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)
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
370 sda_pad = 4 - mod_len
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)
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])
384 if auth_context is None:
385 self.assertEqual(rep.auth_length, 0)
386 self.assertEqual(len(rep.u.auth_info), 0)
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)
392 a = self.parse_auth(rep.u.auth_info, auth_context=auth_context)
394 from_server = a.credentials
395 (finished, to_server) = auth_context["gensec"].update(from_server)
397 self.assertTrue(finished)
398 if auth_context['hdr_signing']:
399 auth_context["gensec"].want_feature(gensec.FEATURE_SIGN_PKT_HEADER)
401 self.assertFalse(use_auth3)
402 self.assertFalse(finished)
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"],
409 req = self.generate_auth3(call_id=call_id,
410 pfc_flags=pfc_flags_2nd,
413 rep = self.recv_pdu(timeout=0.01)
414 self.assertIsNone(rep)
415 self.assertIsConnected()
417 req = self.generate_alter(call_id=call_id,
419 pfc_flags=pfc_flags_2nd,
420 assoc_group_id=0xffffffff - assoc_group_id,
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,
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)
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])
452 self.assertEqual(rep.auth_length, 0)
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)
458 a = self.parse_auth(rep.u.auth_info, auth_context=auth_context)
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)
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,
478 self.epmap_reconnect(abstract, transfer=transfer, object=object)
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
487 ack = self.do_generic_bind(ctx=ctx,
488 auth_context=auth_context,
490 assoc_group_id=assoc_group_id)
498 def do_single_request(self, call_id, ctx, io,
501 bigendian=False, ndr64=False,
502 allow_remaining=False,
506 samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
507 samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST),
509 fault_context_id=None,
514 if fault_context_id is None:
515 fault_context_id = ctx.context_id
517 if ndr_print is None:
518 ndr_print = self.do_ndr_print
520 hexdump = self.do_hexdump
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)
527 sys.stderr.write("stub_in: %d\n%s" % (len(stub_in), self.hexdump(stub_in)))
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
534 req = self.generate_request_auth(call_id=call_id,
535 context_id=ctx.context_id,
540 auth_context=auth_context)
541 self.send_pdu(req, ndr_print=ndr_print, hexdump=hexdump)
543 (rep, rep_blob) = self.recv_pdu_raw(timeout=timeout,
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)
558 expected_auth_length = 0
559 if auth_context is not None and \
560 auth_context["auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PACKET:
562 expected_auth_length = req.auth_length
564 expected_auth_length = rep.auth_length
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)
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)
581 sys.stderr.write("out: %s" % samba.ndr.ndr_print_out(io))
583 def epmap_reconnect(self, abstract, transfer=None, object=None):
584 ndr32 = samba.dcerpc.base.transfer_syntax_ndr()
590 object = samba.dcerpc.misc.GUID()
592 ctx = self.prepare_presentation(samba.dcerpc.epmapper.abstract_syntax(),
593 transfer, context_id=0)
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()
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()
613 lhs3 = samba.dcerpc.epmapper.epm_lhs()
614 lhs3.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_NCACN
616 floor3 = samba.dcerpc.epmapper.epm_floor()
618 floor3.rhs.minor_version = 0
619 lhs4 = samba.dcerpc.epmapper.epm_lhs()
620 lhs4.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_TCP
622 floor4 = samba.dcerpc.epmapper.epm_floor()
624 floor4.rhs.port = int(self.primary_address)
625 lhs5 = samba.dcerpc.epmapper.epm_lhs()
626 lhs5.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_IP
628 floor5 = samba.dcerpc.epmapper.epm_floor()
630 floor5.rhs.ipaddr = "0.0.0.0"
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
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
645 self.do_single_request(call_id=2, ctx=ctx, io=epm_map)
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)
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
664 def send_pdu(self, req, ndr_print=None, hexdump=None):
665 if ndr_print is None:
666 ndr_print = self.do_ndr_print
668 hexdump = self.do_hexdump
670 req_pdu = ndr_pack(req)
672 sys.stderr.write("send_pdu: %s" % samba.ndr.ndr_print(req))
674 sys.stderr.write("send_pdu: %d\n%s" % (len(req_pdu), self.hexdump(req_pdu)))
676 sent = self.s.send(req_pdu, 0)
677 if sent == len(req_pdu):
679 req_pdu = req_pdu[sent:]
680 except socket.error as e:
681 self._disconnect("send_pdu: %s" % e)
684 self._disconnect("send_pdu: %s" % e)
686 except NTSTATUSError as e:
687 self._disconnect("send_pdu: %s" % e)
692 def recv_raw(self, hexdump=None, timeout=None):
695 hexdump = self.do_hexdump
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")
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")
710 except socket.error as e:
711 self._disconnect("recv_raw: %s" % e)
714 self._disconnect("recv_raw: %s" % e)
720 def recv_pdu_raw(self, ndr_print=None, hexdump=None, timeout=None):
723 if ndr_print is None:
724 ndr_print = self.do_ndr_print
726 hexdump = self.do_hexdump
728 rep_pdu = self.recv_raw(hexdump=hexdump, timeout=timeout)
731 rep = ndr_unpack(samba.dcerpc.dcerpc.ncacn_packet, rep_pdu, allow_remaining=True)
733 sys.stderr.write("recv_pdu: %s" % samba.ndr.ndr_print(rep))
734 self.assertEqual(rep.frag_length, len(rep_pdu))
737 return (rep, rep_pdu)
739 def recv_pdu(self, ndr_print=None, hexdump=None, timeout=None):
740 (rep, rep_pdu) = self.recv_pdu_raw(ndr_print=ndr_print,
745 def generate_auth(self,
749 auth_context_id=None,
751 ndr_print=None, hexdump=None):
752 if ndr_print is None:
753 ndr_print = self.do_ndr_print
755 hexdump = self.do_hexdump
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
767 sys.stderr.write("generate_auth: %s" % samba.ndr.ndr_print(a))
769 sys.stderr.write("generate_auth: %d\n%s" % (len(ai), self.hexdump(ai)))
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
780 hexdump = self.do_hexdump
782 if (len(auth_info) <= samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH):
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)
789 sys.stderr.write("parse_auth: %s" % samba.ndr.ndr_print(a))
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"])
797 self.assertLessEqual(a.auth_pad_length, dcerpc.DCERPC_AUTH_PAD_ALIGNMENT)
798 self.assertLessEqual(a.auth_pad_length, stub_len)
802 def check_response_auth(self, rep, rep_blob, auth_context=None,
803 auth_pad_length=None):
805 if auth_context is None:
806 self.assertEqual(rep.auth_length, 0)
807 return rep.u.stub_and_verifier
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
813 self.assertGreater(rep.auth_length, 0)
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:]
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)
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)
836 stub_out = rep_data[0:len(rep_data)-rep_auth_info.auth_pad_length]
840 def generate_pdu(self, ptype, call_id, payload,
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):
848 if getattr(payload, 'auth_info', None):
849 ai = payload.auth_info
853 p = samba.dcerpc.dcerpc.ncacn_packet()
854 p.rpc_vers = rpc_vers
855 p.rpc_vers_minor = rpc_vers_minor
857 p.pfc_flags = pfc_flags
860 if len(ai) > samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH:
861 p.auth_length = len(ai) - samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH
868 p.frag_length = len(pdu)
872 def generate_request_auth(self, call_id,
873 pfc_flags=(dcerpc.DCERPC_PFC_FLAG_FIRST |
874 dcerpc.DCERPC_PFC_FLAG_LAST),
881 ndr_print=None, hexdump=None):
887 if auth_context is not None:
888 mod_len = len(stub) % dcerpc.DCERPC_AUTH_PAD_ALIGNMENT
891 auth_pad_length = dcerpc.DCERPC_AUTH_PAD_ALIGNMENT - mod_len
892 stub += b'\x00' * auth_pad_length
894 if auth_context["g_auth_level"] >= samba.dcerpc.dcerpc.DCERPC_AUTH_LEVEL_PACKET:
895 sig_size = auth_context["gensec"].sig_size(len(stub))
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"],
908 req = self.generate_request(call_id=call_id,
910 alloc_hint=alloc_hint,
911 context_id=context_id,
918 if auth_context is None:
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]
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
939 self.assertEqual(len(req_sig), req.auth_length)
940 self.assertEqual(len(req_sig), sig_size)
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
948 def verify_pdu(self, p, ptype, call_id,
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],
956 self.assertIsNotNone(p, "No valid pdu")
958 if getattr(p.u, 'auth_info', None):
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)
976 self.assertEqual(p.auth_length, 0)
977 self.assertEqual(p.call_id, call_id)
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),
989 ndr_print=None, hexdump=None):
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
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
1004 p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_BIND,
1005 pfc_flags=pfc_flags,
1008 ndr_print=ndr_print, hexdump=hexdump)
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),
1020 ndr_print=None, hexdump=None):
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
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
1035 p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_ALTER,
1036 pfc_flags=pfc_flags,
1039 ndr_print=ndr_print, hexdump=hexdump)
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),
1047 ndr_print=None, hexdump=None):
1049 a = samba.dcerpc.dcerpc.auth3()
1050 a.auth_info = auth_info
1052 p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_AUTH3,
1053 pfc_flags=pfc_flags,
1056 ndr_print=ndr_print, hexdump=hexdump)
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),
1069 ndr_print=None, hexdump=None):
1071 if alloc_hint is None:
1072 alloc_hint = len(stub)
1074 r = samba.dcerpc.dcerpc.request()
1075 r.alloc_hint = alloc_hint
1076 r.context_id = context_id
1078 if object is not None:
1080 r.stub_and_verifier = stub + auth_info
1082 p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_REQUEST,
1083 pfc_flags=pfc_flags,
1086 ndr_print=ndr_print, hexdump=hexdump)
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
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),
1097 ndr_print=None, hexdump=None):
1099 c = samba.dcerpc.dcerpc.co_cancel()
1100 c.auth_info = auth_info
1102 p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_CO_CANCEL,
1103 pfc_flags=pfc_flags,
1106 ndr_print=ndr_print, hexdump=hexdump)
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),
1114 ndr_print=None, hexdump=None):
1116 o = samba.dcerpc.dcerpc.orphaned()
1117 o.auth_info = auth_info
1119 p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_ORPHANED,
1120 pfc_flags=pfc_flags,
1123 ndr_print=ndr_print, hexdump=hexdump)
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):
1132 s = samba.dcerpc.dcerpc.shutdown()
1134 p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_SHUTDOWN,
1135 pfc_flags=pfc_flags,
1138 ndr_print=ndr_print, hexdump=hexdump)
1142 def assertIsConnected(self):
1143 self.assertIsNotNone(self.s, msg="Not connected")
1146 def assertNotConnected(self):
1147 self.assertIsNone(self.s, msg="Is connected")
1150 def assertNDRSyntaxEquals(self, s1, s2):
1151 self.assertEqual(s1.uuid, s2.uuid)
1152 self.assertEqual(s1.if_version, s2.if_version)
1155 def assertPadding(self, pad, length):
1156 self.assertEqual(len(pad), length)
1158 # sometimes windows sends random bytes
1160 # we have IGNORE_RANDOM_PAD=1 to
1163 if self.ignore_random_pad:
1165 zero_pad = b'\0' * length
1166 self.assertEqual(pad, zero_pad)
1168 def assertEqualsStrLower(self, s1, s2):
1169 self.assertEqual(str(s1).lower(), str(s2).lower())