1 /**
2 * WinPR: Windows Portable Runtime
3 * Network Data Representation (NDR)
4 *
5 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27
28 #include <winpr/ndr.h>
29
30 #ifndef _WIN32
31
32 #include "ndr_array.h"
33 #include "ndr_context.h"
34 #include "ndr_pointer.h"
35 #include "ndr_simple.h"
36 #include "ndr_string.h"
37 #include "ndr_structure.h"
38 #include "ndr_union.h"
39
40 #include "ndr_private.h"
41
42 #include "../log.h"
43 #define TAG WINPR_TAG("rpc")
44
45 /**
46 * MSRPC NDR Types Technical Overview:
47 * http://dvlabs.tippingpoint.com/blog/2007/11/24/msrpc-ndr-types/
48 */
49
NdrPrintParamAttributes(PARAM_ATTRIBUTES attributes)50 static void NdrPrintParamAttributes(PARAM_ATTRIBUTES attributes)
51 {
52 if (attributes.ServerAllocSize)
53 WLog_INFO(TAG, "ServerAllocSize, ");
54
55 if (attributes.SaveForAsyncFinish)
56 WLog_INFO(TAG, "SaveForAsyncFinish, ");
57
58 if (attributes.IsDontCallFreeInst)
59 WLog_INFO(TAG, "IsDontCallFreeInst, ");
60
61 if (attributes.IsSimpleRef)
62 WLog_INFO(TAG, "IsSimpleRef, ");
63
64 if (attributes.IsByValue)
65 WLog_INFO(TAG, "IsByValue, ");
66
67 if (attributes.IsBasetype)
68 WLog_INFO(TAG, "IsBaseType, ");
69
70 if (attributes.IsReturn)
71 WLog_INFO(TAG, "IsReturn, ");
72
73 if (attributes.IsOut)
74 WLog_INFO(TAG, "IsOut, ");
75
76 if (attributes.IsIn)
77 WLog_INFO(TAG, "IsIn, ");
78
79 if (attributes.IsPipe)
80 WLog_INFO(TAG, "IsPipe, ");
81
82 if (attributes.MustFree)
83 WLog_INFO(TAG, "MustFree, ");
84
85 if (attributes.MustSize)
86 WLog_INFO(TAG, "MustSize, ");
87 }
88
NdrProcessParam(PMIDL_STUB_MESSAGE pStubMsg,NDR_PHASE phase,unsigned char * pMemory,NDR_PARAM * param)89 static void NdrProcessParam(PMIDL_STUB_MESSAGE pStubMsg, NDR_PHASE phase, unsigned char* pMemory,
90 NDR_PARAM* param)
91 {
92 unsigned char type;
93 PFORMAT_STRING pFormat;
94
95 /* Parameter Descriptors: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374362/ */
96
97 if (param->Attributes.IsBasetype)
98 {
99 pFormat = ¶m->Type.FormatChar;
100
101 if (param->Attributes.IsSimpleRef)
102 pMemory = *(unsigned char**)pMemory;
103 }
104 else
105 {
106 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->Type.Offset];
107
108 if (!(param->Attributes.IsByValue))
109 pMemory = *(unsigned char**)pMemory;
110 }
111
112 type = (pFormat[0] & 0x7F);
113
114 if (type > FC_PAD)
115 return;
116
117 if (phase == NDR_PHASE_SIZE)
118 {
119 NDR_TYPE_SIZE_ROUTINE pfnSizeRoutine = pfnSizeRoutines[type];
120
121 if (pfnSizeRoutine)
122 pfnSizeRoutine(pStubMsg, pMemory, pFormat);
123 }
124 else if (phase == NDR_PHASE_MARSHALL)
125 {
126 NDR_TYPE_MARSHALL_ROUTINE pfnMarshallRoutine = pfnMarshallRoutines[type];
127
128 if (pfnMarshallRoutine)
129 pfnMarshallRoutine(pStubMsg, pMemory, *pFormat);
130 }
131 else if (phase == NDR_PHASE_UNMARSHALL)
132 {
133 NDR_TYPE_UNMARSHALL_ROUTINE pfnUnmarshallRoutine = pfnUnmarshallRoutines[type];
134
135 if (pfnUnmarshallRoutine)
136 pfnUnmarshallRoutine(pStubMsg, pMemory, *pFormat);
137 }
138 else if (phase == NDR_PHASE_FREE)
139 {
140 NDR_TYPE_FREE_ROUTINE pfnFreeRoutine = pfnFreeRoutines[type];
141
142 if (pfnFreeRoutine)
143 pfnFreeRoutine(pStubMsg, pMemory, pFormat);
144 }
145 }
146
NdrProcessParams(PMIDL_STUB_MESSAGE pStubMsg,PFORMAT_STRING pFormat,NDR_PHASE phase,void ** fpuArgs,unsigned short numberParams)147 static void NdrProcessParams(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, NDR_PHASE phase,
148 void** fpuArgs, unsigned short numberParams)
149 {
150 unsigned int i;
151 NDR_PARAM* params;
152 PFORMAT_STRING fmt;
153 unsigned char* arg;
154 unsigned char type;
155 params = (NDR_PARAM*)pFormat;
156 WLog_INFO(TAG, "Params = ");
157
158 for (i = 0; i < numberParams; i++)
159 {
160 #ifdef __x86_64__
161 float tmp;
162 #endif
163 arg = pStubMsg->StackTop + params[i].StackOffset;
164 fmt = (PFORMAT_STRING)&pStubMsg->StubDesc->pFormatTypes[params[i].Type.Offset];
165 #ifdef __x86_64__
166
167 if ((params[i].Attributes.IsBasetype) && !(params[i].Attributes.IsSimpleRef) &&
168 ((params[i].Type.FormatChar) == FC_FLOAT) && !fpuArgs)
169 {
170 tmp = *(double*)arg;
171 arg = (unsigned char*)&tmp;
172 }
173
174 #endif
175 type = (params[i].Attributes.IsBasetype) ? params[i].Type.FormatChar : *fmt;
176 WLog_INFO(TAG, "'\t#%u\ttype %s (0x%02X) ", i, FC_TYPE_STRINGS[type], type);
177 NdrPrintParamAttributes(params[i].Attributes);
178
179 if (params[i].Attributes.IsIn)
180 {
181 NdrProcessParam(pStubMsg, phase, arg, ¶ms[i]);
182 }
183 }
184 }
185
NdrClientInitializeNew(PRPC_MESSAGE pRpcMessage,PMIDL_STUB_MESSAGE pStubMsg,PMIDL_STUB_DESC pStubDesc,unsigned int ProcNum)186 static void NdrClientInitializeNew(PRPC_MESSAGE pRpcMessage, PMIDL_STUB_MESSAGE pStubMsg,
187 PMIDL_STUB_DESC pStubDesc, unsigned int ProcNum)
188 {
189 pRpcMessage->Handle = NULL;
190 pRpcMessage->RpcFlags = 0;
191 pRpcMessage->ProcNum = ProcNum;
192 pRpcMessage->DataRepresentation = 0;
193 pRpcMessage->ReservedForRuntime = NULL;
194 pRpcMessage->RpcInterfaceInformation = pStubDesc->RpcInterfaceInformation;
195 pStubMsg->RpcMsg = pRpcMessage;
196 pStubMsg->BufferStart = NULL;
197 pStubMsg->BufferEnd = NULL;
198 pStubMsg->BufferLength = 0;
199 pStubMsg->StackTop = NULL;
200 pStubMsg->StubDesc = pStubDesc;
201 pStubMsg->IgnoreEmbeddedPointers = 0;
202 pStubMsg->PointerLength = 0;
203 }
204
NdrPrintOptFlags(INTERPRETER_OPT_FLAGS optFlags)205 static void NdrPrintOptFlags(INTERPRETER_OPT_FLAGS optFlags)
206 {
207 if (optFlags.ClientMustSize)
208 WLog_INFO(TAG, "ClientMustSize, ");
209
210 if (optFlags.ServerMustSize)
211 WLog_INFO(TAG, "ServerMustSize, ");
212
213 if (optFlags.HasAsyncUuid)
214 WLog_INFO(TAG, "HasAsyncUiid, ");
215
216 if (optFlags.HasAsyncHandle)
217 WLog_INFO(TAG, "HasAsyncHandle, ");
218
219 if (optFlags.HasReturn)
220 WLog_INFO(TAG, "HasReturn, ");
221
222 if (optFlags.HasPipes)
223 WLog_INFO(TAG, "HasPipes, ");
224
225 if (optFlags.HasExtensions)
226 WLog_INFO(TAG, "HasExtensions, ");
227 }
228
NdrPrintExtFlags(INTERPRETER_OPT_FLAGS2 extFlags)229 static void NdrPrintExtFlags(INTERPRETER_OPT_FLAGS2 extFlags)
230 {
231 if (extFlags.HasNewCorrDesc)
232 WLog_INFO(TAG, "HasNewCorrDesc, ");
233
234 if (extFlags.ClientCorrCheck)
235 WLog_INFO(TAG, "ClientCorrCheck, ");
236
237 if (extFlags.ServerCorrCheck)
238 WLog_INFO(TAG, "ServerCorrCheck, ");
239
240 if (extFlags.HasNotify)
241 WLog_INFO(TAG, "HasNotify, ");
242
243 if (extFlags.HasNotify2)
244 WLog_INFO(TAG, "HasNotify2, ");
245 }
246
NdrClientCall(PMIDL_STUB_DESC pStubDescriptor,PFORMAT_STRING pFormat,void ** stackTop,void ** fpuStack)247 CLIENT_CALL_RETURN NdrClientCall(PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat,
248 void** stackTop, void** fpuStack)
249 {
250 RPC_MESSAGE rpcMsg;
251 unsigned short procNum;
252 unsigned short stackSize;
253 unsigned char numberParams;
254 unsigned char handleType;
255 MIDL_STUB_MESSAGE stubMsg;
256 INTERPRETER_FLAGS flags;
257 INTERPRETER_OPT_FLAGS optFlags;
258 NDR_PROC_HEADER* procHeader;
259 NDR_OI2_PROC_HEADER* oi2ProcHeader;
260 CLIENT_CALL_RETURN client_call_return;
261 procNum = stackSize = numberParams = 0;
262 procHeader = (NDR_PROC_HEADER*)&pFormat[0];
263 client_call_return.Pointer = NULL;
264 handleType = procHeader->HandleType;
265 flags = procHeader->OldOiFlags;
266 procNum = procHeader->ProcNum;
267 stackSize = procHeader->StackSize;
268 pFormat += sizeof(NDR_PROC_HEADER);
269 /* The Header: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378707/ */
270 /* Procedure Header Descriptor:
271 * http://msdn.microsoft.com/en-us/library/windows/desktop/aa374387/ */
272 /* Handles: http://msdn.microsoft.com/en-us/library/windows/desktop/aa373932/ */
273 WLog_DBG(TAG, "Oi Header: HandleType: 0x%02X OiFlags: 0x%02X ProcNum: %hu StackSize: 0x%04X",
274 handleType, *((unsigned char*)&flags), procNum, stackSize);
275
276 if (handleType > 0)
277 {
278 /* implicit handle */
279 WLog_INFO(TAG, "Implicit Handle");
280 oi2ProcHeader = (NDR_OI2_PROC_HEADER*)&pFormat[0];
281 pFormat += sizeof(NDR_OI2_PROC_HEADER);
282 }
283 else
284 {
285 /* explicit handle */
286 WLog_INFO(TAG, "Explicit Handle");
287 oi2ProcHeader = (NDR_OI2_PROC_HEADER*)&pFormat[6];
288 pFormat += sizeof(NDR_OI2_PROC_HEADER) + 6;
289 }
290
291 optFlags = oi2ProcHeader->Oi2Flags;
292 numberParams = oi2ProcHeader->NumberParams;
293 WLog_DBG(TAG,
294 "Oi2 Header: Oi2Flags: 0x%02X, NumberParams: %u ClientBufferSize: %hu "
295 "ServerBufferSize: %hu",
296 *((unsigned char*)&optFlags), numberParams, oi2ProcHeader->ClientBufferSize,
297 oi2ProcHeader->ServerBufferSize);
298 WLog_INFO(TAG, "Oi2Flags: ");
299 NdrPrintOptFlags(optFlags);
300 NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDescriptor, procNum);
301
302 if (optFlags.HasExtensions)
303 {
304 INTERPRETER_OPT_FLAGS2 extFlags;
305 NDR_PROC_HEADER_EXTS* extensions = (NDR_PROC_HEADER_EXTS*)pFormat;
306 pFormat += extensions->Size;
307 extFlags = extensions->Flags2;
308 WLog_DBG(TAG, "Extensions: Size: %hhu, flags2: 0x%02X", extensions->Size,
309 *((unsigned char*)&extensions->Flags2));
310 #ifdef __x86_64__
311
312 if (extensions->Size > sizeof(*extensions) && fpuStack)
313 {
314 int i;
315 unsigned short fpuMask = *(unsigned short*)(extensions + 1);
316
317 for (i = 0; i < 4; i++, fpuMask >>= 2)
318 {
319 switch (fpuMask & 3)
320 {
321 case 1:
322 *(float*)&stackTop[i] = *(float*)&fpuStack[i];
323 break;
324
325 case 2:
326 *(double*)&stackTop[i] = *(double*)&fpuStack[i];
327 break;
328 }
329 }
330 }
331
332 #endif
333 WLog_INFO(TAG, "ExtFlags: ");
334 NdrPrintExtFlags(extFlags);
335 }
336
337 stubMsg.StackTop = (unsigned char*)stackTop;
338 NdrProcessParams(&stubMsg, pFormat, NDR_PHASE_SIZE, fpuStack, numberParams);
339 WLog_DBG(TAG, "stubMsg BufferLength: %" PRIu32 "", stubMsg.BufferLength);
340 return client_call_return;
341 }
342
NdrClientCall2(PMIDL_STUB_DESC pStubDescriptor,PFORMAT_STRING pFormat,...)343 CLIENT_CALL_RETURN NdrClientCall2(PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, ...)
344 {
345 va_list args;
346 CLIENT_CALL_RETURN client_call_return;
347 va_start(args, pFormat);
348 client_call_return = NdrClientCall(pStubDescriptor, pFormat, va_arg(args, void**), NULL);
349 va_end(args);
350 return client_call_return;
351 }
352
353 #endif
354