1# Copyright (c) 2003-2016 CORE Security Technologies
2#
3# This software is provided under under a slightly modified version
4# of the Apache Software License. See the accompanying LICENSE file
5# for more information.
6#
7# Author: Alberto Solino (@agsolino)
8#
9# Description:
10#   [MS-DCOM] Interface implementation
11#
12#   Best way to learn how to use these calls is to grab the protocol standard
13#   so you understand what the call does, and then read the test case located
14#   at https://github.com/CoreSecurity/impacket/tree/master/impacket/testcases/SMB_RPC
15#
16#   Some calls have helper functions, which makes it even easier to use.
17#   They are located at the end of this file.
18#   Helper functions start with "h"<name of the call>.
19#   There are test cases for them too.
20#
21# ToDo:
22# [X] Use the same DCE connection for all the calls. Right now is connecting to the remote machine
23#     for each call, making it slower.
24#
25# [X] Implement a ping mechanism, otherwise the garbage collector at the server shuts down the objects if
26#    not used, returning RPC_E_DISCONNECTED
27#
28
29import socket
30from struct import pack
31from threading import Timer, currentThread
32
33from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray, NDRTLSTRUCT, UNKNOWNDATA
34from impacket.dcerpc.v5.dtypes import LPWSTR, ULONGLONG, HRESULT, GUID, USHORT, WSTR, DWORD, LPLONG, LONG, PGUID, ULONG, \
35    UUID, WIDESTR, NULL
36from impacket import hresult_errors, LOG
37from impacket.uuid import string_to_bin, uuidtup_to_bin, generate
38from impacket.dcerpc.v5.rpcrt import TypeSerialization1, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_NONE, \
39    RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_WINNT, DCERPCException
40from impacket.dcerpc.v5 import transport
41
42CLSID_ActivationContextInfo   = string_to_bin('000001a5-0000-0000-c000-000000000046')
43CLSID_ActivationPropertiesIn  = string_to_bin('00000338-0000-0000-c000-000000000046')
44CLSID_ActivationPropertiesOut = string_to_bin('00000339-0000-0000-c000-000000000046')
45CLSID_CONTEXT_EXTENSION       = string_to_bin('00000334-0000-0000-c000-000000000046')
46CLSID_ContextMarshaler        = string_to_bin('0000033b-0000-0000-c000-000000000046')
47CLSID_ERROR_EXTENSION         = string_to_bin('0000031c-0000-0000-c000-000000000046')
48CLSID_ErrorObject             = string_to_bin('0000031b-0000-0000-c000-000000000046')
49CLSID_InstanceInfo            = string_to_bin('000001ad-0000-0000-c000-000000000046')
50CLSID_InstantiationInfo       = string_to_bin('000001ab-0000-0000-c000-000000000046')
51CLSID_PropsOutInfo            = string_to_bin('00000339-0000-0000-c000-000000000046')
52CLSID_ScmReplyInfo            = string_to_bin('000001b6-0000-0000-c000-000000000046')
53CLSID_ScmRequestInfo          = string_to_bin('000001aa-0000-0000-c000-000000000046')
54CLSID_SecurityInfo            = string_to_bin('000001a6-0000-0000-c000-000000000046')
55CLSID_ServerLocationInfo      = string_to_bin('000001a4-0000-0000-c000-000000000046')
56CLSID_SpecialSystemProperties = string_to_bin('000001b9-0000-0000-c000-000000000046')
57IID_IActivation               = uuidtup_to_bin(('4d9f4ab8-7d1c-11cf-861e-0020af6e7c57','0.0'))
58IID_IActivationPropertiesIn   = uuidtup_to_bin(('000001A2-0000-0000-C000-000000000046','0.0'))
59IID_IActivationPropertiesOut  = uuidtup_to_bin(('000001A3-0000-0000-C000-000000000046','0.0'))
60IID_IContext                  = uuidtup_to_bin(('000001c0-0000-0000-C000-000000000046','0.0'))
61IID_IObjectExporter           = uuidtup_to_bin(('99fcfec4-5260-101b-bbcb-00aa0021347a','0.0'))
62IID_IRemoteSCMActivator       = uuidtup_to_bin(('000001A0-0000-0000-C000-000000000046','0.0'))
63IID_IRemUnknown               = uuidtup_to_bin(('00000131-0000-0000-C000-000000000046','0.0'))
64IID_IRemUnknown2              = uuidtup_to_bin(('00000143-0000-0000-C000-000000000046','0.0'))
65IID_IUnknown                  = uuidtup_to_bin(('00000000-0000-0000-C000-000000000046','0.0'))
66IID_IClassFactory             = uuidtup_to_bin(('00000001-0000-0000-C000-000000000046','0.0'))
67
68class DCERPCSessionError(DCERPCException):
69    def __init__(self, error_string=None, error_code=None, packet=None):
70        DCERPCException.__init__(self, error_string, error_code, packet)
71
72    def __str__( self ):
73        if hresult_errors.ERROR_MESSAGES.has_key(self.error_code):
74            error_msg_short = hresult_errors.ERROR_MESSAGES[self.error_code][0]
75            error_msg_verbose = hresult_errors.ERROR_MESSAGES[self.error_code][1]
76            return 'DCOM SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)
77        else:
78            return 'DCOM SessionError: unknown error code: 0x%x' % self.error_code
79
80################################################################################
81# CONSTANTS
82################################################################################
83# 2.2.1 OID
84OID = ULONGLONG
85
86class OID_ARRAY(NDRUniConformantArray):
87    item = OID
88
89class POID_ARRAY(NDRPOINTER):
90    referent = (
91        ('Data', OID_ARRAY),
92    )
93
94# 2.2.2 SETID
95SETID = ULONGLONG
96
97# 2.2.4 error_status_t
98error_status_t = ULONG
99
100# 2.2.6 CID
101CID = GUID
102
103# 2.2.7 CLSID
104CLSID = GUID
105
106# 2.2.8 IID
107IID = GUID
108PIID = PGUID
109
110# 2.2.9 IPID
111IPID = GUID
112
113# 2.2.10 OXID
114OXID = ULONGLONG
115
116# 2.2.18 OBJREF
117FLAGS_OBJREF_STANDARD = 0x00000001
118FLAGS_OBJREF_HANDLER  = 0x00000002
119FLAGS_OBJREF_CUSTOM   = 0x00000004
120FLAGS_OBJREF_EXTENDED = 0x00000008
121
122# 2.2.18.1 STDOBJREF
123SORF_NOPING = 0x00001000
124
125# 2.2.20 Context
126CTXMSHLFLAGS_BYVAL = 0x00000002
127
128# 2.2.20.1 PROPMARSHALHEADER
129CPFLAG_PROPAGATE = 0x00000001
130CPFLAG_EXPOSE    = 0x00000002
131CPFLAG_ENVOY     = 0x00000004
132
133# 2.2.22.2.1 InstantiationInfoData
134ACTVFLAGS_DISABLE_AAA            = 0x00000002
135ACTVFLAGS_ACTIVATE_32_BIT_SERVER = 0x00000004
136ACTVFLAGS_ACTIVATE_64_BIT_SERVER = 0x00000008
137ACTVFLAGS_NO_FAILURE_LOG         = 0x00000020
138
139# 2.2.22.2.2 SpecialPropertiesData
140SPD_FLAG_USE_CONSOLE_SESSION  = 0x00000001
141
142# 2.2.28.1 IDL Range Constants
143MAX_REQUESTED_INTERFACES = 0x8000
144MAX_REQUESTED_PROTSEQS   = 0x8000
145MIN_ACTPROP_LIMIT        = 1
146MAX_ACTPROP_LIMIT        = 10
147
148################################################################################
149# STRUCTURES
150################################################################################
151class handle_t(NDRSTRUCT):
152    structure =  (
153        ('context_handle_attributes',ULONG),
154        ('context_handle_uuid',UUID),
155    )
156    def __init__(self, data = None,isNDR64 = False):
157        NDRSTRUCT.__init__(self, data, isNDR64)
158        self['context_handle_uuid'] = '\x00'*20
159
160# 2.2.11 COMVERSION
161class COMVERSION(NDRSTRUCT):
162    structure = (
163        ('MajorVersion',USHORT),
164        ('MinorVersion',USHORT),
165    )
166    def __init__(self, data = None,isNDR64 = False):
167        NDRSTRUCT.__init__(self, data, isNDR64)
168        if data is None:
169            self['MajorVersion'] = 5
170            self['MinorVersion'] = 6
171
172class PCOMVERSION(NDRPOINTER):
173    referent = (
174        ('Data', COMVERSION),
175    )
176
177# 2.2.13.1 ORPC_EXTENT
178# This MUST contain an array of bytes that form the extent data.
179# The array size MUST be a multiple of 8 for alignment reasons.
180class BYTE_ARRAY(NDRUniConformantArray):
181    item = 'c'
182
183class ORPC_EXTENT(NDRSTRUCT):
184    structure = (
185        ('id',GUID),
186        ('size',ULONG),
187        ('data',BYTE_ARRAY),
188    )
189
190# 2.2.13.2 ORPC_EXTENT_ARRAY
191# ThisMUSTbeanarrayofORPC_EXTENTs.ThearraysizeMUSTbeamultipleof2for alignment reasons.
192class PORPC_EXTENT(NDRPOINTER):
193    referent = (
194        ('Data', ORPC_EXTENT),
195    )
196
197class EXTENT_ARRAY(NDRUniConformantArray):
198    item = PORPC_EXTENT
199
200class PEXTENT_ARRAY(NDRPOINTER):
201    referent = (
202        ('Data', EXTENT_ARRAY),
203    )
204
205class ORPC_EXTENT_ARRAY(NDRSTRUCT):
206    structure = (
207        ('size',ULONG),
208        ('reserved',ULONG),
209        ('extent',PEXTENT_ARRAY),
210    )
211
212class PORPC_EXTENT_ARRAY(NDRPOINTER):
213    referent = (
214        ('Data', ORPC_EXTENT_ARRAY),
215    )
216
217# 2.2.13.3 ORPCTHIS
218class ORPCTHIS(NDRSTRUCT):
219    structure = (
220        ('version',COMVERSION),
221        ('flags',ULONG),
222        ('reserved1',ULONG),
223        ('cid',CID),
224        ('extensions',PORPC_EXTENT_ARRAY),
225    )
226
227# 2.2.13.4 ORPCTHAT
228class ORPCTHAT(NDRSTRUCT):
229    structure = (
230        ('flags',ULONG),
231        ('extensions',PORPC_EXTENT_ARRAY),
232    )
233
234# 2.2.14 MInterfacePointer
235class MInterfacePointer(NDRSTRUCT):
236    structure = (
237        ('ulCntData',ULONG),
238        ('abData',BYTE_ARRAY),
239    )
240
241# 2.2.15 PMInterfacePointerInternal
242class PMInterfacePointerInternal(NDRPOINTER):
243    referent = (
244        ('Data', MInterfacePointer),
245    )
246
247# 2.2.16 PMInterfacePointer
248class PMInterfacePointer(NDRPOINTER):
249    referent = (
250        ('Data', MInterfacePointer),
251    )
252
253class PPMInterfacePointer(NDRPOINTER):
254    referent = (
255        ('Data', PMInterfacePointer),
256    )
257
258# 2.2.18 OBJREF
259class OBJREF(NDRSTRUCT):
260    commonHdr = (
261        ('signature',ULONG),
262        ('flags',ULONG),
263        ('iid',GUID),
264    )
265    def __init__(self, data = None,isNDR64 = False):
266        NDRSTRUCT.__init__(self, data, isNDR64)
267        if data is None:
268            self['signature'] = 0x574F454D
269
270# 2.2.18.1 STDOBJREF
271class STDOBJREF(NDRSTRUCT):
272    structure = (
273        ('flags',ULONG),
274        ('cPublicRefs',ULONG),
275        ('oxid',OXID),
276        ('oid',OID),
277        ('ipid',IPID),
278    )
279
280# 2.2.18.4 OBJREF_STANDARD
281class OBJREF_STANDARD(OBJREF):
282    structure = (
283        ('std',STDOBJREF),
284        ('saResAddr',':'),
285    )
286    def __init__(self, data = None,isNDR64 = False):
287        OBJREF.__init__(self, data, isNDR64)
288        if data is None:
289            self['flags'] = FLAGS_OBJREF_STANDARD
290
291# 2.2.18.5 OBJREF_HANDLER
292class OBJREF_HANDLER(OBJREF):
293    structure = (
294        ('std',STDOBJREF),
295        ('clsid',CLSID),
296        ('saResAddr',':'),
297    )
298    def __init__(self, data = None,isNDR64 = False):
299        OBJREF.__init__(self, data, isNDR64)
300        if data is None:
301            self['flags'] = FLAGS_OBJREF_HANDLER
302
303# 2.2.18.6 OBJREF_CUSTOM
304class OBJREF_CUSTOM(OBJREF):
305    structure = (
306        ('clsid',CLSID),
307        ('cbExtension',ULONG),
308        ('ObjectReferenceSize',ULONG),
309        ('pObjectData',':'),
310    )
311    def __init__(self, data = None,isNDR64 = False):
312        OBJREF.__init__(self, data, isNDR64)
313        if data is None:
314            self['flags'] = FLAGS_OBJREF_CUSTOM
315
316# 2.2.18.8 DATAELEMENT
317class DATAELEMENT(NDRSTRUCT):
318    structure = (
319        ('dataID',GUID),
320        ('cbSize',ULONG),
321        ('cbRounded',ULONG),
322        ('Data',':'),
323    )
324
325class DUALSTRINGARRAYPACKED(NDRSTRUCT):
326    structure = (
327        ('wNumEntries',USHORT),
328        ('wSecurityOffset',USHORT),
329        ('aStringArray',':'),
330    )
331    def getDataLen(self, data):
332        return self['wNumEntries']*2
333
334# 2.2.18.7 OBJREF_EXTENDED
335class OBJREF_EXTENDED(OBJREF):
336    structure = (
337        ('std',STDOBJREF),
338        ('Signature1',ULONG),
339        ('saResAddr',DUALSTRINGARRAYPACKED),
340        ('nElms',ULONG),
341        ('Signature2',ULONG),
342        ('ElmArray',DATAELEMENT),
343    )
344    def __init__(self, data = None, isNDR64 = False):
345        OBJREF.__init__(self, data, isNDR64)
346        if data is None:
347            self['flags'] = FLAGS_OBJREF_EXTENDED
348            self['Signature1'] = 0x4E535956
349            self['Signature1'] = 0x4E535956
350            self['nElms'] = 0x4E535956
351
352# 2.2.19 DUALSTRINGARRAY
353class USHORT_ARRAY(NDRUniConformantArray):
354    item = '<H'
355
356class PUSHORT_ARRAY(NDRPOINTER):
357    referent = (
358        ('Data', USHORT_ARRAY),
359    )
360
361class DUALSTRINGARRAY(NDRSTRUCT):
362    structure = (
363        ('wNumEntries',USHORT),
364        ('wSecurityOffset',USHORT),
365        ('aStringArray',USHORT_ARRAY),
366    )
367
368class PDUALSTRINGARRAY(NDRPOINTER):
369    referent = (
370        ('Data',DUALSTRINGARRAY),
371    )
372
373# 2.2.19.3 STRINGBINDING
374class STRINGBINDING(NDRSTRUCT):
375    structure = (
376        ('wTowerId',USHORT),
377        ('aNetworkAddr',WIDESTR),
378    )
379
380# 2.2.19.4 SECURITYBINDING
381class SECURITYBINDING(NDRSTRUCT):
382    structure = (
383        ('wAuthnSvc',USHORT),
384        ('Reserved',USHORT),
385        ('aPrincName',WIDESTR),
386    )
387
388# 2.2.20.1 PROPMARSHALHEADER
389class PROPMARSHALHEADER(NDRSTRUCT):
390    structure = (
391        ('clsid',CLSID),
392        ('policyId',GUID),
393        ('flags',ULONG),
394        ('cb',ULONG),
395        ('ctxProperty',':'),
396    )
397
398class PROPMARSHALHEADER_ARRAY(NDRUniConformantArray):
399    item = PROPMARSHALHEADER
400
401# 2.2.20 Context
402class Context(NDRSTRUCT):
403    structure = (
404        ('MajorVersion',USHORT),
405        ('MinVersion',USHORT),
406        ('ContextId',GUID),
407        ('Flags',ULONG),
408        ('Reserved',ULONG),
409        ('dwNumExtents',ULONG),
410        ('cbExtents',ULONG),
411        ('MshlFlags',ULONG),
412        ('Count',ULONG),
413        ('Frozen',ULONG),
414        ('PropMarshalHeader',PROPMARSHALHEADER_ARRAY),
415    )
416
417# 2.2.21.3 ErrorInfoString
418class ErrorInfoString(NDRSTRUCT):
419    structure = (
420        ('dwMax',ULONG),
421        ('dwOffSet',ULONG),
422        ('dwActual',IID),
423        ('Name',WSTR),
424    )
425
426# 2.2.21.2 Custom-Marshaled Error Information Format
427class ORPC_ERROR_INFORMATION(NDRSTRUCT):
428    structure = (
429        ('dwVersion',ULONG),
430        ('dwHelpContext',ULONG),
431        ('iid',IID),
432        ('dwSourceSignature',ULONG),
433        ('Source',ErrorInfoString),
434        ('dwDescriptionSignature',ULONG),
435        ('Description',ErrorInfoString),
436        ('dwHelpFileSignature',ULONG),
437        ('HelpFile',ErrorInfoString),
438    )
439
440# 2.2.21.5 EntryHeader
441class EntryHeader(NDRSTRUCT):
442    structure = (
443        ('Signature',ULONG),
444        ('cbEHBuffer',ULONG),
445        ('cbSize',ULONG),
446        ('reserved',ULONG),
447        ('policyID',GUID),
448    )
449
450class EntryHeader_ARRAY(NDRUniConformantArray):
451    item = EntryHeader
452
453# 2.2.21.4 Context ORPC Extension
454class ORPC_CONTEXT(NDRSTRUCT):
455    structure = (
456        ('SignatureVersion',ULONG),
457        ('Version',ULONG),
458        ('cPolicies',ULONG),
459        ('cbBuffer',ULONG),
460        ('cbSize',ULONG),
461        ('hr',ULONG),
462        ('hrServer',ULONG),
463        ('reserved',ULONG),
464        ('EntryHeader',EntryHeader_ARRAY),
465        ('PolicyData',':'),
466    )
467    def __init__(self, data = None, isNDR64 = False):
468        NDRSTRUCT.__init__(self, data, isNDR64)
469        if data is None:
470            self['SignatureVersion'] = 0x414E554B
471
472# 2.2.22.1 CustomHeader
473class CLSID_ARRAY(NDRUniConformantArray):
474    item = CLSID
475
476class PCLSID_ARRAY(NDRPOINTER):
477    referent = (
478        ('Data', CLSID_ARRAY),
479    )
480
481class DWORD_ARRAY(NDRUniConformantArray):
482    item = DWORD
483
484class PDWORD_ARRAY(NDRPOINTER):
485    referent = (
486        ('Data', DWORD_ARRAY),
487    )
488
489class CustomHeader(TypeSerialization1):
490    structure = (
491        ('totalSize',DWORD),
492        ('headerSize',DWORD),
493        ('dwReserved',DWORD),
494        ('destCtx',DWORD),
495        ('cIfs',DWORD),
496        ('classInfoClsid',CLSID),
497        ('pclsid',PCLSID_ARRAY),
498        ('pSizes',PDWORD_ARRAY),
499        ('pdwReserved',LPLONG),
500        #('pdwReserved',LONG),
501    )
502    def getData(self, soFar = 0):
503        self['headerSize'] = len(TypeSerialization1.getData(self, soFar)) + len(
504            TypeSerialization1.getDataReferents(self, soFar))
505        self['cIfs'] = len(self['pclsid'])
506        return TypeSerialization1.getData(self, soFar)
507
508# 2.2.22 Activation Properties BLOB
509class ACTIVATION_BLOB(NDRTLSTRUCT):
510    structure = (
511        ('dwSize',ULONG),
512        ('dwReserved',ULONG),
513        ('CustomHeader',CustomHeader),
514        ('Property',UNKNOWNDATA),
515    )
516    def getData(self, soFar = 0):
517        self['dwSize'] = len(self['CustomHeader'].getData(soFar)) + len(
518            self['CustomHeader'].getDataReferents(soFar)) + len(self['Property'])
519        self['CustomHeader']['totalSize'] = self['dwSize']
520        return NDRTLSTRUCT.getData(self)
521
522# 2.2.22.2.1 InstantiationInfoData
523class IID_ARRAY(NDRUniConformantArray):
524    item = IID
525
526class PIID_ARRAY(NDRPOINTER):
527    referent = (
528        ('Data', IID_ARRAY),
529    )
530
531class InstantiationInfoData(TypeSerialization1):
532    structure = (
533        ('classId',CLSID),
534        ('classCtx',DWORD),
535        ('actvflags',DWORD),
536        ('fIsSurrogate',LONG),
537        ('cIID',DWORD),
538        ('instFlag',DWORD),
539        ('pIID',PIID_ARRAY),
540        ('thisSize',DWORD),
541        ('clientCOMVersion',COMVERSION),
542    )
543
544# 2.2.22.2.2 SpecialPropertiesData
545class SpecialPropertiesData(TypeSerialization1):
546    structure = (
547        ('dwSessionId',ULONG),
548        ('fRemoteThisSessionId',LONG),
549        ('fClientImpersonating',LONG),
550        ('fPartitionIDPresent',LONG),
551        ('dwDefaultAuthnLvl',DWORD),
552        ('guidPartition',GUID),
553        ('dwPRTFlags',DWORD),
554        ('dwOrigClsctx',DWORD),
555        ('dwFlags',DWORD),
556        ('Reserved0',DWORD),
557        ('Reserved0',DWORD),
558        ('Reserved', '32s=""'),
559        #('Reserved1',DWORD),
560        #('Reserved2',ULONGLONG),
561        #('Reserved3_1',DWORD),
562        #('Reserved3_2',DWORD),
563        #('Reserved3_3',DWORD),
564        #('Reserved3_4',DWORD),
565        #('Reserved3_5',DWORD),
566    )
567
568# 2.2.22.2.3 InstanceInfoData
569class InstanceInfoData(TypeSerialization1):
570    structure = (
571        ('fileName',LPWSTR),
572        ('mode',DWORD),
573        ('ifdROT',PMInterfacePointer),
574        ('ifdStg',PMInterfacePointer),
575    )
576
577# 2.2.22.2.4.1 customREMOTE_REQUEST_SCM_INFO
578class customREMOTE_REQUEST_SCM_INFO(NDRSTRUCT):
579    structure = (
580        ('ClientImpLevel',DWORD),
581        ('cRequestedProtseqs',USHORT),
582        ('pRequestedProtseqs',PUSHORT_ARRAY),
583    )
584
585class PcustomREMOTE_REQUEST_SCM_INFO(NDRPOINTER):
586    referent = (
587        ('Data', customREMOTE_REQUEST_SCM_INFO),
588    )
589
590# 2.2.22.2.4 ScmRequestInfoData
591class ScmRequestInfoData(TypeSerialization1):
592    structure = (
593        ('pdwReserved',LPLONG),
594        ('remoteRequest',PcustomREMOTE_REQUEST_SCM_INFO),
595    )
596
597# 2.2.22.2.5 ActivationContextInfoData
598class ActivationContextInfoData(TypeSerialization1):
599    structure = (
600        ('clientOK',LONG),
601        ('bReserved1',LONG),
602        ('dwReserved1',DWORD),
603        ('dwReserved2',DWORD),
604        ('pIFDClientCtx',PMInterfacePointer),
605        ('pIFDPrototypeCtx',PMInterfacePointer),
606    )
607
608# 2.2.22.2.6 LocationInfoData
609class LocationInfoData(TypeSerialization1):
610    structure = (
611        ('machineName',LPWSTR),
612        ('processId',DWORD),
613        ('apartmentId',DWORD),
614        ('contextId',DWORD),
615    )
616
617# 2.2.22.2.7.1 COSERVERINFO
618class COSERVERINFO(NDRSTRUCT):
619    structure = (
620        ('dwReserved1',DWORD),
621        ('pwszName',LPWSTR),
622        ('pdwReserved',LPLONG),
623        ('dwReserved2',DWORD),
624    )
625
626class PCOSERVERINFO(NDRPOINTER):
627    referent = (
628        ('Data', COSERVERINFO),
629    )
630
631# 2.2.22.2.7 SecurityInfoData
632class SecurityInfoData(TypeSerialization1):
633    structure = (
634        ('dwAuthnFlags',DWORD),
635        ('pServerInfo',PCOSERVERINFO),
636        ('pdwReserved',LPLONG),
637    )
638
639# 2.2.22.2.8.1 customREMOTE_REPLY_SCM_INFO
640class customREMOTE_REPLY_SCM_INFO(NDRSTRUCT):
641    structure = (
642        ('Oxid',OXID),
643        ('pdsaOxidBindings',PDUALSTRINGARRAY),
644        ('ipidRemUnknown',IPID),
645        ('authnHint',DWORD),
646        ('serverVersion',COMVERSION),
647    )
648
649class PcustomREMOTE_REPLY_SCM_INFO(NDRPOINTER):
650    referent = (
651        ('Data', customREMOTE_REPLY_SCM_INFO),
652    )
653
654# 2.2.22.2.8 ScmReplyInfoData
655class ScmReplyInfoData(TypeSerialization1):
656    structure = (
657        ('pdwReserved',DWORD),
658        ('remoteReply',PcustomREMOTE_REPLY_SCM_INFO),
659    )
660
661# 2.2.22.2.9 PropsOutInfo
662class HRESULT_ARRAY(NDRUniConformantArray):
663    item = HRESULT
664
665class PHRESULT_ARRAY(NDRPOINTER):
666    referent = (
667        ('Data', HRESULT_ARRAY),
668    )
669
670class MInterfacePointer_ARRAY(NDRUniConformantArray):
671    item = MInterfacePointer
672
673class PMInterfacePointer_ARRAY(NDRUniConformantArray):
674    item = PMInterfacePointer
675
676class PPMInterfacePointer_ARRAY(NDRPOINTER):
677    referent = (
678        ('Data', PMInterfacePointer_ARRAY),
679    )
680
681class PropsOutInfo(TypeSerialization1):
682    structure = (
683        ('cIfs',DWORD),
684        ('piid',PIID_ARRAY),
685        ('phresults',PHRESULT_ARRAY),
686        ('ppIntfData',PPMInterfacePointer_ARRAY),
687    )
688
689# 2.2.23 REMINTERFACEREF
690class REMINTERFACEREF(NDRSTRUCT):
691    structure = (
692        ('ipid',IPID),
693        ('cPublicRefs',LONG),
694        ('cPrivateRefs',LONG),
695    )
696
697class REMINTERFACEREF_ARRAY(NDRUniConformantArray):
698    item = REMINTERFACEREF
699
700# 2.2.24 REMQIRESULT
701class REMQIRESULT(NDRSTRUCT):
702    structure = (
703        ('hResult',HRESULT),
704        ('std',STDOBJREF),
705    )
706
707# 2.2.25 PREMQIRESULT
708class PREMQIRESULT(NDRPOINTER):
709    referent = (
710        ('Data', REMQIRESULT),
711    )
712
713# 2.2.26 REFIPID
714REFIPID = GUID
715
716################################################################################
717# RPC CALLS
718################################################################################
719class DCOMCALL(NDRCALL):
720    commonHdr = (
721       ('ORPCthis', ORPCTHIS),
722    )
723
724class DCOMANSWER(NDRCALL):
725    commonHdr = (
726       ('ORPCthat', ORPCTHAT),
727    )
728
729# 3.1.2.5.1.1 IObjectExporter::ResolveOxid (Opnum 0)
730class ResolveOxid(NDRCALL):
731    opnum = 0
732    structure = (
733       ('pOxid', OXID),
734       ('cRequestedProtseqs', USHORT),
735       ('arRequestedProtseqs', USHORT_ARRAY),
736    )
737
738class ResolveOxidResponse(NDRCALL):
739    structure = (
740       ('ppdsaOxidBindings', PDUALSTRINGARRAY),
741       ('pipidRemUnknown', IPID),
742       ('pAuthnHint', DWORD),
743       ('ErrorCode', error_status_t),
744    )
745
746# 3.1.2.5.1.2 IObjectExporter::SimplePing (Opnum 1)
747class SimplePing(NDRCALL):
748    opnum = 1
749    structure = (
750       ('pSetId', SETID),
751    )
752
753class SimplePingResponse(NDRCALL):
754    structure = (
755       ('ErrorCode', error_status_t),
756    )
757
758# 3.1.2.5.1.3 IObjectExporter::ComplexPing (Opnum 2)
759class ComplexPing(NDRCALL):
760    opnum = 2
761    structure = (
762       ('pSetId', SETID),
763       ('SequenceNum', USHORT),
764       ('cAddToSet', USHORT),
765       ('cDelFromSet', USHORT),
766       ('AddToSet', POID_ARRAY),
767       ('DelFromSet', POID_ARRAY),
768    )
769
770class ComplexPingResponse(NDRCALL):
771    structure = (
772       ('pSetId', SETID),
773       ('pPingBackoffFactor', USHORT),
774       ('ErrorCode', error_status_t),
775    )
776
777# 3.1.2.5.1.4 IObjectExporter::ServerAlive (Opnum 3)
778class ServerAlive(NDRCALL):
779    opnum = 3
780    structure = (
781    )
782
783class ServerAliveResponse(NDRCALL):
784    structure = (
785       ('ErrorCode', error_status_t),
786    )
787
788# 3.1.2.5.1.5 IObjectExporter::ResolveOxid2 (Opnum 4)
789class ResolveOxid2(NDRCALL):
790    opnum = 4
791    structure = (
792       ('pOxid', OXID),
793       ('cRequestedProtseqs', USHORT),
794       ('arRequestedProtseqs', USHORT_ARRAY),
795    )
796
797class ResolveOxid2Response(NDRCALL):
798    structure = (
799       ('ppdsaOxidBindings', PDUALSTRINGARRAY),
800       ('pipidRemUnknown', IPID),
801       ('pAuthnHint', DWORD),
802       ('pComVersion', COMVERSION),
803       ('ErrorCode', error_status_t),
804    )
805
806# 3.1.2.5.1.6 IObjectExporter::ServerAlive2 (Opnum 5)
807class ServerAlive2(NDRCALL):
808    opnum = 5
809    structure = (
810    )
811
812class ServerAlive2Response(NDRCALL):
813    structure = (
814       ('pComVersion', COMVERSION),
815       ('ppdsaOrBindings', PDUALSTRINGARRAY),
816       ('pReserved', LPLONG),
817       ('ErrorCode', error_status_t),
818    )
819
820# 3.1.2.5.2.3.1 IActivation:: RemoteActivation (Opnum 0)
821class RemoteActivation(NDRCALL):
822    opnum = 0
823    structure = (
824       ('ORPCthis', ORPCTHIS),
825       ('Clsid', GUID),
826       ('pwszObjectName', LPWSTR),
827       ('pObjectStorage', PMInterfacePointer),
828       ('ClientImpLevel', DWORD),
829       ('Mode', DWORD),
830       ('Interfaces', DWORD),
831       ('pIIDs', PIID_ARRAY),
832       ('cRequestedProtseqs', USHORT),
833       ('aRequestedProtseqs', USHORT_ARRAY),
834    )
835
836class RemoteActivationResponse(NDRCALL):
837    structure = (
838       ('ORPCthat', ORPCTHAT),
839       ('pOxid', OXID),
840       ('ppdsaOxidBindings', PDUALSTRINGARRAY),
841       ('pipidRemUnknown', IPID),
842       ('pAuthnHint', DWORD),
843       ('pServerVersion', COMVERSION),
844       ('phr', HRESULT),
845       ('ppInterfaceData', PMInterfacePointer_ARRAY),
846       ('pResults', HRESULT_ARRAY),
847       ('ErrorCode', error_status_t),
848    )
849
850# 3.1.2.5.2.3.2 IRemoteSCMActivator:: RemoteGetClassObject (Opnum 3)
851class RemoteGetClassObject(NDRCALL):
852    opnum = 3
853    structure = (
854       ('ORPCthis', ORPCTHIS),
855       ('pActProperties', PMInterfacePointer),
856    )
857
858class RemoteGetClassObjectResponse(NDRCALL):
859    structure = (
860       ('ORPCthat', ORPCTHAT),
861       ('ppActProperties', PMInterfacePointer),
862       ('ErrorCode', error_status_t),
863    )
864
865# 3.1.2.5.2.3.3 IRemoteSCMActivator::RemoteCreateInstance (Opnum 4)
866class RemoteCreateInstance(NDRCALL):
867    opnum = 4
868    structure = (
869       ('ORPCthis', ORPCTHIS),
870       ('pUnkOuter', PMInterfacePointer),
871       ('pActProperties', PMInterfacePointer),
872    )
873
874class RemoteCreateInstanceResponse(NDRCALL):
875    structure = (
876       ('ORPCthat', ORPCTHAT),
877       ('ppActProperties', PMInterfacePointer),
878       ('ErrorCode', error_status_t),
879    )
880
881# 3.1.1.5.6.1.1 IRemUnknown::RemQueryInterface (Opnum 3)
882class RemQueryInterface(DCOMCALL):
883    opnum = 3
884    structure = (
885       ('ripid', REFIPID),
886       ('cRefs', ULONG),
887       ('cIids', USHORT),
888       ('iids', IID_ARRAY),
889    )
890
891class RemQueryInterfaceResponse(DCOMANSWER):
892    structure = (
893       ('ppQIResults', PREMQIRESULT),
894       ('ErrorCode', error_status_t),
895    )
896
897# 3.1.1.5.6.1.2 IRemUnknown::RemAddRef (Opnum 4 )
898class RemAddRef(DCOMCALL):
899    opnum = 4
900    structure = (
901       ('cInterfaceRefs', USHORT),
902       ('InterfaceRefs', REMINTERFACEREF_ARRAY),
903    )
904
905class RemAddRefResponse(DCOMANSWER):
906    structure = (
907       ('pResults', DWORD_ARRAY),
908       ('ErrorCode', error_status_t),
909    )
910
911# 3.1.1.5.6.1.3 IRemUnknown::RemRelease (Opnum 5)
912class RemRelease(DCOMCALL):
913    opnum = 5
914    structure = (
915       ('cInterfaceRefs', USHORT),
916       ('InterfaceRefs', REMINTERFACEREF_ARRAY),
917    )
918
919class RemReleaseResponse(DCOMANSWER):
920    structure = (
921       ('ErrorCode', error_status_t),
922    )
923
924################################################################################
925# OPNUMs and their corresponding structures
926################################################################################
927OPNUMS = {
928}
929
930################################################################################
931# HELPER FUNCTIONS
932################################################################################
933class DCOMConnection:
934    """
935    This class represents a DCOM Connection. It is in charge of establishing the
936    DCE connection against the portmap, and then launch a thread that will be
937    pinging the objects created against the target.
938    In theory, there should be a single instance of this class for every target
939    """
940    PINGTIMER = None
941    OID_ADD = {}
942    OID_DEL = {}
943    OID_SET = {}
944    PORTMAPS = {}
945
946    def __init__(self, target, username='', password='', domain='', lmhash='', nthash='', aesKey='', TGT=None, TGS=None,
947                 authLevel=RPC_C_AUTHN_LEVEL_PKT_PRIVACY, oxidResolver=False, doKerberos=False, kdcHost=None):
948        self.__target = target
949        self.__userName = username
950        self.__password = password
951        self.__domain = domain
952        self.__lmhash = lmhash
953        self.__nthash = nthash
954        self.__aesKey = aesKey
955        self.__TGT    = TGT
956        self.__TGS    = TGS
957        self.__authLevel = authLevel
958        self.__portmap = None
959        self.__oxidResolver = oxidResolver
960        self.__doKerberos = doKerberos
961        self.__kdcHost = kdcHost
962        self.initConnection()
963
964    @classmethod
965    def addOid(cls, target, oid):
966        if DCOMConnection.OID_ADD.has_key(target) is False:
967            DCOMConnection.OID_ADD[target] = set()
968        DCOMConnection.OID_ADD[target].add(oid)
969        if DCOMConnection.OID_SET.has_key(target) is False:
970            DCOMConnection.OID_SET[target] = {}
971            DCOMConnection.OID_SET[target]['oids'] = set()
972            DCOMConnection.OID_SET[target]['setid'] = 0
973
974    @classmethod
975    def delOid(cls, target, oid):
976        if DCOMConnection.OID_DEL.has_key(target) is False:
977            DCOMConnection.OID_DEL[target] = set()
978        DCOMConnection.OID_DEL[target].add(oid)
979        if DCOMConnection.OID_SET.has_key(target) is False:
980            DCOMConnection.OID_SET[target] = {}
981            DCOMConnection.OID_SET[target]['oids'] = set()
982            DCOMConnection.OID_SET[target]['setid'] = 0
983
984    @classmethod
985    def pingServer(cls):
986        # Here we need to go through all the objects opened and ping them.
987        # ToDo: locking for avoiding race conditions
988        #print DCOMConnection.PORTMAPS
989        #print DCOMConnection.OID_SET
990        try:
991            for target in DCOMConnection.OID_SET:
992                addedOids = set()
993                deletedOids = set()
994                if DCOMConnection.OID_ADD.has_key(target):
995                    addedOids = DCOMConnection.OID_ADD[target]
996                    del(DCOMConnection.OID_ADD[target])
997
998                if DCOMConnection.OID_DEL.has_key(target):
999                    deletedOids = DCOMConnection.OID_DEL[target]
1000                    del(DCOMConnection.OID_DEL[target])
1001
1002                objExporter = IObjectExporter(DCOMConnection.PORTMAPS[target])
1003
1004                if len(addedOids) > 0 or len(deletedOids) > 0:
1005                    if DCOMConnection.OID_SET[target].has_key('setid'):
1006                        setId = DCOMConnection.OID_SET[target]['setid']
1007                    else:
1008                        setId = 0
1009                    resp = objExporter.ComplexPing(setId, 0, addedOids, deletedOids)
1010                    DCOMConnection.OID_SET[target]['oids'] -= deletedOids
1011                    DCOMConnection.OID_SET[target]['oids'] |= addedOids
1012                    DCOMConnection.OID_SET[target]['setid'] = resp['pSetId']
1013                else:
1014                    objExporter.SimplePing(DCOMConnection.OID_SET[target]['setid'])
1015        except Exception, e:
1016            # There might be exceptions when sending packets
1017            # We should try to continue tho.
1018            LOG.error(str(e))
1019            pass
1020
1021        DCOMConnection.PINGTIMER = Timer(120,DCOMConnection.pingServer)
1022        try:
1023            DCOMConnection.PINGTIMER.start()
1024        except Exception, e:
1025            if str(e).find('threads can only be started once') < 0:
1026                raise e
1027
1028    def initTimer(self):
1029        if self.__oxidResolver is True:
1030            if DCOMConnection.PINGTIMER is None:
1031                DCOMConnection.PINGTIMER = Timer(120, DCOMConnection.pingServer)
1032            try:
1033                DCOMConnection.PINGTIMER.start()
1034            except Exception, e:
1035                if str(e).find('threads can only be started once') < 0:
1036                    raise e
1037
1038    def initConnection(self):
1039        stringBinding = r'ncacn_ip_tcp:%s' % self.__target
1040        rpctransport = transport.DCERPCTransportFactory(stringBinding)
1041
1042        if hasattr(rpctransport, 'set_credentials') and len(self.__userName) >=0:
1043            # This method exists only for selected protocol sequences.
1044            rpctransport.set_credentials(self.__userName, self.__password, self.__domain, self.__lmhash, self.__nthash,
1045                                         self.__aesKey, self.__TGT, self.__TGS)
1046            rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost)
1047        self.__portmap = rpctransport.get_dce_rpc()
1048        self.__portmap.set_auth_level(self.__authLevel)
1049        if self.__doKerberos is True:
1050            self.__portmap.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)
1051        self.__portmap.connect()
1052        DCOMConnection.PORTMAPS[self.__target] = self.__portmap
1053
1054    def CoCreateInstanceEx(self, clsid, iid):
1055        scm = IRemoteSCMActivator(self.__portmap)
1056        iInterface = scm.RemoteCreateInstance(clsid, iid)
1057        self.initTimer()
1058        return iInterface
1059
1060    def get_dce_rpc(self):
1061        return DCOMConnection.PORTMAPS[self.__target]
1062
1063    def disconnect(self):
1064        if DCOMConnection.PINGTIMER is not None:
1065            del(DCOMConnection.PORTMAPS[self.__target])
1066            del(DCOMConnection.OID_SET[self.__target])
1067            if len(DCOMConnection.PORTMAPS) == 0:
1068                # This means there are no more clients using this object, kill it
1069                DCOMConnection.PINGTIMER.cancel()
1070                DCOMConnection.PINGTIMER.join()
1071                DCOMConnection.PINGTIMER = None
1072        if INTERFACE.CONNECTIONS.has_key(self.__target):
1073            del(INTERFACE.CONNECTIONS[self.__target][currentThread().getName()])
1074        self.__portmap.disconnect()
1075        #print INTERFACE.CONNECTIONS
1076
1077class CLASS_INSTANCE:
1078    def __init__(self, ORPCthis, stringBinding):
1079        self.__stringBindings = stringBinding
1080        self.__ORPCthis = ORPCthis
1081        self.__authType = RPC_C_AUTHN_WINNT
1082        self.__authLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY
1083    def get_ORPCthis(self):
1084        return self.__ORPCthis
1085    def get_string_bindings(self):
1086        return self.__stringBindings
1087    def get_auth_level(self):
1088        if RPC_C_AUTHN_LEVEL_NONE < self.__authLevel < RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
1089            if self.__authType == RPC_C_AUTHN_WINNT:
1090                return RPC_C_AUTHN_LEVEL_PKT_INTEGRITY
1091            else:
1092                return RPC_C_AUTHN_LEVEL_PKT_PRIVACY
1093        return self.__authLevel
1094    def set_auth_level(self, level):
1095        self.__authLevel = level
1096    def get_auth_type(self):
1097        return self.__authType
1098    def set_auth_type(self, authType):
1099        self.__authType = authType
1100
1101
1102class INTERFACE:
1103    # class variable holding the transport connections, organized by target IP
1104    CONNECTIONS = {}
1105
1106    def __init__(self, cinstance=None, objRef=None, ipidRemUnknown=None, iPid=None, oxid=None, oid=None, target=None,
1107                 interfaceInstance=None):
1108        if interfaceInstance is not None:
1109            self.__target = interfaceInstance.get_target()
1110            self.__iPid = interfaceInstance.get_iPid()
1111            self.__oid  = interfaceInstance.get_oid()
1112            self.__oxid = interfaceInstance.get_oxid()
1113            self.__cinstance = interfaceInstance.get_cinstance()
1114            self.__objRef = interfaceInstance.get_objRef()
1115            self.__ipidRemUnknown = interfaceInstance.get_ipidRemUnknown()
1116        else:
1117            if target is None:
1118                raise Exception('No target')
1119            self.__target = target
1120            self.__iPid = iPid
1121            self.__oid  = oid
1122            self.__oxid = oxid
1123            self.__cinstance = cinstance
1124            self.__objRef = objRef
1125            self.__ipidRemUnknown = ipidRemUnknown
1126            # We gotta check if we have a container inside our connection list, if not, create
1127            if INTERFACE.CONNECTIONS.has_key(self.__target) is not True:
1128                INTERFACE.CONNECTIONS[self.__target] = {}
1129                INTERFACE.CONNECTIONS[self.__target][currentThread().getName()] = {}
1130
1131            if objRef is not None:
1132                self.process_interface(objRef)
1133
1134    def process_interface(self, data):
1135        objRefType = OBJREF(data)['flags']
1136        objRef = None
1137        if objRefType == FLAGS_OBJREF_CUSTOM:
1138            objRef = OBJREF_CUSTOM(data)
1139        elif objRefType == FLAGS_OBJREF_HANDLER:
1140            objRef = OBJREF_HANDLER(data)
1141        elif objRefType == FLAGS_OBJREF_STANDARD:
1142            objRef = OBJREF_STANDARD(data)
1143        elif objRefType == FLAGS_OBJREF_EXTENDED:
1144            objRef = OBJREF_EXTENDED(data)
1145        else:
1146            LOG.error("Unknown OBJREF Type! 0x%x" % objRefType)
1147
1148        if objRefType != FLAGS_OBJREF_CUSTOM:
1149            if objRef['std']['flags'] & SORF_NOPING == 0:
1150                DCOMConnection.addOid(self.__target, objRef['std']['oid'])
1151            self.__iPid = objRef['std']['ipid']
1152            self.__oid  = objRef['std']['oid']
1153            self.__oxid = objRef['std']['oxid']
1154            if self.__oxid is None:
1155                objRef.dump()
1156                raise Exception('OXID is None')
1157
1158    def get_oxid(self):
1159        return self.__oxid
1160
1161    def set_oxid(self, oxid):
1162        self.__oxid = oxid
1163
1164    def get_oid(self):
1165        return self.__oid
1166
1167    def set_oid(self, oid):
1168        self.__oid = oid
1169
1170    def get_target(self):
1171        return self.__target
1172
1173    def get_iPid(self):
1174        return self.__iPid
1175
1176    def set_iPid(self, iPid):
1177        self.__iPid = iPid
1178
1179    def get_objRef(self):
1180        return self.__objRef
1181
1182    def set_objRef(self, objRef):
1183        self.__objRef = objRef
1184
1185    def get_ipidRemUnknown(self):
1186        return self.__ipidRemUnknown
1187
1188    def get_dce_rpc(self):
1189        return INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce']
1190
1191    def get_cinstance(self):
1192        return self.__cinstance
1193
1194    def set_cinstance(self, cinstance):
1195        self.__cinstance = cinstance
1196
1197    def is_fdqn(self):
1198        # I will assume the following
1199        # If I can't socket.inet_aton() then it's not an IPv4 address
1200        # Same for ipv6, but since socket.inet_pton is not available in Windows, I'll look for ':'. There can't be
1201        # an FQDN with ':'
1202        # Is it isn't both, then it is a FDQN
1203        try:
1204            socket.inet_aton(self.__target)
1205        except:
1206            # Not an IPv4
1207            try:
1208                self.__target.index(':')
1209            except:
1210                # Not an IPv6, it's a FDQN
1211                return True
1212        return False
1213
1214
1215    def connect(self, iid = None):
1216        if INTERFACE.CONNECTIONS.has_key(self.__target) is True:
1217            if INTERFACE.CONNECTIONS[self.__target].has_key(currentThread().getName()) and \
1218                            INTERFACE.CONNECTIONS[self.__target][currentThread().getName()].has_key(self.__oxid) is True:
1219                dce = INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce']
1220                currentBinding = INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['currentBinding']
1221                if currentBinding == iid:
1222                    # We don't need to alter_ctx
1223                    pass
1224                else:
1225                    newDce = dce.alter_ctx(iid)
1226                    INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce'] = newDce
1227                    INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['currentBinding'] = iid
1228            else:
1229                stringBindings = self.get_cinstance().get_string_bindings()
1230                # No OXID present, we should create a new connection and store it
1231                stringBinding = None
1232                isTargetFDQN = self.is_fdqn()
1233                LOG.debug('Target system is %s and isFDQN is %s' % (self.get_target(), isTargetFDQN))
1234                for strBinding in stringBindings:
1235                    # Here, depending on the get_target() value several things can happen
1236                    # 1) it's an IPv4 address
1237                    # 2) it's an IPv6 address
1238                    # 3) it's a NetBios Name
1239                    # we should handle all this cases accordingly
1240                    # Does this match exactly what get_target() returns?
1241                    LOG.debug('StringBinding: %s' % strBinding['aNetworkAddr'])
1242                    if strBinding['wTowerId'] == 7:
1243                        # If there's port information, let's strip it for now.
1244                        if strBinding['aNetworkAddr'].find('[') >= 0:
1245                            binding, _, bindingPort = strBinding['aNetworkAddr'].partition('[')
1246                            bindingPort = '[' + bindingPort
1247                        else:
1248                            binding = strBinding['aNetworkAddr']
1249                            bindingPort = ''
1250
1251                        if binding.upper().find(self.get_target().upper()) >= 0:
1252                            stringBinding = 'ncacn_ip_tcp:' + strBinding['aNetworkAddr'][:-1]
1253                            break
1254                        # If get_target() is a FQDN, does it match the hostname?
1255                        elif isTargetFDQN and binding.upper().find(self.get_target().upper().partition('.')[0]) >= 0:
1256                            # Here we replace the aNetworkAddr with self.get_target()
1257                            # This is to help resolving the target system name.
1258                            # self.get_target() has been resolved already otherwise we wouldn't be here whereas
1259                            # aNetworkAddr is usually the NetBIOS name and unless you have your DNS resolver
1260                            # with the right suffixes it will probably not resolve right.
1261                            stringBinding = 'ncacn_ip_tcp:%s%s' % (self.get_target(), bindingPort)
1262                            break
1263
1264                LOG.debug('StringBinding chosen: %s' % stringBinding)
1265                if stringBinding is None:
1266                    # Something wen't wrong, let's just report it
1267                    raise Exception('Can\'t find a valid stringBinding to connect')
1268
1269                dcomInterface = transport.DCERPCTransportFactory(stringBinding)
1270                if hasattr(dcomInterface, 'set_credentials'):
1271                    # This method exists only for selected protocol sequences.
1272                    dcomInterface.set_credentials(*DCOMConnection.PORTMAPS[self.__target].get_credentials())
1273                    dcomInterface.set_kerberos(DCOMConnection.PORTMAPS[self.__target].get_rpc_transport().get_kerberos(),
1274                                               DCOMConnection.PORTMAPS[self.__target].get_rpc_transport().get_kdcHost())
1275                dcomInterface.set_connect_timeout(300)
1276                dce = dcomInterface.get_dce_rpc()
1277
1278                if iid is None:
1279                    raise Exception('IID is None')
1280                else:
1281                    dce.set_auth_level(self.__cinstance.get_auth_level())
1282                    dce.set_auth_type(self.__cinstance.get_auth_type())
1283
1284                dce.connect()
1285
1286                if iid is None:
1287                    raise Exception('IID is None')
1288                else:
1289                    dce.bind(iid)
1290
1291                if self.__oxid is None:
1292                    #import traceback
1293                    #traceback.print_stack()
1294                    raise Exception("OXID NONE, something wrong!!!")
1295
1296                INTERFACE.CONNECTIONS[self.__target][currentThread().getName()] = {}
1297                INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid] = {}
1298                INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce'] = dce
1299                INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['currentBinding'] = iid
1300        else:
1301            # No connection created
1302            raise Exception('No connection created')
1303
1304    def request(self, req, iid = None, uuid = None):
1305        req['ORPCthis'] = self.get_cinstance().get_ORPCthis()
1306        req['ORPCthis']['flags'] = 0
1307        self.connect(iid)
1308        dce = self.get_dce_rpc()
1309        try:
1310            resp = dce.request(req, uuid)
1311        except Exception, e:
1312            if str(e).find('RPC_E_DISCONNECTED') >= 0:
1313                msg = str(e) + '\n'
1314                msg += "DCOM keep-alive pinging it might not be working as expected. You can't be idle for more than 14 minutes!\n"
1315                msg += "You should exit the app and start again\n"
1316                raise DCERPCException(msg)
1317            else:
1318                raise
1319        return resp
1320
1321    def disconnect(self):
1322        return INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce'].disconnect()
1323
1324
1325# 3.1.1.5.6.1 IRemUnknown Methods
1326class IRemUnknown(INTERFACE):
1327    def __init__(self, interface):
1328        self._iid = IID_IRemUnknown
1329        #INTERFACE.__init__(self, interface.get_cinstance(), interface.get_objRef(), interface.get_ipidRemUnknown(),
1330        #                   interface.get_iPid(), target=interface.get_target())
1331        INTERFACE.__init__(self, interfaceInstance=interface)
1332        self.set_oxid(interface.get_oxid())
1333
1334    def RemQueryInterface(self, cRefs, iids):
1335        # For now, it only supports a single IID
1336        request = RemQueryInterface()
1337        request['ORPCthis'] = self.get_cinstance().get_ORPCthis()
1338        request['ORPCthis']['flags'] = 0
1339        request['ripid'] = self.get_iPid()
1340        request['cRefs'] = cRefs
1341        request['cIids'] = len(iids)
1342        for iid in iids:
1343            _iid = IID()
1344            _iid['Data'] = iid
1345            request['iids'].append(_iid)
1346        resp = self.request(request, IID_IRemUnknown, self.get_ipidRemUnknown())
1347        #resp.dump()
1348
1349        return IRemUnknown2(
1350            INTERFACE(self.get_cinstance(), None, self.get_ipidRemUnknown(), resp['ppQIResults']['std']['ipid'],
1351                      oxid=resp['ppQIResults']['std']['oxid'], oid=resp['ppQIResults']['std']['oxid'],
1352                      target=self.get_target()))
1353
1354    def RemAddRef(self):
1355        request = RemAddRef()
1356        request['ORPCthis'] = self.get_cinstance().get_ORPCthis()
1357        request['ORPCthis']['flags'] = 0
1358        request['cInterfaceRefs'] = 1
1359        element = REMINTERFACEREF()
1360        element['ipid'] = self.get_iPid()
1361        element['cPublicRefs'] = 1
1362        request['InterfaceRefs'].append(element)
1363        resp = self.request(request, IID_IRemUnknown, self.get_ipidRemUnknown())
1364        return resp
1365
1366    def RemRelease(self):
1367        request = RemRelease()
1368        request['ORPCthis'] = self.get_cinstance().get_ORPCthis()
1369        request['ORPCthis']['flags'] = 0
1370        request['cInterfaceRefs'] = 1
1371        element = REMINTERFACEREF()
1372        element['ipid'] = self.get_iPid()
1373        element['cPublicRefs'] = 1
1374        request['InterfaceRefs'].append(element)
1375        resp = self.request(request, IID_IRemUnknown, self.get_ipidRemUnknown())
1376        DCOMConnection.delOid(self.get_target(), self.get_oid())
1377        return resp
1378
1379# 3.1.1.5.7 IRemUnknown2 Interface
1380class IRemUnknown2(IRemUnknown):
1381    def __init__(self, interface):
1382        IRemUnknown.__init__(self, interface)
1383        self._iid = IID_IRemUnknown2
1384
1385# 3.1.2.5.1 IObjectExporter Methods
1386class IObjectExporter:
1387    def __init__(self, dce):
1388        self.__portmap = dce
1389
1390    # 3.1.2.5.1.1 IObjectExporter::ResolveOxid (Opnum 0)
1391    def ResolveOxid(self, pOxid, arRequestedProtseqs):
1392        self.__portmap.connect()
1393        self.__portmap.bind(IID_IObjectExporter)
1394        request = ResolveOxid()
1395        request['pOxid'] = pOxid
1396        request['cRequestedProtseqs'] = len(arRequestedProtseqs)
1397        for protSeq in arRequestedProtseqs:
1398            request['arRequestedProtseqs'].append(protSeq)
1399        resp = self.__portmap.request(request)
1400        Oxids = ''.join(pack('<H', x) for x in resp['ppdsaOxidBindings']['aStringArray'])
1401        strBindings = Oxids[:resp['ppdsaOxidBindings']['wSecurityOffset']*2]
1402
1403        done = False
1404        stringBindings = list()
1405        while not done:
1406            if strBindings[0] == '\x00' and strBindings[1] == '\x00':
1407                done = True
1408            else:
1409                binding = STRINGBINDING(strBindings)
1410                stringBindings.append(binding)
1411                strBindings = strBindings[len(binding):]
1412
1413        return stringBindings
1414
1415    # 3.1.2.5.1.2 IObjectExporter::SimplePing (Opnum 1)
1416    def SimplePing(self, setId):
1417        self.__portmap.connect()
1418        self.__portmap.bind(IID_IObjectExporter)
1419        request = SimplePing()
1420        request['pSetId'] = setId
1421        resp = self.__portmap.request(request)
1422        return resp
1423
1424    # 3.1.2.5.1.3 IObjectExporter::ComplexPing (Opnum 2)
1425    def ComplexPing(self, setId = 0, sequenceNum = 0, addToSet = [], delFromSet = []):
1426        self.__portmap.connect()
1427        #self.__portmap.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
1428        self.__portmap.bind(IID_IObjectExporter)
1429        request = ComplexPing()
1430        request['pSetId'] = setId
1431        request['SequenceNum'] = setId
1432        request['cAddToSet'] = len(addToSet)
1433        request['cDelFromSet'] = len(delFromSet)
1434        if len(addToSet) > 0:
1435            for oid in addToSet:
1436                oidn = OID()
1437                oidn['Data'] = oid
1438                request['AddToSet'].append(oidn)
1439        else:
1440            request['AddToSet'] = NULL
1441
1442        if len(delFromSet) > 0:
1443            for oid in delFromSet:
1444                oidn = OID()
1445                oidn['Data'] = oid
1446                request['DelFromSet'].append(oidn)
1447        else:
1448            request['DelFromSet'] = NULL
1449        resp = self.__portmap.request(request)
1450        return resp
1451
1452    # 3.1.2.5.1.4 IObjectExporter::ServerAlive (Opnum 3)
1453    def ServerAlive(self):
1454        self.__portmap.connect()
1455        self.__portmap.bind(IID_IObjectExporter)
1456        request = ServerAlive()
1457        resp = self.__portmap.request(request)
1458        return resp
1459
1460    # 3.1.2.5.1.5 IObjectExporter::ResolveOxid2 (Opnum 4)
1461    def ResolveOxid2(self,pOxid, arRequestedProtseqs):
1462        self.__portmap.connect()
1463        self.__portmap.bind(IID_IObjectExporter)
1464        request = ResolveOxid2()
1465        request['pOxid'] = pOxid
1466        request['cRequestedProtseqs'] = len(arRequestedProtseqs)
1467        for protSeq in arRequestedProtseqs:
1468            request['arRequestedProtseqs'].append(protSeq)
1469        resp = self.__portmap.request(request)
1470        Oxids = ''.join(pack('<H', x) for x in resp['ppdsaOxidBindings']['aStringArray'])
1471        strBindings = Oxids[:resp['ppdsaOxidBindings']['wSecurityOffset']*2]
1472
1473        done = False
1474        stringBindings = list()
1475        while not done:
1476            if strBindings[0] == '\x00' and strBindings[1] == '\x00':
1477                done = True
1478            else:
1479                binding = STRINGBINDING(strBindings)
1480                stringBindings.append(binding)
1481                strBindings = strBindings[len(binding):]
1482
1483        return stringBindings
1484
1485    # 3.1.2.5.1.6 IObjectExporter::ServerAlive2 (Opnum 5)
1486    def ServerAlive2(self):
1487        self.__portmap.connect()
1488        self.__portmap.bind(IID_IObjectExporter)
1489        request = ServerAlive2()
1490        resp = self.__portmap.request(request)
1491
1492        Oxids = ''.join(pack('<H', x) for x in resp['ppdsaOrBindings']['aStringArray'])
1493        strBindings = Oxids[:resp['ppdsaOrBindings']['wSecurityOffset']*2]
1494
1495        done = False
1496        stringBindings = list()
1497        while not done:
1498            if strBindings[0] == '\x00' and strBindings[1] == '\x00':
1499                done = True
1500            else:
1501                binding = STRINGBINDING(strBindings)
1502                stringBindings.append(binding)
1503                strBindings = strBindings[len(binding):]
1504
1505        return stringBindings
1506
1507# 3.1.2.5.2.1 IActivation Methods
1508class IActivation:
1509    def __init__(self, dce):
1510        self.__portmap = dce
1511
1512    # 3.1.2.5.2.3.1 IActivation:: RemoteActivation (Opnum 0)
1513    def RemoteActivation(self, clsId, iid):
1514        # Only supports one interface at a time
1515        self.__portmap.bind(IID_IActivation)
1516        ORPCthis = ORPCTHIS()
1517        ORPCthis['cid'] = generate()
1518        ORPCthis['extensions'] = NULL
1519        ORPCthis['flags'] = 1
1520
1521        request = RemoteActivation()
1522        request['Clsid'] = clsId
1523        request['pwszObjectName'] = NULL
1524        request['pObjectStorage'] = NULL
1525        request['ClientImpLevel'] = 2
1526        request['Mode'] = 0
1527        request['Interfaces'] = 1
1528
1529        _iid = IID()
1530        _iid['Data'] = iid
1531
1532        request['pIIDs'].append(_iid)
1533        request['cRequestedProtseqs'] = 1
1534        request['aRequestedProtseqs'].append(7)
1535
1536        resp = self.__portmap.request(request)
1537
1538        # Now let's parse the answer and build an Interface instance
1539
1540        ipidRemUnknown = resp['pipidRemUnknown']
1541
1542        Oxids = ''.join(pack('<H', x) for x in resp['ppdsaOxidBindings']['aStringArray'])
1543        strBindings = Oxids[:resp['ppdsaOxidBindings']['wSecurityOffset']*2]
1544        securityBindings = Oxids[resp['ppdsaOxidBindings']['wSecurityOffset']*2:]
1545
1546        done = False
1547        stringBindings = list()
1548        while not done:
1549            if strBindings[0] == '\x00' and strBindings[1] == '\x00':
1550                done = True
1551            else:
1552                binding = STRINGBINDING(strBindings)
1553                stringBindings.append(binding)
1554                strBindings = strBindings[len(binding):]
1555
1556        done = False
1557        while not done:
1558            if len(securityBindings) < 2:
1559                done = True
1560            elif securityBindings[0] == '\x00' and securityBindings[1] == '\x00':
1561                done = True
1562            else:
1563                secBinding = SECURITYBINDING(securityBindings)
1564                securityBindings = securityBindings[len(secBinding):]
1565
1566        classInstance = CLASS_INSTANCE(ORPCthis, stringBindings)
1567        return IRemUnknown2(INTERFACE(classInstance, ''.join(resp['ppInterfaceData'][0]['abData']), ipidRemUnknown,
1568                                      target=self.__portmap.get_rpc_transport().getRemoteHost()))
1569
1570
1571# 3.1.2.5.2.2 IRemoteSCMActivator Methods
1572class IRemoteSCMActivator:
1573    def __init__(self, dce):
1574        self.__portmap = dce
1575
1576    def RemoteGetClassObject(self, clsId, iid):
1577        #  iid should be IID_IClassFactory
1578        self.__portmap.bind(IID_IRemoteSCMActivator)
1579        ORPCthis = ORPCTHIS()
1580        ORPCthis['cid'] = generate()
1581        ORPCthis['extensions'] = NULL
1582        ORPCthis['flags'] = 1
1583
1584        request = RemoteGetClassObject()
1585        request['ORPCthis'] = ORPCthis
1586        activationBLOB = ACTIVATION_BLOB()
1587        activationBLOB['CustomHeader']['destCtx'] = 2
1588        activationBLOB['CustomHeader']['pdwReserved'] = NULL
1589        clsid = CLSID()
1590        clsid['Data'] = CLSID_InstantiationInfo
1591        activationBLOB['CustomHeader']['pclsid'].append(clsid)
1592        clsid = CLSID()
1593        clsid['Data'] = CLSID_ActivationContextInfo
1594        activationBLOB['CustomHeader']['pclsid'].append(clsid)
1595        clsid = CLSID()
1596        clsid['Data'] = CLSID_ServerLocationInfo
1597        activationBLOB['CustomHeader']['pclsid'].append(clsid)
1598        clsid = CLSID()
1599        clsid['Data'] = CLSID_ScmRequestInfo
1600        activationBLOB['CustomHeader']['pclsid'].append(clsid)
1601
1602        properties = ''
1603        # InstantiationInfo
1604        instantiationInfo = InstantiationInfoData()
1605        instantiationInfo['classId'] = clsId
1606        instantiationInfo['cIID'] = 1
1607
1608        _iid = IID()
1609        _iid['Data'] = iid
1610
1611        instantiationInfo['pIID'].append(_iid)
1612
1613        dword = DWORD()
1614        marshaled = instantiationInfo.getData()+instantiationInfo.getDataReferents()
1615        pad = (8 - (len(marshaled) % 8)) % 8
1616        dword['Data'] = len(marshaled) + pad
1617        activationBLOB['CustomHeader']['pSizes'].append(dword)
1618        instantiationInfo['thisSize'] = dword['Data']
1619
1620        properties += marshaled + '\xFA'*pad
1621
1622        # ActivationContextInfoData
1623        activationInfo = ActivationContextInfoData()
1624        activationInfo['pIFDClientCtx'] = NULL
1625        activationInfo['pIFDPrototypeCtx'] = NULL
1626
1627        dword = DWORD()
1628        marshaled = activationInfo.getData()+activationInfo.getDataReferents()
1629        pad = (8 - (len(marshaled) % 8)) % 8
1630        dword['Data'] = len(marshaled) + pad
1631        activationBLOB['CustomHeader']['pSizes'].append(dword)
1632
1633        properties += marshaled + '\xFA'*pad
1634
1635        # ServerLocation
1636        locationInfo = LocationInfoData()
1637        locationInfo['machineName'] = NULL
1638
1639        dword = DWORD()
1640        dword['Data'] = len(locationInfo.getData())
1641        activationBLOB['CustomHeader']['pSizes'].append(dword)
1642
1643        properties += locationInfo.getData()+locationInfo.getDataReferents()
1644
1645        # ScmRequestInfo
1646        scmInfo = ScmRequestInfoData()
1647        scmInfo['pdwReserved'] = NULL
1648        #scmInfo['remoteRequest']['ClientImpLevel'] = 2
1649        scmInfo['remoteRequest']['cRequestedProtseqs'] = 1
1650        scmInfo['remoteRequest']['pRequestedProtseqs'].append(7)
1651
1652        dword = DWORD()
1653        marshaled = scmInfo.getData()+scmInfo.getDataReferents()
1654        pad = (8 - (len(marshaled) % 8)) % 8
1655        dword['Data'] = len(marshaled) + pad
1656        activationBLOB['CustomHeader']['pSizes'].append(dword)
1657
1658        properties += marshaled + '\xFA'*pad
1659
1660        activationBLOB['Property'] = properties
1661
1662
1663        objrefcustom = OBJREF_CUSTOM()
1664        objrefcustom['iid'] = IID_IActivationPropertiesIn[:-4]
1665        objrefcustom['clsid'] = CLSID_ActivationPropertiesIn
1666
1667        objrefcustom['pObjectData'] = activationBLOB.getData()
1668        objrefcustom['ObjectReferenceSize'] = len(objrefcustom['pObjectData'])+8
1669
1670        request['pActProperties']['ulCntData'] = len(str(objrefcustom))
1671        request['pActProperties']['abData'] = list(str(objrefcustom))
1672        resp = self.__portmap.request(request)
1673        # Now let's parse the answer and build an Interface instance
1674
1675        objRefType = OBJREF(''.join(resp['ppActProperties']['abData']))['flags']
1676        objRef = None
1677        if objRefType == FLAGS_OBJREF_CUSTOM:
1678            objRef = OBJREF_CUSTOM(''.join(resp['ppActProperties']['abData']))
1679        elif objRefType == FLAGS_OBJREF_HANDLER:
1680            objRef = OBJREF_HANDLER(''.join(resp['ppActProperties']['abData']))
1681        elif objRefType == FLAGS_OBJREF_STANDARD:
1682            objRef = OBJREF_STANDARD(''.join(resp['ppActProperties']['abData']))
1683        elif objRefType == FLAGS_OBJREF_EXTENDED:
1684            objRef = OBJREF_EXTENDED(''.join(resp['ppActProperties']['abData']))
1685        else:
1686            LOG.error("Unknown OBJREF Type! 0x%x" % objRefType)
1687
1688
1689        activationBlob = ACTIVATION_BLOB(objRef['pObjectData'])
1690
1691        propOutput = activationBlob['Property'][:activationBlob['CustomHeader']['pSizes'][0]['Data']]
1692        scmReply = activationBlob['Property'][
1693                   activationBlob['CustomHeader']['pSizes'][0]['Data']:activationBlob['CustomHeader']['pSizes'][0][
1694                                                                           'Data'] +
1695                                                                       activationBlob['CustomHeader']['pSizes'][1][
1696                                                                           'Data']]
1697
1698        scmr = ScmReplyInfoData()
1699        size = scmr.fromString(scmReply)
1700        # Processing the scmReply
1701        scmr.fromStringReferents(scmReply[size:])
1702        ipidRemUnknown = scmr['remoteReply']['ipidRemUnknown']
1703        Oxids = ''.join(pack('<H', x) for x in scmr['remoteReply']['pdsaOxidBindings']['aStringArray'])
1704        strBindings = Oxids[:scmr['remoteReply']['pdsaOxidBindings']['wSecurityOffset']*2]
1705        securityBindings = Oxids[scmr['remoteReply']['pdsaOxidBindings']['wSecurityOffset']*2:]
1706
1707        done = False
1708        stringBindings = list()
1709        while not done:
1710            if strBindings[0] == '\x00' and strBindings[1] == '\x00':
1711                done = True
1712            else:
1713                binding = STRINGBINDING(strBindings)
1714                stringBindings.append(binding)
1715                strBindings = strBindings[len(binding):]
1716
1717        done = False
1718        while not done:
1719            if len(securityBindings) < 2:
1720                done = True
1721            elif securityBindings[0] == '\x00' and securityBindings[1] == '\x00':
1722                done = True
1723            else:
1724                secBinding = SECURITYBINDING(securityBindings)
1725                securityBindings = securityBindings[len(secBinding):]
1726
1727        # Processing the Properties Output
1728        propsOut = PropsOutInfo()
1729        size = propsOut.fromString(propOutput)
1730        propsOut.fromStringReferents(propOutput[size:])
1731
1732        classInstance = CLASS_INSTANCE(ORPCthis, stringBindings)
1733        classInstance.set_auth_level(scmr['remoteReply']['authnHint'])
1734        classInstance.set_auth_type(self.__portmap.get_auth_type())
1735        return IRemUnknown2(INTERFACE(classInstance, ''.join(propsOut['ppIntfData'][0]['abData']), ipidRemUnknown,
1736                                      target=self.__portmap.get_rpc_transport().getRemoteHost()))
1737
1738    def RemoteCreateInstance(self, clsId, iid):
1739        # Only supports one interface at a time
1740        self.__portmap.bind(IID_IRemoteSCMActivator)
1741
1742        ORPCthis = ORPCTHIS()
1743        ORPCthis['cid'] = generate()
1744        ORPCthis['extensions'] = NULL
1745        ORPCthis['flags'] = 1
1746
1747        request = RemoteCreateInstance()
1748        request['ORPCthis'] = ORPCthis
1749        request['pUnkOuter'] = NULL
1750
1751        activationBLOB = ACTIVATION_BLOB()
1752        activationBLOB['CustomHeader']['destCtx'] = 2
1753        activationBLOB['CustomHeader']['pdwReserved'] = NULL
1754        clsid = CLSID()
1755        clsid['Data'] = CLSID_InstantiationInfo
1756        activationBLOB['CustomHeader']['pclsid'].append(clsid)
1757        clsid = CLSID()
1758        clsid['Data'] = CLSID_ActivationContextInfo
1759        activationBLOB['CustomHeader']['pclsid'].append(clsid)
1760        clsid = CLSID()
1761        clsid['Data'] = CLSID_ServerLocationInfo
1762        activationBLOB['CustomHeader']['pclsid'].append(clsid)
1763        clsid = CLSID()
1764        clsid['Data'] = CLSID_ScmRequestInfo
1765        activationBLOB['CustomHeader']['pclsid'].append(clsid)
1766
1767        properties = ''
1768        # InstantiationInfo
1769        instantiationInfo = InstantiationInfoData()
1770        instantiationInfo['classId'] = clsId
1771        instantiationInfo['cIID'] = 1
1772
1773        _iid = IID()
1774        _iid['Data'] = iid
1775
1776        instantiationInfo['pIID'].append(_iid)
1777
1778        dword = DWORD()
1779        marshaled = instantiationInfo.getData()+instantiationInfo.getDataReferents()
1780        pad = (8 - (len(marshaled) % 8)) % 8
1781        dword['Data'] = len(marshaled) + pad
1782        activationBLOB['CustomHeader']['pSizes'].append(dword)
1783        instantiationInfo['thisSize'] = dword['Data']
1784
1785        properties += marshaled + '\xFA'*pad
1786
1787        # ActivationContextInfoData
1788        activationInfo = ActivationContextInfoData()
1789        activationInfo['pIFDClientCtx'] = NULL
1790        activationInfo['pIFDPrototypeCtx'] = NULL
1791
1792        dword = DWORD()
1793        marshaled = activationInfo.getData()+activationInfo.getDataReferents()
1794        pad = (8 - (len(marshaled) % 8)) % 8
1795        dword['Data'] = len(marshaled) + pad
1796        activationBLOB['CustomHeader']['pSizes'].append(dword)
1797
1798        properties += marshaled + '\xFA'*pad
1799
1800        # ServerLocation
1801        locationInfo = LocationInfoData()
1802        locationInfo['machineName'] = NULL
1803
1804        dword = DWORD()
1805        dword['Data'] = len(locationInfo.getData())
1806        activationBLOB['CustomHeader']['pSizes'].append(dword)
1807
1808        properties += locationInfo.getData()+locationInfo.getDataReferents()
1809
1810        # ScmRequestInfo
1811        scmInfo = ScmRequestInfoData()
1812        scmInfo['pdwReserved'] = NULL
1813        #scmInfo['remoteRequest']['ClientImpLevel'] = 2
1814        scmInfo['remoteRequest']['cRequestedProtseqs'] = 1
1815        scmInfo['remoteRequest']['pRequestedProtseqs'].append(7)
1816
1817        dword = DWORD()
1818        marshaled = scmInfo.getData()+scmInfo.getDataReferents()
1819        pad = (8 - (len(marshaled) % 8)) % 8
1820        dword['Data'] = len(marshaled) + pad
1821        activationBLOB['CustomHeader']['pSizes'].append(dword)
1822
1823        properties += marshaled + '\xFA'*pad
1824
1825        activationBLOB['Property'] = properties
1826
1827
1828        objrefcustom = OBJREF_CUSTOM()
1829        objrefcustom['iid'] = IID_IActivationPropertiesIn[:-4]
1830        objrefcustom['clsid'] = CLSID_ActivationPropertiesIn
1831
1832        objrefcustom['pObjectData'] = activationBLOB.getData()
1833        objrefcustom['ObjectReferenceSize'] = len(objrefcustom['pObjectData'])+8
1834
1835        request['pActProperties']['ulCntData'] = len(str(objrefcustom))
1836        request['pActProperties']['abData'] = list(str(objrefcustom))
1837        resp = self.__portmap.request(request)
1838
1839        # Now let's parse the answer and build an Interface instance
1840
1841        objRefType = OBJREF(''.join(resp['ppActProperties']['abData']))['flags']
1842        objRef = None
1843        if objRefType == FLAGS_OBJREF_CUSTOM:
1844            objRef = OBJREF_CUSTOM(''.join(resp['ppActProperties']['abData']))
1845        elif objRefType == FLAGS_OBJREF_HANDLER:
1846            objRef = OBJREF_HANDLER(''.join(resp['ppActProperties']['abData']))
1847        elif objRefType == FLAGS_OBJREF_STANDARD:
1848            objRef = OBJREF_STANDARD(''.join(resp['ppActProperties']['abData']))
1849        elif objRefType == FLAGS_OBJREF_EXTENDED:
1850            objRef = OBJREF_EXTENDED(''.join(resp['ppActProperties']['abData']))
1851        else:
1852            LOG.error("Unknown OBJREF Type! 0x%x" % objRefType)
1853
1854
1855        activationBlob = ACTIVATION_BLOB(objRef['pObjectData'])
1856
1857        propOutput = activationBlob['Property'][:activationBlob['CustomHeader']['pSizes'][0]['Data']]
1858        scmReply = activationBlob['Property'][
1859                   activationBlob['CustomHeader']['pSizes'][0]['Data']:activationBlob['CustomHeader']['pSizes'][0][
1860                                                                           'Data'] +
1861                                                                       activationBlob['CustomHeader']['pSizes'][1][
1862                                                                           'Data']]
1863
1864        scmr = ScmReplyInfoData()
1865        size = scmr.fromString(scmReply)
1866        # Processing the scmReply
1867        scmr.fromStringReferents(scmReply[size:])
1868        ipidRemUnknown = scmr['remoteReply']['ipidRemUnknown']
1869        Oxids = ''.join(pack('<H', x) for x in scmr['remoteReply']['pdsaOxidBindings']['aStringArray'])
1870        strBindings = Oxids[:scmr['remoteReply']['pdsaOxidBindings']['wSecurityOffset']*2]
1871        securityBindings = Oxids[scmr['remoteReply']['pdsaOxidBindings']['wSecurityOffset']*2:]
1872
1873        done = False
1874        stringBindings = list()
1875        while not done:
1876            if strBindings[0] == '\x00' and strBindings[1] == '\x00':
1877                done = True
1878            else:
1879                binding = STRINGBINDING(strBindings)
1880                stringBindings.append(binding)
1881                strBindings = strBindings[len(binding):]
1882
1883        done = False
1884        while not done:
1885            if len(securityBindings) < 2:
1886                done = True
1887            elif securityBindings[0] == '\x00' and securityBindings[1] == '\x00':
1888                done = True
1889            else:
1890                secBinding = SECURITYBINDING(securityBindings)
1891                securityBindings = securityBindings[len(secBinding):]
1892
1893        # Processing the Properties Output
1894        propsOut = PropsOutInfo()
1895        size = propsOut.fromString(propOutput)
1896        propsOut.fromStringReferents(propOutput[size:])
1897
1898        classInstance = CLASS_INSTANCE(ORPCthis, stringBindings)
1899        classInstance.set_auth_level(scmr['remoteReply']['authnHint'])
1900        classInstance.set_auth_type(self.__portmap.get_auth_type())
1901        return IRemUnknown2(INTERFACE(classInstance, ''.join(propsOut['ppIntfData'][0]['abData']), ipidRemUnknown,
1902                                      target=self.__portmap.get_rpc_transport().getRemoteHost()))
1903