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#   [C706] Remote Management 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#
21from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray, NDRUniConformantVaryingArray
22from impacket.dcerpc.v5.epm import PRPC_IF_ID
23from impacket.dcerpc.v5.dtypes import ULONG, DWORD_ARRAY, ULONGLONG
24from impacket.dcerpc.v5.rpcrt import DCERPCException
25from impacket.uuid import uuidtup_to_bin
26from impacket import nt_errors
27
28MSRPC_UUID_MGMT  = uuidtup_to_bin(('afa8bd80-7d8a-11c9-bef4-08002b102989','1.0'))
29
30class DCERPCSessionError(DCERPCException):
31    def __init__(self, error_string=None, error_code=None, packet=None):
32        DCERPCException.__init__(self, error_string, error_code, packet)
33
34    def __str__( self ):
35        key = self.error_code
36        if nt_errors.ERROR_MESSAGES.has_key(key):
37            error_msg_short = nt_errors.ERROR_MESSAGES[key][0]
38            error_msg_verbose = nt_errors.ERROR_MESSAGES[key][1]
39            return 'MGMT SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)
40        else:
41            return 'MGMT SessionError: unknown error code: 0x%x' % self.error_code
42
43################################################################################
44# CONSTANTS
45################################################################################
46
47class rpc_if_id_p_t_array(NDRUniConformantArray):
48    item = PRPC_IF_ID
49
50class rpc_if_id_vector_t(NDRSTRUCT):
51    structure = (
52        ('count',ULONG),
53        ('if_id',rpc_if_id_p_t_array),
54    )
55    structure64 = (
56        ('count',ULONGLONG),
57        ('if_id',rpc_if_id_p_t_array),
58    )
59
60class rpc_if_id_vector_p_t(NDRPOINTER):
61    referent = (
62        ('Data', rpc_if_id_vector_t),
63    )
64
65error_status = ULONG
66################################################################################
67# STRUCTURES
68################################################################################
69
70################################################################################
71# RPC CALLS
72################################################################################
73class inq_if_ids(NDRCALL):
74    opnum = 0
75    structure = (
76    )
77
78class inq_if_idsResponse(NDRCALL):
79    structure = (
80       ('if_id_vector', rpc_if_id_vector_p_t),
81       ('status', error_status),
82    )
83
84class inq_stats(NDRCALL):
85    opnum = 1
86    structure = (
87       ('count', ULONG),
88    )
89
90class inq_statsResponse(NDRCALL):
91    structure = (
92       ('count', ULONG),
93       ('statistics', DWORD_ARRAY),
94       ('status', error_status),
95    )
96
97class is_server_listening(NDRCALL):
98    opnum = 2
99    structure = (
100    )
101
102class is_server_listeningResponse(NDRCALL):
103    structure = (
104       ('status', error_status),
105    )
106
107class stop_server_listening(NDRCALL):
108    opnum = 3
109    structure = (
110    )
111
112class stop_server_listeningResponse(NDRCALL):
113    structure = (
114       ('status', error_status),
115    )
116
117class inq_princ_name(NDRCALL):
118    opnum = 4
119    structure = (
120       ('authn_proto', ULONG),
121       ('princ_name_size', ULONG),
122    )
123
124class inq_princ_nameResponse(NDRCALL):
125    structure = (
126       ('princ_name', NDRUniConformantVaryingArray),
127       ('status', error_status),
128    )
129
130
131################################################################################
132# OPNUMs and their corresponding structures
133################################################################################
134OPNUMS = {
135 0 : (inq_if_ids, inq_if_idsResponse),
136 1 : (inq_stats, inq_statsResponse),
137 2 : (is_server_listening, is_server_listeningResponse),
138 3 : (stop_server_listening, stop_server_listeningResponse),
139 4 : (inq_princ_name, inq_princ_nameResponse),
140}
141
142################################################################################
143# HELPER FUNCTIONS
144################################################################################
145def hinq_if_ids(dce):
146    request = inq_if_ids()
147    return dce.request(request)
148
149def hinq_stats(dce, count = 4):
150    request = inq_stats()
151    request['count'] = count
152    return dce.request(request)
153
154def his_server_listening(dce):
155    request = is_server_listening()
156    return dce.request(request, checkError=False)
157
158def hstop_server_listening(dce):
159    request = stop_server_listening()
160    return dce.request(request)
161
162def hinq_princ_name(dce, authn_proto=0, princ_name_size=1):
163    request = inq_princ_name()
164    request['authn_proto'] = authn_proto
165    request['princ_name_size'] = princ_name_size
166    return dce.request(request, checkError=False)
167
168
169