2016-09-08 10:05:22 +03:00
# Unix SMB/CIFS implementation.
# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2010
# Copyright (C) Stefan Metzmacher 2014,2015
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import sys
import socket
import struct
import samba . dcerpc . dcerpc
import samba . dcerpc . base
import samba . dcerpc . epmapper
import samba . tests
from samba import gensec
from samba . credentials import Credentials
from samba . tests import TestCase
2018-04-30 20:43:54 +03:00
from samba . ndr import ndr_pack , ndr_unpack , ndr_unpack_out
2016-09-08 10:05:22 +03:00
2018-07-30 09:20:39 +03:00
2016-09-08 10:05:22 +03:00
class RawDCERPCTest ( TestCase ) :
""" A raw DCE/RPC Test case. """
def _disconnect ( self , reason ) :
if self . s is None :
return
self . s . close ( )
self . s = None
if self . do_hexdump :
sys . stderr . write ( " disconnect[ %s ] \n " % reason )
def connect ( self ) :
try :
self . a = socket . getaddrinfo ( self . host , self . tcp_port , socket . AF_UNSPEC ,
socket . SOCK_STREAM , socket . SOL_TCP ,
0 )
self . s = socket . socket ( self . a [ 0 ] [ 0 ] , self . a [ 0 ] [ 1 ] , self . a [ 0 ] [ 2 ] )
self . s . settimeout ( 10 )
self . s . connect ( self . a [ 0 ] [ 4 ] )
except socket . error as e :
self . s . close ( )
raise
except IOError as e :
self . s . close ( )
raise
except Exception as e :
raise
finally :
pass
def setUp ( self ) :
super ( RawDCERPCTest , self ) . setUp ( )
self . do_ndr_print = False
self . do_hexdump = False
self . host = samba . tests . env_get_var_value ( ' SERVER ' )
self . target_hostname = samba . tests . env_get_var_value ( ' TARGET_HOSTNAME ' , allow_missing = True )
if self . target_hostname is None :
self . target_hostname = self . host
self . tcp_port = 135
self . settings = { }
self . settings [ " lp_ctx " ] = self . lp_ctx = samba . tests . env_loadparm ( )
self . settings [ " target_hostname " ] = self . target_hostname
self . connect ( )
def noop ( self ) :
return
def second_connection ( self , tcp_port = None ) :
c = RawDCERPCTest ( methodName = ' noop ' )
c . do_ndr_print = self . do_ndr_print
c . do_hexdump = self . do_hexdump
c . host = self . host
c . target_hostname = self . target_hostname
if tcp_port is not None :
c . tcp_port = tcp_port
else :
c . tcp_port = self . tcp_port
c . settings = self . settings
c . connect ( )
return c
def get_user_creds ( self ) :
c = Credentials ( )
c . guess ( )
username = samba . tests . env_get_var_value ( ' USERNAME ' )
password = samba . tests . env_get_var_value ( ' PASSWORD ' )
c . set_username ( username )
c . set_password ( password )
return c
def get_anon_creds ( self ) :
c = Credentials ( )
c . set_anonymous ( )
return c
def get_auth_context_creds ( self , creds , auth_type , auth_level ,
auth_context_id ,
g_auth_level = None ) :
if g_auth_level is None :
g_auth_level = auth_level
g = gensec . Security . start_client ( self . settings )
g . set_credentials ( creds )
g . want_feature ( gensec . FEATURE_DCE_STYLE )
g . start_mech_by_authtype ( auth_type , g_auth_level )
auth_context = { }
auth_context [ " auth_type " ] = auth_type
auth_context [ " auth_level " ] = auth_level
auth_context [ " auth_context_id " ] = auth_context_id
auth_context [ " g_auth_level " ] = g_auth_level
auth_context [ " gensec " ] = g
return auth_context
def do_generic_bind ( self , ctx , auth_context = None ,
pfc_flags = samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ,
assoc_group_id = 0 , call_id = 0 ,
nak_reason = None , alter_fault = None ) :
ctx_list = [ ctx ]
if auth_context is not None :
from_server = " "
( finished , to_server ) = auth_context [ " gensec " ] . update ( from_server )
self . assertFalse ( finished )
auth_info = self . generate_auth ( auth_type = auth_context [ " auth_type " ] ,
auth_level = auth_context [ " auth_level " ] ,
auth_context_id = auth_context [ " auth_context_id " ] ,
auth_blob = to_server )
else :
auth_info = " "
req = self . generate_bind ( call_id = call_id ,
pfc_flags = pfc_flags ,
ctx_list = ctx_list ,
assoc_group_id = assoc_group_id ,
auth_info = auth_info )
self . send_pdu ( req )
rep = self . recv_pdu ( )
if nak_reason is not None :
self . verify_pdu ( rep , samba . dcerpc . dcerpc . DCERPC_PKT_BIND_NAK , req . call_id ,
auth_length = 0 )
self . assertEquals ( rep . u . reject_reason , nak_reason )
self . assertEquals ( rep . u . num_versions , 1 )
self . assertEquals ( rep . u . versions [ 0 ] . rpc_vers , req . rpc_vers )
self . assertEquals ( rep . u . versions [ 0 ] . rpc_vers_minor , req . rpc_vers_minor )
self . assertEquals ( len ( rep . u . _pad ) , 3 )
self . assertEquals ( rep . u . _pad , ' \0 ' * 3 )
return
self . verify_pdu ( rep , samba . dcerpc . dcerpc . DCERPC_PKT_BIND_ACK , req . call_id ,
pfc_flags = pfc_flags )
self . assertEquals ( rep . u . max_xmit_frag , req . u . max_xmit_frag )
self . assertEquals ( rep . u . max_recv_frag , req . u . max_recv_frag )
if assoc_group_id != 0 :
self . assertEquals ( rep . u . assoc_group_id , assoc_group_id )
else :
self . assertNotEquals ( rep . u . assoc_group_id , 0 )
assoc_group_id = rep . u . assoc_group_id
port_str = " %d " % self . tcp_port
port_len = len ( port_str ) + 1
mod_len = ( 2 + port_len ) % 4
if mod_len != 0 :
port_pad = 4 - mod_len
else :
port_pad = 0
self . assertEquals ( rep . u . secondary_address_size , port_len )
self . assertEquals ( rep . u . secondary_address , port_str )
self . assertEquals ( len ( rep . u . _pad1 ) , port_pad )
# sometimes windows sends random bytes
# self.assertEquals(rep.u._pad1, '\0' * port_pad)
self . assertEquals ( rep . u . num_results , 1 )
self . assertEquals ( rep . u . ctx_list [ 0 ] . result ,
2018-07-30 09:16:12 +03:00
samba . dcerpc . dcerpc . DCERPC_BIND_ACK_RESULT_ACCEPTANCE )
2016-09-08 10:05:22 +03:00
self . assertEquals ( rep . u . ctx_list [ 0 ] . reason ,
2018-07-30 09:16:12 +03:00
samba . dcerpc . dcerpc . DCERPC_BIND_ACK_REASON_NOT_SPECIFIED )
2016-09-08 10:05:22 +03:00
self . assertNDRSyntaxEquals ( rep . u . ctx_list [ 0 ] . syntax , ctx . transfer_syntaxes [ 0 ] )
ack = rep
if auth_context is None :
self . assertEquals ( rep . auth_length , 0 )
self . assertEquals ( len ( rep . u . auth_info ) , 0 )
return ack
self . assertNotEquals ( rep . auth_length , 0 )
self . assertGreater ( len ( rep . u . auth_info ) , samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH )
self . assertEquals ( rep . auth_length , len ( rep . u . auth_info ) - samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH )
a = self . parse_auth ( rep . u . auth_info )
from_server = a . credentials
( finished , to_server ) = auth_context [ " gensec " ] . update ( from_server )
self . assertFalse ( finished )
auth_info = self . generate_auth ( auth_type = auth_context [ " auth_type " ] ,
auth_level = auth_context [ " auth_level " ] ,
auth_context_id = auth_context [ " auth_context_id " ] ,
auth_blob = to_server )
req = self . generate_alter ( call_id = call_id ,
ctx_list = ctx_list ,
2018-08-22 09:26:48 +03:00
assoc_group_id = 0xffffffff - assoc_group_id ,
2016-09-08 10:05:22 +03:00
auth_info = auth_info )
self . send_pdu ( req )
rep = self . recv_pdu ( )
if alter_fault is not None :
self . verify_pdu ( rep , samba . dcerpc . dcerpc . DCERPC_PKT_FAULT , req . call_id ,
pfc_flags = req . pfc_flags |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_DID_NOT_EXECUTE ,
auth_length = 0 )
self . assertNotEquals ( rep . u . alloc_hint , 0 )
self . assertEquals ( rep . u . context_id , 0 )
self . assertEquals ( rep . u . cancel_count , 0 )
self . assertEquals ( rep . u . flags , 0 )
self . assertEquals ( rep . u . status , alter_fault )
self . assertEquals ( rep . u . reserved , 0 )
self . assertEquals ( len ( rep . u . error_and_verifier ) , 0 )
return None
self . verify_pdu ( rep , samba . dcerpc . dcerpc . DCERPC_PKT_ALTER_RESP , req . call_id )
self . assertEquals ( rep . u . max_xmit_frag , req . u . max_xmit_frag )
self . assertEquals ( rep . u . max_recv_frag , req . u . max_recv_frag )
self . assertEquals ( rep . u . assoc_group_id , assoc_group_id )
self . assertEquals ( rep . u . secondary_address_size , 0 )
self . assertEquals ( rep . u . secondary_address , ' ' )
self . assertEquals ( len ( rep . u . _pad1 ) , 2 )
# sometimes windows sends random bytes
# self.assertEquals(rep.u._pad1, '\0' * 2)
self . assertEquals ( rep . u . num_results , 1 )
self . assertEquals ( rep . u . ctx_list [ 0 ] . result ,
2018-07-30 09:16:12 +03:00
samba . dcerpc . dcerpc . DCERPC_BIND_ACK_RESULT_ACCEPTANCE )
2016-09-08 10:05:22 +03:00
self . assertEquals ( rep . u . ctx_list [ 0 ] . reason ,
2018-07-30 09:16:12 +03:00
samba . dcerpc . dcerpc . DCERPC_BIND_ACK_REASON_NOT_SPECIFIED )
2016-09-08 10:05:22 +03:00
self . assertNDRSyntaxEquals ( rep . u . ctx_list [ 0 ] . syntax , ctx . transfer_syntaxes [ 0 ] )
self . assertNotEquals ( rep . auth_length , 0 )
self . assertGreater ( len ( rep . u . auth_info ) , samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH )
self . assertEquals ( rep . auth_length , len ( rep . u . auth_info ) - samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH )
a = self . parse_auth ( rep . u . auth_info )
from_server = a . credentials
( finished , to_server ) = auth_context [ " gensec " ] . update ( from_server )
self . assertTrue ( finished )
return ack
def prepare_presentation ( self , abstract , transfer , object = None ,
context_id = 0xffff , epmap = False , auth_context = None ,
pfc_flags = samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ,
assoc_group_id = 0 ,
return_ack = False ) :
if epmap :
self . epmap_reconnect ( abstract , transfer = transfer , object = object )
tsf1_list = [ transfer ]
ctx = samba . dcerpc . dcerpc . ctx_list ( )
ctx . context_id = context_id
ctx . num_transfer_syntaxes = len ( tsf1_list )
ctx . abstract_syntax = abstract
ctx . transfer_syntaxes = tsf1_list
ack = self . do_generic_bind ( ctx = ctx ,
auth_context = auth_context ,
pfc_flags = pfc_flags ,
assoc_group_id = assoc_group_id )
if ack is None :
ctx = None
if return_ack :
return ( ctx , ack )
return ctx
def do_single_request ( self , call_id , ctx , io ,
auth_context = None ,
object = None ,
bigendian = False , ndr64 = False ,
allow_remaining = False ,
send_req = True ,
recv_rep = True ,
2018-08-22 09:26:09 +03:00
fault_pfc_flags = (
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ) ,
2016-09-08 10:05:22 +03:00
fault_status = None ,
fault_context_id = None ,
timeout = None ,
ndr_print = None ,
hexdump = None ) :
if fault_context_id is None :
fault_context_id = ctx . context_id
if ndr_print is None :
ndr_print = self . do_ndr_print
if hexdump is None :
hexdump = self . do_hexdump
if send_req :
if ndr_print :
sys . stderr . write ( " in: %s " % samba . ndr . ndr_print_in ( io ) )
stub_in = samba . ndr . ndr_pack_in ( io , bigendian = bigendian , ndr64 = ndr64 )
if hexdump :
sys . stderr . write ( " stub_in: %d \n %s " % ( len ( stub_in ) , self . hexdump ( stub_in ) ) )
else :
# only used for sig_size calculation
stub_in = ' \xff ' * samba . dcerpc . dcerpc . DCERPC_AUTH_PAD_ALIGNMENT
sig_size = 0
if auth_context is not None :
mod_len = len ( stub_in ) % samba . dcerpc . dcerpc . DCERPC_AUTH_PAD_ALIGNMENT
auth_pad_length = 0
if mod_len > 0 :
auth_pad_length = samba . dcerpc . dcerpc . DCERPC_AUTH_PAD_ALIGNMENT - mod_len
stub_in + = ' \x00 ' * auth_pad_length
if auth_context [ " g_auth_level " ] > = samba . dcerpc . dcerpc . DCERPC_AUTH_LEVEL_PACKET :
sig_size = auth_context [ " gensec " ] . sig_size ( len ( stub_in ) )
else :
sig_size = 16
2018-07-30 09:18:25 +03:00
zero_sig = " \x00 " * sig_size
2016-09-08 10:05:22 +03:00
auth_info = self . generate_auth ( auth_type = auth_context [ " auth_type " ] ,
auth_level = auth_context [ " auth_level " ] ,
auth_pad_length = auth_pad_length ,
auth_context_id = auth_context [ " auth_context_id " ] ,
auth_blob = zero_sig )
else :
2018-07-30 09:18:03 +03:00
auth_info = " "
2016-09-08 10:05:22 +03:00
2018-07-30 09:17:44 +03:00
pfc_flags = samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST
2016-09-08 10:05:22 +03:00
pfc_flags | = samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST
if object is not None :
pfc_flags | = samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_OBJECT_UUID
req = self . generate_request ( call_id = call_id ,
context_id = ctx . context_id ,
pfc_flags = pfc_flags ,
object = object ,
opnum = io . opnum ( ) ,
stub = stub_in ,
auth_info = auth_info )
if send_req :
if sig_size != 0 and auth_context [ " auth_level " ] > = samba . dcerpc . dcerpc . DCERPC_AUTH_LEVEL_PACKET :
req_blob = samba . ndr . ndr_pack ( req )
ofs_stub = samba . dcerpc . dcerpc . DCERPC_REQUEST_LENGTH
ofs_sig = len ( req_blob ) - req . auth_length
ofs_trailer = ofs_sig - samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH
req_data = req_blob [ ofs_stub : ofs_trailer ]
req_whole = req_blob [ 0 : ofs_sig ]
sig = auth_context [ " gensec " ] . sign_packet ( req_data , req_whole )
auth_info = self . generate_auth ( auth_type = auth_context [ " auth_type " ] ,
auth_level = auth_context [ " auth_level " ] ,
auth_pad_length = auth_pad_length ,
auth_context_id = auth_context [ " auth_context_id " ] ,
auth_blob = sig )
req = self . generate_request ( call_id = call_id ,
context_id = ctx . context_id ,
pfc_flags = pfc_flags ,
object = object ,
opnum = io . opnum ( ) ,
stub = stub_in ,
auth_info = auth_info )
self . send_pdu ( req , ndr_print = ndr_print , hexdump = hexdump )
if recv_rep :
( rep , rep_blob ) = self . recv_pdu_raw ( timeout = timeout ,
ndr_print = ndr_print ,
hexdump = hexdump )
if fault_status :
self . verify_pdu ( rep , samba . dcerpc . dcerpc . DCERPC_PKT_FAULT , req . call_id ,
pfc_flags = fault_pfc_flags , auth_length = 0 )
self . assertNotEquals ( rep . u . alloc_hint , 0 )
self . assertEquals ( rep . u . context_id , fault_context_id )
self . assertEquals ( rep . u . cancel_count , 0 )
self . assertEquals ( rep . u . flags , 0 )
self . assertEquals ( rep . u . status , fault_status )
self . assertEquals ( rep . u . reserved , 0 )
self . assertEquals ( len ( rep . u . error_and_verifier ) , 0 )
return
self . verify_pdu ( rep , samba . dcerpc . dcerpc . DCERPC_PKT_RESPONSE , req . call_id ,
auth_length = sig_size )
self . assertNotEquals ( rep . u . alloc_hint , 0 )
self . assertEquals ( rep . u . context_id , req . u . context_id & 0xff )
self . assertEquals ( rep . u . cancel_count , 0 )
self . assertGreaterEqual ( len ( rep . u . stub_and_verifier ) , rep . u . alloc_hint )
if sig_size != 0 :
ofs_stub = samba . dcerpc . dcerpc . DCERPC_REQUEST_LENGTH
ofs_sig = rep . frag_length - rep . auth_length
ofs_trailer = ofs_sig - samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH
rep_data = rep_blob [ ofs_stub : ofs_trailer ]
rep_whole = rep_blob [ 0 : ofs_sig ]
rep_sig = rep_blob [ ofs_sig : ]
rep_auth_info_blob = rep_blob [ ofs_trailer : ]
rep_auth_info = self . parse_auth ( rep_auth_info_blob )
self . assertEquals ( rep_auth_info . auth_type , auth_context [ " auth_type " ] )
self . assertEquals ( rep_auth_info . auth_level , auth_context [ " auth_level " ] )
self . assertLessEqual ( rep_auth_info . auth_pad_length , len ( rep_data ) )
self . assertEquals ( rep_auth_info . auth_reserved , 0 )
self . assertEquals ( rep_auth_info . auth_context_id , auth_context [ " auth_context_id " ] )
self . assertEquals ( rep_auth_info . credentials , rep_sig )
if auth_context [ " auth_level " ] > = samba . dcerpc . dcerpc . DCERPC_AUTH_LEVEL_PACKET :
auth_context [ " gensec " ] . check_packet ( rep_data , rep_whole , rep_sig )
stub_out = rep_data [ 0 : - rep_auth_info . auth_pad_length ]
else :
stub_out = rep . u . stub_and_verifier
if hexdump :
sys . stderr . write ( " stub_out: %d \n %s " % ( len ( stub_out ) , self . hexdump ( stub_out ) ) )
2018-04-30 20:43:54 +03:00
ndr_unpack_out ( io , stub_out , bigendian = bigendian , ndr64 = ndr64 ,
2018-07-30 09:15:34 +03:00
allow_remaining = allow_remaining )
2016-09-08 10:05:22 +03:00
if ndr_print :
sys . stderr . write ( " out: %s " % samba . ndr . ndr_print_out ( io ) )
def epmap_reconnect ( self , abstract , transfer = None , object = None ) :
ndr32 = samba . dcerpc . base . transfer_syntax_ndr ( )
if transfer is None :
transfer = ndr32
if object is None :
object = samba . dcerpc . misc . GUID ( )
ctx = self . prepare_presentation ( samba . dcerpc . epmapper . abstract_syntax ( ) ,
transfer , context_id = 0 )
2018-04-30 20:43:54 +03:00
data1 = ndr_pack ( abstract )
2016-09-08 10:05:22 +03:00
lhs1 = samba . dcerpc . epmapper . epm_lhs ( )
lhs1 . protocol = samba . dcerpc . epmapper . EPM_PROTOCOL_UUID
lhs1 . lhs_data = data1 [ : 18 ]
rhs1 = samba . dcerpc . epmapper . epm_rhs_uuid ( )
rhs1 . unknown = data1 [ 18 : ]
floor1 = samba . dcerpc . epmapper . epm_floor ( )
floor1 . lhs = lhs1
floor1 . rhs = rhs1
2018-04-30 20:43:54 +03:00
data2 = ndr_pack ( transfer )
2016-09-08 10:05:22 +03:00
lhs2 = samba . dcerpc . epmapper . epm_lhs ( )
lhs2 . protocol = samba . dcerpc . epmapper . EPM_PROTOCOL_UUID
lhs2 . lhs_data = data2 [ : 18 ]
rhs2 = samba . dcerpc . epmapper . epm_rhs_uuid ( )
rhs2 . unknown = data1 [ 18 : ]
floor2 = samba . dcerpc . epmapper . epm_floor ( )
floor2 . lhs = lhs2
floor2 . rhs = rhs2
lhs3 = samba . dcerpc . epmapper . epm_lhs ( )
lhs3 . protocol = samba . dcerpc . epmapper . EPM_PROTOCOL_NCACN
lhs3 . lhs_data = " "
floor3 = samba . dcerpc . epmapper . epm_floor ( )
floor3 . lhs = lhs3
floor3 . rhs . minor_version = 0
lhs4 = samba . dcerpc . epmapper . epm_lhs ( )
lhs4 . protocol = samba . dcerpc . epmapper . EPM_PROTOCOL_TCP
lhs4 . lhs_data = " "
floor4 = samba . dcerpc . epmapper . epm_floor ( )
floor4 . lhs = lhs4
floor4 . rhs . port = self . tcp_port
lhs5 = samba . dcerpc . epmapper . epm_lhs ( )
lhs5 . protocol = samba . dcerpc . epmapper . EPM_PROTOCOL_IP
lhs5 . lhs_data = " "
floor5 = samba . dcerpc . epmapper . epm_floor ( )
floor5 . lhs = lhs5
floor5 . rhs . ipaddr = " 0.0.0.0 "
2018-07-30 09:19:05 +03:00
floors = [ floor1 , floor2 , floor3 , floor4 , floor5 ]
2016-09-08 10:05:22 +03:00
req_tower = samba . dcerpc . epmapper . epm_tower ( )
req_tower . num_floors = len ( floors )
req_tower . floors = floors
req_twr = samba . dcerpc . epmapper . epm_twr_t ( )
req_twr . tower = req_tower
epm_map = samba . dcerpc . epmapper . epm_Map ( )
epm_map . in_object = object
epm_map . in_map_tower = req_twr
epm_map . in_entry_handle = samba . dcerpc . misc . policy_handle ( )
epm_map . in_max_towers = 4
self . do_single_request ( call_id = 2 , ctx = ctx , io = epm_map )
self . assertGreaterEqual ( epm_map . out_num_towers , 1 )
rep_twr = epm_map . out_towers [ 0 ] . twr
self . assertIsNotNone ( rep_twr )
self . assertEqual ( rep_twr . tower_length , 75 )
self . assertEqual ( rep_twr . tower . num_floors , 5 )
self . assertEqual ( len ( rep_twr . tower . floors ) , 5 )
self . assertEqual ( rep_twr . tower . floors [ 3 ] . lhs . protocol ,
2018-07-30 09:15:34 +03:00
samba . dcerpc . epmapper . EPM_PROTOCOL_TCP )
2016-09-08 10:05:22 +03:00
self . assertEqual ( rep_twr . tower . floors [ 3 ] . lhs . protocol ,
2018-07-30 09:15:34 +03:00
samba . dcerpc . epmapper . EPM_PROTOCOL_TCP )
2016-09-08 10:05:22 +03:00
# reconnect to the given port
self . _disconnect ( " epmap_reconnect " )
self . tcp_port = rep_twr . tower . floors [ 3 ] . rhs . port
self . connect ( )
def send_pdu ( self , req , ndr_print = None , hexdump = None ) :
if ndr_print is None :
ndr_print = self . do_ndr_print
if hexdump is None :
hexdump = self . do_hexdump
try :
2018-04-30 20:43:54 +03:00
req_pdu = ndr_pack ( req )
2016-09-08 10:05:22 +03:00
if ndr_print :
sys . stderr . write ( " send_pdu: %s " % samba . ndr . ndr_print ( req ) )
if hexdump :
sys . stderr . write ( " send_pdu: %d \n %s " % ( len ( req_pdu ) , self . hexdump ( req_pdu ) ) )
while True :
sent = self . s . send ( req_pdu , 0 )
if sent == len ( req_pdu ) :
break
req_pdu = req_pdu [ sent : ]
except socket . error as e :
self . _disconnect ( " send_pdu: %s " % e )
raise
except IOError as e :
self . _disconnect ( " send_pdu: %s " % e )
raise
finally :
pass
def recv_raw ( self , hexdump = None , timeout = None ) :
rep_pdu = None
if hexdump is None :
hexdump = self . do_hexdump
try :
if timeout is not None :
self . s . settimeout ( timeout )
rep_pdu = self . s . recv ( 0xffff , 0 )
self . s . settimeout ( 10 )
if len ( rep_pdu ) == 0 :
self . _disconnect ( " recv_raw: EOF " )
return None
if hexdump :
sys . stderr . write ( " recv_raw: %d \n %s " % ( len ( rep_pdu ) , self . hexdump ( rep_pdu ) ) )
except socket . timeout as e :
self . s . settimeout ( 10 )
sys . stderr . write ( " recv_raw: TIMEOUT \n " )
pass
except socket . error as e :
self . _disconnect ( " recv_raw: %s " % e )
raise
except IOError as e :
self . _disconnect ( " recv_raw: %s " % e )
raise
finally :
pass
return rep_pdu
def recv_pdu_raw ( self , ndr_print = None , hexdump = None , timeout = None ) :
rep_pdu = None
rep = None
if ndr_print is None :
ndr_print = self . do_ndr_print
if hexdump is None :
hexdump = self . do_hexdump
try :
rep_pdu = self . recv_raw ( hexdump = hexdump , timeout = timeout )
if rep_pdu is None :
2018-07-30 09:19:05 +03:00
return ( None , None )
2018-04-30 20:43:54 +03:00
rep = ndr_unpack ( samba . dcerpc . dcerpc . ncacn_packet , rep_pdu , allow_remaining = True )
2016-09-08 10:05:22 +03:00
if ndr_print :
sys . stderr . write ( " recv_pdu: %s " % samba . ndr . ndr_print ( rep ) )
self . assertEqual ( rep . frag_length , len ( rep_pdu ) )
finally :
pass
return ( rep , rep_pdu )
def recv_pdu ( self , ndr_print = None , hexdump = None , timeout = None ) :
( rep , rep_pdu ) = self . recv_pdu_raw ( ndr_print = ndr_print ,
hexdump = hexdump ,
timeout = timeout )
return rep
def generate_auth ( self ,
auth_type = None ,
auth_level = None ,
auth_pad_length = 0 ,
auth_context_id = None ,
auth_blob = None ,
ndr_print = None , hexdump = None ) :
if ndr_print is None :
ndr_print = self . do_ndr_print
if hexdump is None :
hexdump = self . do_hexdump
if auth_type is not None :
a = samba . dcerpc . dcerpc . auth ( )
a . auth_type = auth_type
a . auth_level = auth_level
a . auth_pad_length = auth_pad_length
2018-07-30 09:18:03 +03:00
a . auth_context_id = auth_context_id
2016-09-08 10:05:22 +03:00
a . credentials = auth_blob
2018-04-30 20:43:54 +03:00
ai = ndr_pack ( a )
2016-09-08 10:05:22 +03:00
if ndr_print :
sys . stderr . write ( " generate_auth: %s " % samba . ndr . ndr_print ( a ) )
if hexdump :
sys . stderr . write ( " generate_auth: %d \n %s " % ( len ( ai ) , self . hexdump ( ai ) ) )
else :
ai = " "
return ai
def parse_auth ( self , auth_info , ndr_print = None , hexdump = None ) :
if ndr_print is None :
ndr_print = self . do_ndr_print
if hexdump is None :
hexdump = self . do_hexdump
if ( len ( auth_info ) < = samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH ) :
return None
if hexdump :
sys . stderr . write ( " parse_auth: %d \n %s " % ( len ( auth_info ) , self . hexdump ( auth_info ) ) )
2018-04-30 20:43:54 +03:00
a = ndr_unpack ( samba . dcerpc . dcerpc . auth , auth_info , allow_remaining = True )
2016-09-08 10:05:22 +03:00
if ndr_print :
sys . stderr . write ( " parse_auth: %s " % samba . ndr . ndr_print ( a ) )
return a
def generate_pdu ( self , ptype , call_id , payload ,
rpc_vers = 5 ,
rpc_vers_minor = 0 ,
2018-08-22 09:26:09 +03:00
pfc_flags = ( samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ) ,
2018-07-30 09:19:21 +03:00
drep = [ samba . dcerpc . dcerpc . DCERPC_DREP_LE , 0 , 0 , 0 ] ,
2016-09-08 10:05:22 +03:00
ndr_print = None , hexdump = None ) :
if getattr ( payload , ' auth_info ' , None ) :
ai = payload . auth_info
else :
ai = " "
p = samba . dcerpc . dcerpc . ncacn_packet ( )
p . rpc_vers = rpc_vers
p . rpc_vers_minor = rpc_vers_minor
p . ptype = ptype
p . pfc_flags = pfc_flags
p . drep = drep
p . frag_length = 0
if len ( ai ) > samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH :
p . auth_length = len ( ai ) - samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH
else :
p . auth_length = 0
p . call_id = call_id
p . u = payload
2018-04-30 20:43:54 +03:00
pdu = ndr_pack ( p )
2016-09-08 10:05:22 +03:00
p . frag_length = len ( pdu )
return p
def verify_pdu ( self , p , ptype , call_id ,
rpc_vers = 5 ,
rpc_vers_minor = 0 ,
2018-08-22 09:26:09 +03:00
pfc_flags = ( samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ) ,
2018-07-30 09:19:21 +03:00
drep = [ samba . dcerpc . dcerpc . DCERPC_DREP_LE , 0 , 0 , 0 ] ,
2016-09-08 10:05:22 +03:00
auth_length = None ) :
self . assertIsNotNone ( p , " No valid pdu " )
if getattr ( p . u , ' auth_info ' , None ) :
ai = p . u . auth_info
else :
ai = " "
self . assertEqual ( p . rpc_vers , rpc_vers )
self . assertEqual ( p . rpc_vers_minor , rpc_vers_minor )
self . assertEqual ( p . ptype , ptype )
self . assertEqual ( p . pfc_flags , pfc_flags )
self . assertEqual ( p . drep , drep )
self . assertGreaterEqual ( p . frag_length ,
2018-07-30 09:16:12 +03:00
samba . dcerpc . dcerpc . DCERPC_NCACN_PAYLOAD_OFFSET )
2016-09-08 10:05:22 +03:00
if len ( ai ) > samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH :
self . assertEqual ( p . auth_length ,
2018-07-30 09:16:12 +03:00
len ( ai ) - samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH )
2016-09-08 10:05:22 +03:00
elif auth_length is not None :
self . assertEqual ( p . auth_length , auth_length )
else :
self . assertEqual ( p . auth_length , 0 )
self . assertEqual ( p . call_id , call_id )
return
def generate_bind ( self , call_id ,
2018-08-22 09:26:09 +03:00
pfc_flags = ( samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ) ,
2016-09-08 10:05:22 +03:00
max_xmit_frag = 5840 ,
max_recv_frag = 5840 ,
assoc_group_id = 0 ,
ctx_list = [ ] ,
auth_info = " " ,
ndr_print = None , hexdump = None ) :
b = samba . dcerpc . dcerpc . bind ( )
b . max_xmit_frag = max_xmit_frag
b . max_recv_frag = max_recv_frag
b . assoc_group_id = assoc_group_id
b . num_contexts = len ( ctx_list )
b . ctx_list = ctx_list
b . auth_info = auth_info
p = self . generate_pdu ( ptype = samba . dcerpc . dcerpc . DCERPC_PKT_BIND ,
pfc_flags = pfc_flags ,
call_id = call_id ,
payload = b ,
ndr_print = ndr_print , hexdump = hexdump )
return p
def generate_alter ( self , call_id ,
2018-08-22 09:26:09 +03:00
pfc_flags = ( samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ) ,
2016-09-08 10:05:22 +03:00
max_xmit_frag = 5840 ,
max_recv_frag = 5840 ,
assoc_group_id = 0 ,
ctx_list = [ ] ,
auth_info = " " ,
ndr_print = None , hexdump = None ) :
a = samba . dcerpc . dcerpc . bind ( )
a . max_xmit_frag = max_xmit_frag
a . max_recv_frag = max_recv_frag
a . assoc_group_id = assoc_group_id
a . num_contexts = len ( ctx_list )
a . ctx_list = ctx_list
a . auth_info = auth_info
p = self . generate_pdu ( ptype = samba . dcerpc . dcerpc . DCERPC_PKT_ALTER ,
pfc_flags = pfc_flags ,
call_id = call_id ,
payload = a ,
ndr_print = ndr_print , hexdump = hexdump )
return p
def generate_auth3 ( self , call_id ,
2018-08-22 09:26:09 +03:00
pfc_flags = ( samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ) ,
2016-09-08 10:05:22 +03:00
auth_info = " " ,
ndr_print = None , hexdump = None ) :
a = samba . dcerpc . dcerpc . auth3 ( )
a . auth_info = auth_info
p = self . generate_pdu ( ptype = samba . dcerpc . dcerpc . DCERPC_PKT_AUTH3 ,
pfc_flags = pfc_flags ,
call_id = call_id ,
payload = a ,
ndr_print = ndr_print , hexdump = hexdump )
return p
def generate_request ( self , call_id ,
2018-08-22 09:26:09 +03:00
pfc_flags = ( samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ) ,
2016-09-08 10:05:22 +03:00
alloc_hint = None ,
context_id = None ,
opnum = None ,
object = None ,
stub = None ,
auth_info = " " ,
ndr_print = None , hexdump = None ) :
if alloc_hint is None :
alloc_hint = len ( stub )
r = samba . dcerpc . dcerpc . request ( )
r . alloc_hint = alloc_hint
r . context_id = context_id
r . opnum = opnum
if object is not None :
r . object = object
r . stub_and_verifier = stub + auth_info
p = self . generate_pdu ( ptype = samba . dcerpc . dcerpc . DCERPC_PKT_REQUEST ,
pfc_flags = pfc_flags ,
call_id = call_id ,
payload = r ,
ndr_print = ndr_print , hexdump = hexdump )
if len ( auth_info ) > samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH :
p . auth_length = len ( auth_info ) - samba . dcerpc . dcerpc . DCERPC_AUTH_TRAILER_LENGTH
return p
def generate_co_cancel ( self , call_id ,
2018-08-22 09:26:09 +03:00
pfc_flags = ( samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ) ,
2016-09-08 10:05:22 +03:00
auth_info = " " ,
ndr_print = None , hexdump = None ) :
c = samba . dcerpc . dcerpc . co_cancel ( )
c . auth_info = auth_info
p = self . generate_pdu ( ptype = samba . dcerpc . dcerpc . DCERPC_PKT_CO_CANCEL ,
pfc_flags = pfc_flags ,
call_id = call_id ,
payload = c ,
ndr_print = ndr_print , hexdump = hexdump )
return p
def generate_orphaned ( self , call_id ,
2018-08-22 09:26:09 +03:00
pfc_flags = ( samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ) ,
2016-09-08 10:05:22 +03:00
auth_info = " " ,
ndr_print = None , hexdump = None ) :
o = samba . dcerpc . dcerpc . orphaned ( )
o . auth_info = auth_info
p = self . generate_pdu ( ptype = samba . dcerpc . dcerpc . DCERPC_PKT_ORPHANED ,
pfc_flags = pfc_flags ,
call_id = call_id ,
payload = o ,
ndr_print = ndr_print , hexdump = hexdump )
return p
def generate_shutdown ( self , call_id ,
2018-08-22 09:26:09 +03:00
pfc_flags = ( samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_FIRST |
samba . dcerpc . dcerpc . DCERPC_PFC_FLAG_LAST ) ,
2016-09-08 10:05:22 +03:00
ndr_print = None , hexdump = None ) :
s = samba . dcerpc . dcerpc . shutdown ( )
p = self . generate_pdu ( ptype = samba . dcerpc . dcerpc . DCERPC_PKT_SHUTDOWN ,
pfc_flags = pfc_flags ,
call_id = call_id ,
payload = s ,
ndr_print = ndr_print , hexdump = hexdump )
return p
def assertIsConnected ( self ) :
self . assertIsNotNone ( self . s , msg = " Not connected " )
return
def assertNotConnected ( self ) :
self . assertIsNone ( self . s , msg = " Is connected " )
return
def assertNDRSyntaxEquals ( self , s1 , s2 ) :
self . assertEqual ( s1 . uuid , s2 . uuid )
self . assertEqual ( s1 . if_version , s2 . if_version )
return