rpc.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. #ifndef _DEFAULT_SOURCE
  2. #define _DEFAULT_SOURCE
  3. #endif // _DEFAULT_SOURCE
  4. #ifndef CONFIG
  5. #define CONFIG "config.h"
  6. #endif // CONFIG
  7. #include CONFIG
  8. #ifndef USE_MSRPC
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdint.h>
  13. #include <ctype.h>
  14. #include <time.h>
  15. #if !defined(_WIN32)
  16. #include <sys/socket.h>
  17. #include <netdb.h>
  18. #endif
  19. #include "rpc.h"
  20. #include "output.h"
  21. #include "crypto.h"
  22. #include "endian.h"
  23. #include "helpers.h"
  24. #include "network.h"
  25. #include "shared_globals.h"
  26. /* Forwards */
  27. static int checkRpcHeader(const RPC_HEADER *const Header, const BYTE desiredPacketType, const PRINTFUNC p);
  28. /* Data definitions */
  29. // All GUIDs are defined as BYTE[16] here. No big-endian/little-endian byteswapping required.
  30. static const BYTE TransferSyntaxNDR32[] = {
  31. 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C, 0xC9, 0x11, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60
  32. };
  33. static const BYTE InterfaceUuid[] = {
  34. 0x75, 0x21, 0xc8, 0x51, 0x4e, 0x84, 0x50, 0x47, 0xB0, 0xD8, 0xEC, 0x25, 0x55, 0x55, 0xBC, 0x06
  35. };
  36. static const BYTE TransferSyntaxNDR64[] = {
  37. 0x33, 0x05, 0x71, 0x71, 0xba, 0xbe, 0x37, 0x49, 0x83, 0x19, 0xb5, 0xdb, 0xef, 0x9c, 0xcc, 0x36
  38. };
  39. static const BYTE BindTimeFeatureNegotiation[] = {
  40. 0x2c, 0x1c, 0xb7, 0x6c, 0x12, 0x98, 0x40, 0x45, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  41. };
  42. //
  43. // Dispatch RPC payload to kms.c
  44. //
  45. typedef int (*CreateResponse_t)(const void *const, void *const, const char* const);
  46. static const struct {
  47. unsigned int RequestSize;
  48. CreateResponse_t CreateResponse;
  49. } _Versions[] = {
  50. { sizeof(REQUEST_V4), (CreateResponse_t) CreateResponseV4 },
  51. { sizeof(REQUEST_V6), (CreateResponse_t) CreateResponseV6 },
  52. { sizeof(REQUEST_V6), (CreateResponse_t) CreateResponseV6 }
  53. };
  54. RPC_FLAGS RpcFlags;
  55. static int_fast8_t firstPacketSent;
  56. //
  57. // RPC request (server)
  58. //
  59. #if defined(_PEDANTIC) && !defined(NO_LOG)
  60. static void CheckRpcRequest(const RPC_REQUEST64 *const Request, const unsigned int len, WORD* NdrCtx, WORD* Ndr64Ctx, WORD Ctx)
  61. {
  62. uint_fast8_t kmsMajorVersion;
  63. uint32_t requestSize = Ctx != *Ndr64Ctx ? sizeof(RPC_REQUEST) : sizeof(RPC_REQUEST64);
  64. if (len < requestSize)
  65. {
  66. logger("Fatal: RPC request (including header) must be at least %i bytes but is only %i bytes.\n",
  67. (int)(sizeof(RPC_HEADER) + requestSize),
  68. (int)(len + sizeof(RPC_HEADER))
  69. );
  70. return;
  71. }
  72. if (len < requestSize + sizeof(DWORD))
  73. {
  74. logger("Fatal: KMS Request too small to contain version info (less than 4 bytes).\n");
  75. return;
  76. }
  77. if (Ctx != *Ndr64Ctx)
  78. kmsMajorVersion = LE16(((WORD*)Request->Ndr.Data)[1]);
  79. else
  80. kmsMajorVersion = LE16(((WORD*)Request->Ndr64.Data)[1]);
  81. if (kmsMajorVersion > 6)
  82. {
  83. logger("Fatal: KMSv%u is not supported.\n", (unsigned int)kmsMajorVersion);
  84. }
  85. else
  86. {
  87. if (len >_Versions[kmsMajorVersion].RequestSize + requestSize)
  88. logger("Warning: %u excess bytes in RPC request.\n",
  89. len - _Versions[kmsMajorVersion].RequestSize
  90. );
  91. }
  92. if (Ctx != *Ndr64Ctx && Ctx != *NdrCtx)
  93. logger("Warning: Context id should be %u (NDR32) or %u (NDR64) but is %u.\n",
  94. (unsigned int)*NdrCtx,
  95. (unsigned int)*Ndr64Ctx,
  96. Ctx
  97. );
  98. if (Request->Opnum)
  99. logger("Warning: OpNum should be 0 but is %u.\n",
  100. (unsigned int)LE16(Request->Opnum)
  101. );
  102. if (LE32(Request->AllocHint) != len - sizeof(RPC_REQUEST) + sizeof(Request->Ndr))
  103. logger("Warning: Allocation hint should be %u but is %u.\n",
  104. len + sizeof(Request->Ndr),
  105. LE32(Request->AllocHint)
  106. );
  107. if (Ctx != *Ndr64Ctx)
  108. {
  109. if (LE32(Request->Ndr.DataLength) != len - sizeof(RPC_REQUEST))
  110. logger("Warning: NDR32 data length field should be %u but is %u.\n",
  111. len - sizeof(RPC_REQUEST),
  112. LE32(Request->Ndr.DataLength)
  113. );
  114. if (LE32(Request->Ndr.DataSizeIs) != len - sizeof(RPC_REQUEST))
  115. logger("Warning: NDR32 data size field should be %u but is %u.\n",
  116. len - sizeof(RPC_REQUEST),
  117. LE32(Request->Ndr.DataSizeIs)
  118. );
  119. }
  120. else
  121. {
  122. if (LE64(Request->Ndr64.DataLength) != len - sizeof(RPC_REQUEST64))
  123. logger("Warning: NDR32 data length field should be %u but is %u.\n",
  124. len - sizeof(RPC_REQUEST) + sizeof(Request->Ndr),
  125. LE64(Request->Ndr64.DataLength)
  126. );
  127. if (LE64(Request->Ndr64.DataSizeIs) != len - sizeof(RPC_REQUEST64))
  128. logger("Warning: NDR32 data size field should be %u but is %u.\n",
  129. len - sizeof(RPC_REQUEST64),
  130. LE64(Request->Ndr64.DataSizeIs)
  131. );
  132. }
  133. }
  134. #endif // defined(_PEDANTIC) && !defined(NO_LOG)
  135. /*
  136. * check RPC request for (somewhat) correct size
  137. * allow any size that does not cause CreateResponse to fail badly
  138. */
  139. static unsigned int checkRpcRequestSize(const RPC_REQUEST64 *const Request, const unsigned int requestSize, WORD* NdrCtx, WORD* Ndr64Ctx)
  140. {
  141. WORD Ctx = LE16(Request->ContextId);
  142. # if defined(_PEDANTIC) && !defined(NO_LOG)
  143. CheckRpcRequest(Request, requestSize, NdrCtx, Ndr64Ctx, Ctx);
  144. # endif // defined(_PEDANTIC) && !defined(NO_LOG)
  145. // Anything that is smaller than a v4 request is illegal
  146. if (requestSize < sizeof(REQUEST_V4) + (Ctx != *Ndr64Ctx ? sizeof(RPC_REQUEST) : sizeof(RPC_REQUEST64))) return 0;
  147. // Get KMS major version
  148. uint_fast16_t _v;
  149. if (Ctx != *Ndr64Ctx)
  150. _v = LE16(((WORD*)Request->Ndr.Data)[1]) - 4;
  151. else
  152. _v = LE16(((WORD*)Request->Ndr64.Data)[1]) - 4;
  153. // Only KMS v4, v5 and v6 are supported
  154. if (_v >= vlmcsd_countof(_Versions))
  155. {
  156. # ifndef NO_LOG
  157. logger("Fatal: KMSv%i unsupported\n", _v + 4);
  158. # endif // NO_LOG
  159. return 0;
  160. }
  161. // Could check for equality but allow bigger requests to support buggy RPC clients (e.g. wine)
  162. // Buffer overrun is check by caller.
  163. return (requestSize >= _Versions[_v].RequestSize);
  164. }
  165. /*
  166. * Handles the actual KMS request from the client.
  167. * Calls KMS functions (CreateResponseV4 or CreateResponseV6) in kms.c
  168. * Returns size of the KMS response packet or 0 on failure.
  169. *
  170. * The RPC packet size (excluding header) is actually in Response->AllocHint
  171. */
  172. static int rpcRequest(const RPC_REQUEST64 *const Request, RPC_RESPONSE64 *const Response, const DWORD RpcAssocGroup_unused, const SOCKET sock_unused, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr)
  173. {
  174. uint_fast16_t _v;
  175. int ResponseSize;
  176. WORD Ctx = LE16(Request->ContextId);
  177. BYTE* requestData;
  178. BYTE* responseData;
  179. BYTE* pRpcReturnCode;
  180. int len;
  181. if (Ctx != *Ndr64Ctx)
  182. {
  183. requestData = (BYTE*)&Request->Ndr.Data;
  184. responseData = (BYTE*)&Response->Ndr.Data;
  185. }
  186. else
  187. {
  188. requestData = (BYTE*)&Request->Ndr64.Data;
  189. responseData = (BYTE*)&Response->Ndr64.Data;
  190. }
  191. _v = LE16(((WORD*)requestData)[1]) - 4;
  192. if (!(ResponseSize = _Versions[_v].CreateResponse(requestData, responseData, ipstr)))
  193. {
  194. return 0;
  195. }
  196. if (Ctx != *Ndr64Ctx)
  197. {
  198. Response->Ndr.DataSizeMax = LE32(0x00020000);
  199. Response->Ndr.DataLength = Response->Ndr.DataSizeIs = LE32(ResponseSize);
  200. len = ResponseSize + sizeof(Response->Ndr);
  201. }
  202. else
  203. {
  204. Response->Ndr64.DataSizeMax = LE64(0x00020000ULL);
  205. Response->Ndr64.DataLength = Response->Ndr64.DataSizeIs = LE64((uint64_t)ResponseSize);
  206. len = ResponseSize + sizeof(Response->Ndr64);
  207. }
  208. pRpcReturnCode = ((BYTE*)&Response->Ndr) + len;
  209. UA32(pRpcReturnCode) = 0; //LE32 not needed for 0
  210. len += sizeof(DWORD);
  211. // Pad zeros to 32-bit align (seems not neccassary but Windows RPC does it this way)
  212. int pad = ((~len & 3) + 1) & 3;
  213. memset(pRpcReturnCode + sizeof(DWORD), 0, pad);
  214. len += pad;
  215. Response->AllocHint = LE32(len);
  216. Response->ContextId = Request->ContextId;
  217. *((WORD*)&Response->CancelCount) = 0; // CancelCount + Pad1
  218. return len + 8;
  219. }
  220. #if defined(_PEDANTIC) && !defined(NO_LOG)
  221. static void CheckRpcBindRequest(const RPC_BIND_REQUEST *const Request, const unsigned int len)
  222. {
  223. uint_fast8_t i, HasTransferSyntaxNDR32 = FALSE;
  224. char guidBuffer1[GUID_STRING_LENGTH + 1], guidBuffer2[GUID_STRING_LENGTH + 1];
  225. uint32_t CapCtxItems = (len - sizeof(*Request) + sizeof(Request->CtxItems)) / sizeof(Request->CtxItems);
  226. DWORD NumCtxItems = LE32(Request->NumCtxItems);
  227. if (NumCtxItems < CapCtxItems) // Can't be too small because already handled by RpcBindSize
  228. logger("Warning: Excess bytes in RPC bind request.\n");
  229. for (i = 0; i < NumCtxItems; i++)
  230. {
  231. if (!IsEqualGUID(&Request->CtxItems[i].InterfaceUUID, InterfaceUuid))
  232. {
  233. uuid2StringLE((GUID*)&Request->CtxItems[i].InterfaceUUID, guidBuffer1);
  234. uuid2StringLE((GUID*)InterfaceUuid, guidBuffer2);
  235. logger("Warning: Interface UUID is %s but should be %s in Ctx item %u.\n", guidBuffer1, guidBuffer2, (unsigned int)i);
  236. }
  237. if (Request->CtxItems[i].NumTransItems != LE16(1))
  238. logger("Fatal: %u NDR32 transfer items detected in Ctx item %u, but only one is supported.\n",
  239. (unsigned int)LE16(Request->CtxItems[i].NumTransItems), (unsigned int)i
  240. );
  241. if (Request->CtxItems[i].InterfaceVerMajor != LE16(1) || Request->CtxItems[i].InterfaceVerMinor != 0)
  242. logger("Warning: NDR32 Interface version is %u.%u but should be 1.0.\n",
  243. (unsigned int)LE16(Request->CtxItems[i].InterfaceVerMajor),
  244. (unsigned int)LE16(Request->CtxItems[i].InterfaceVerMinor)
  245. );
  246. if (Request->CtxItems[i].ContextId != LE16((WORD)i))
  247. logger("Warning: context id of Ctx item %u is %u.\n", (unsigned int)i, (unsigned int)Request->CtxItems[i].ContextId);
  248. if ( IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
  249. {
  250. HasTransferSyntaxNDR32 = TRUE;
  251. if (Request->CtxItems[i].SyntaxVersion != LE32(2))
  252. logger("NDR32 transfer syntax version is %u but should be 2.\n", LE32(Request->CtxItems[i].SyntaxVersion));
  253. }
  254. else if ( IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
  255. {
  256. if (Request->CtxItems[i].SyntaxVersion != LE32(1))
  257. logger("NDR64 transfer syntax version is %u but should be 1.\n", LE32(Request->CtxItems[i].SyntaxVersion));
  258. }
  259. else if (!memcmp(BindTimeFeatureNegotiation, (BYTE*)(&Request->CtxItems[i].TransferSyntax), 8))
  260. {
  261. if (Request->CtxItems[i].SyntaxVersion != LE32(1))
  262. logger("BTFN syntax version is %u but should be 1.\n", LE32(Request->CtxItems[i].SyntaxVersion));
  263. }
  264. }
  265. if (!HasTransferSyntaxNDR32)
  266. logger("Warning: RPC bind request has no NDR32 CtxItem.\n");
  267. }
  268. #endif // defined(_PEDANTIC) && !defined(NO_LOG)
  269. /*
  270. * Check, if we receive enough bytes to return a valid RPC bind response
  271. */
  272. static unsigned int checkRpcBindSize(const RPC_BIND_REQUEST *const Request, const unsigned int RequestSize, WORD* NdrCtx, WORD* Ndr64Ctx)
  273. {
  274. if ( RequestSize < sizeof(RPC_BIND_REQUEST) ) return FALSE;
  275. unsigned int _NumCtxItems = LE32(Request->NumCtxItems);
  276. if ( RequestSize < sizeof(RPC_BIND_REQUEST) - sizeof(Request->CtxItems[0]) + _NumCtxItems * sizeof(Request->CtxItems[0]) ) return FALSE;
  277. #if defined(_PEDANTIC) && !defined(NO_LOG)
  278. CheckRpcBindRequest(Request, RequestSize);
  279. #endif // defined(_PEDANTIC) && !defined(NO_LOG)
  280. return TRUE;
  281. }
  282. /*
  283. * Accepts a bind or alter context request from the client and composes the bind response.
  284. * Needs the socket because the tcp port number is part of the response.
  285. * len is not used here.
  286. *
  287. * Returns TRUE on success.
  288. */
  289. static int rpcBind(const RPC_BIND_REQUEST *const Request, RPC_BIND_RESPONSE* Response, const DWORD RpcAssocGroup, const SOCKET sock, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr_unused)
  290. {
  291. unsigned int i, _st = FALSE;
  292. DWORD numCtxItems = LE32(Request->NumCtxItems);
  293. int_fast8_t IsNDR64possible = FALSE;
  294. uint_fast8_t portNumberSize;
  295. socklen_t socklen;
  296. struct sockaddr_storage addr;
  297. // M$ RPC does not do this. Pad bytes contain apparently random data
  298. // memset(Response->SecondaryAddress, 0, sizeof(Response->SecondaryAddress));
  299. socklen = sizeof addr;
  300. if (
  301. packetType == RPC_PT_ALTERCONTEXT_REQ ||
  302. getsockname(sock, (struct sockaddr*)&addr, &socklen) ||
  303. getnameinfo((struct sockaddr*)&addr, socklen, NULL, 0, (char*)Response->SecondaryAddress, sizeof(Response->SecondaryAddress), NI_NUMERICSERV))
  304. {
  305. portNumberSize = Response->SecondaryAddressLength = 0;
  306. }
  307. else
  308. {
  309. portNumberSize = strlen((char*)Response->SecondaryAddress) + 1;
  310. Response->SecondaryAddressLength = LE16(portNumberSize);
  311. }
  312. Response->MaxXmitFrag = Request->MaxXmitFrag;
  313. Response->MaxRecvFrag = Request->MaxRecvFrag;
  314. Response->AssocGroup = LE32(RpcAssocGroup);
  315. // This is really ugly (but efficient) code to support padding after the secondary address field
  316. if (portNumberSize < 3)
  317. {
  318. Response = (RPC_BIND_RESPONSE*)((BYTE*)Response - 4);
  319. }
  320. Response->NumResults = Request->NumCtxItems;
  321. if (UseRpcNDR64)
  322. {
  323. for (i = 0; i < numCtxItems; i++)
  324. {
  325. if ( IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
  326. {
  327. /*if (packetType == RPC_PT_BIND_REQ)*/
  328. *NdrCtx = LE16(Request->CtxItems[i].ContextId);
  329. }
  330. if ( IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
  331. {
  332. IsNDR64possible = TRUE;
  333. /*if (packetType == RPC_PT_BIND_REQ)*/
  334. *Ndr64Ctx = LE16(Request->CtxItems[i].ContextId);
  335. }
  336. }
  337. }
  338. for (i = 0; i < numCtxItems; i++)
  339. {
  340. memset(&Response->Results[i].TransferSyntax, 0, sizeof(GUID));
  341. if ( !IsNDR64possible && IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
  342. {
  343. Response->Results[i].SyntaxVersion = LE32(2);
  344. Response->Results[i].AckResult =
  345. Response->Results[i].AckReason = RPC_BIND_ACCEPT;
  346. memcpy(&Response->Results[i].TransferSyntax, TransferSyntaxNDR32, sizeof(GUID));
  347. _st = TRUE;
  348. }
  349. else if ( IsNDR64possible && IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
  350. {
  351. Response->Results[i].SyntaxVersion = LE32(1);
  352. Response->Results[i].AckResult =
  353. Response->Results[i].AckReason = RPC_BIND_ACCEPT;
  354. memcpy(&Response->Results[i].TransferSyntax, TransferSyntaxNDR64, sizeof(GUID));
  355. _st = TRUE;
  356. }
  357. else if ( UseRpcBTFN && !memcmp(BindTimeFeatureNegotiation, (BYTE*)(&Request->CtxItems[i].TransferSyntax), 8) )
  358. {
  359. Response->Results[i].SyntaxVersion = 0;
  360. Response->Results[i].AckResult = RPC_BIND_ACK;
  361. // Features requested are actually encoded in the GUID
  362. Response->Results[i].AckReason =
  363. ((WORD*)(&Request->CtxItems[i].TransferSyntax))[4] &
  364. (RPC_BTFN_SEC_CONTEXT_MULTIPLEX | RPC_BTFN_KEEP_ORPHAN);
  365. }
  366. else
  367. {
  368. Response->Results[i].SyntaxVersion = 0;
  369. Response->Results[i].AckResult =
  370. Response->Results[i].AckReason = RPC_BIND_NACK; // Unsupported
  371. }
  372. }
  373. if ( !_st ) return 0;
  374. return sizeof(RPC_BIND_RESPONSE) + numCtxItems * sizeof(((RPC_BIND_RESPONSE *)0)->Results[0]) - (portNumberSize < 3 ? 4 : 0);
  375. }
  376. //
  377. // Main RPC handling routine
  378. //
  379. typedef unsigned int (*GetResponseSize_t)(const void *const request, const unsigned int requestSize, WORD* NdrCtx, WORD* Ndr64Ctx);
  380. typedef int (*GetResponse_t)(const void* const request, void* response, const DWORD rpcAssocGroup, const SOCKET socket, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr);
  381. static const struct {
  382. BYTE ResponsePacketType;
  383. GetResponseSize_t CheckRequestSize;
  384. GetResponse_t GetResponse;
  385. }
  386. _Actions[] = {
  387. { RPC_PT_BIND_ACK, (GetResponseSize_t)checkRpcBindSize, (GetResponse_t) rpcBind },
  388. { RPC_PT_RESPONSE, (GetResponseSize_t)checkRpcRequestSize, (GetResponse_t) rpcRequest },
  389. { RPC_PT_ALTERCONTEXT_ACK, (GetResponseSize_t)checkRpcBindSize, (GetResponse_t) rpcBind },
  390. };
  391. /*
  392. * This is the main RPC server loop. Returns after KMS request has been serviced
  393. * or a timeout has occured.
  394. */
  395. void rpcServer(const SOCKET sock, const DWORD RpcAssocGroup, const char* const ipstr)
  396. {
  397. RPC_HEADER rpcRequestHeader;
  398. WORD NdrCtx = INVALID_NDR_CTX, Ndr64Ctx = INVALID_NDR_CTX;
  399. randomNumberInit();
  400. while (_recv(sock, &rpcRequestHeader, sizeof(rpcRequestHeader)))
  401. {
  402. //int_fast8_t _st;
  403. unsigned int request_len, response_len;
  404. uint_fast8_t _a;
  405. #if defined(_PEDANTIC) && !defined(NO_LOG)
  406. checkRpcHeader(&rpcRequestHeader, rpcRequestHeader.PacketType, &logger);
  407. #endif // defined(_PEDANTIC) && !defined(NO_LOG)
  408. switch (rpcRequestHeader.PacketType)
  409. {
  410. case RPC_PT_BIND_REQ: _a = 0; break;
  411. case RPC_PT_REQUEST: _a = 1; break;
  412. case RPC_PT_ALTERCONTEXT_REQ: _a = 2; break;
  413. default: return;
  414. }
  415. request_len = LE16(rpcRequestHeader.FragLength) - sizeof(rpcRequestHeader);
  416. BYTE requestBuffer[MAX_REQUEST_SIZE + sizeof(RPC_RESPONSE64)];
  417. BYTE responseBuffer[MAX_RESPONSE_SIZE + sizeof(RPC_HEADER) + sizeof(RPC_RESPONSE64)];
  418. RPC_HEADER *rpcResponseHeader = (RPC_HEADER *)responseBuffer;
  419. RPC_RESPONSE* rpcResponse = (RPC_RESPONSE*)(responseBuffer + sizeof(rpcRequestHeader));
  420. // The request is larger than the buffer size
  421. if (request_len > MAX_REQUEST_SIZE + sizeof(RPC_REQUEST64)) return;
  422. // Unable to receive the complete request
  423. if (!_recv(sock, requestBuffer, request_len)) return;
  424. // Request is invalid
  425. if (!_Actions[_a].CheckRequestSize(requestBuffer, request_len, &NdrCtx, &Ndr64Ctx)) return;
  426. // Unable to create a valid response from request
  427. if (!(response_len = _Actions[_a].GetResponse(requestBuffer, rpcResponse, RpcAssocGroup, sock, &NdrCtx, &Ndr64Ctx, rpcRequestHeader.PacketType, ipstr))) return;
  428. response_len += sizeof(RPC_HEADER);
  429. memcpy(rpcResponseHeader, &rpcRequestHeader, sizeof(RPC_HEADER));
  430. rpcResponseHeader->FragLength = LE16(response_len);
  431. rpcResponseHeader->PacketType = _Actions[_a].ResponsePacketType;
  432. if (rpcResponseHeader->PacketType == RPC_PT_ALTERCONTEXT_ACK)
  433. rpcResponseHeader->PacketFlags = RPC_PF_FIRST | RPC_PF_LAST;
  434. if (!_send(sock, responseBuffer, response_len)) return;
  435. if (DisconnectImmediately && rpcResponseHeader->PacketType == RPC_PT_RESPONSE)
  436. shutdown(sock, VLMCSD_SHUT_RDWR);
  437. }
  438. }
  439. /* RPC client functions */
  440. static DWORD CallId = 2; // M$ starts with CallId 2. So we do the same.
  441. /*
  442. * Checks RPC header. Returns 0 on success.
  443. * This is mainly for debugging a non Microsoft KMS server that uses its own RPC code.
  444. */
  445. static int checkRpcHeader(const RPC_HEADER *const Header, const BYTE desiredPacketType, const PRINTFUNC p)
  446. {
  447. int status = 0;
  448. if (Header->PacketType != desiredPacketType)
  449. {
  450. p("Fatal: Received wrong RPC packet type. Expected %u but got %u\n",
  451. (uint32_t)desiredPacketType,
  452. Header->PacketType
  453. );
  454. status = !0;
  455. }
  456. if (Header->DataRepresentation != BE32(0x10000000))
  457. {
  458. p("Fatal: RPC response does not conform to Microsoft's limited support of DCE RPC\n");
  459. status = !0;
  460. }
  461. if (Header->AuthLength != 0)
  462. {
  463. p("Fatal: RPC response requests authentication\n");
  464. status = !0;
  465. }
  466. // vlmcsd does not support fragmented packets (not yet neccassary)
  467. if ( (Header->PacketFlags & (RPC_PF_FIRST | RPC_PF_LAST)) != (RPC_PF_FIRST | RPC_PF_LAST) )
  468. {
  469. p("Fatal: RPC packet flags RPC_PF_FIRST and RPC_PF_LAST are not both set.\n");
  470. status = !0;
  471. }
  472. if (Header->PacketFlags & RPC_PF_CANCEL_PENDING) p("Warning: %s should not be set\n", "RPC_PF_CANCEL_PENDING");
  473. if (Header->PacketFlags & RPC_PF_RESERVED) p("Warning: %s should not be set\n", "RPC_PF_RESERVED");
  474. if (Header->PacketFlags & RPC_PF_NOT_EXEC) p("Warning: %s should not be set\n", "RPC_PF_NOT_EXEC");
  475. if (Header->PacketFlags & RPC_PF_MAYBE) p("Warning: %s should not be set\n", "RPC_PF_MAYBE");
  476. if (Header->PacketFlags & RPC_PF_OBJECT) p("Warning: %s should not be set\n", "RPC_PF_OBJECT");
  477. if (Header->VersionMajor != 5 || Header->VersionMinor != 0)
  478. {
  479. p("Fatal: Expected RPC version 5.0 and got %u.%u\n", Header->VersionMajor, Header->VersionMinor);
  480. status = !0;
  481. }
  482. return status;
  483. }
  484. /*
  485. * Checks an RPC response header. Does basic header checks by calling checkRpcHeader()
  486. * and then does additional checks if response header complies with the respective request header.
  487. * PRINTFUNC p can be anything that has the same prototype as printf.
  488. * Returns 0 on success.
  489. */
  490. static int checkRpcResponseHeader(const RPC_HEADER *const ResponseHeader, const RPC_HEADER *const RequestHeader, const BYTE desiredPacketType, const PRINTFUNC p)
  491. {
  492. static int_fast8_t WineBugDetected = FALSE;
  493. int status = checkRpcHeader(ResponseHeader, desiredPacketType, p);
  494. if (desiredPacketType == RPC_PT_BIND_ACK)
  495. {
  496. if ((ResponseHeader->PacketFlags & RPC_PF_MULTIPLEX) != (RequestHeader->PacketFlags & RPC_PF_MULTIPLEX))
  497. {
  498. p("Warning: RPC_PF_MULTIPLEX of RPC request and response should match\n");
  499. }
  500. }
  501. else
  502. {
  503. if (ResponseHeader->PacketFlags & RPC_PF_MULTIPLEX)
  504. {
  505. p("Warning: %s should not be set\n", "RPC_PF_MULTIPLEX");
  506. }
  507. }
  508. if (!status && ResponseHeader->CallId == LE32(1))
  509. {
  510. if (!WineBugDetected)
  511. {
  512. p("Warning: Buggy RPC of Wine detected. Call Id of Response is always 1\n");
  513. WineBugDetected = TRUE;
  514. }
  515. }
  516. else if (ResponseHeader->CallId != RequestHeader->CallId)
  517. {
  518. p("Fatal: Sent Call Id %u but received answer for Call Id %u\n",
  519. (uint32_t)LE32(RequestHeader->CallId),
  520. (uint32_t)LE32(ResponseHeader->CallId)
  521. );
  522. status = !0;
  523. }
  524. return status;
  525. }
  526. /*
  527. * Initializes an RPC request header as needed for KMS, i.e. packet always fits in one fragment.
  528. * size cannot be greater than fragment length negotiated during RPC bind.
  529. */
  530. static void createRpcRequestHeader(RPC_HEADER* RequestHeader, BYTE packetType, WORD size)
  531. {
  532. RequestHeader->PacketType = packetType;
  533. RequestHeader->PacketFlags = RPC_PF_FIRST | RPC_PF_LAST;
  534. RequestHeader->VersionMajor = 5;
  535. RequestHeader->VersionMinor = 0;
  536. RequestHeader->AuthLength = 0;
  537. RequestHeader->DataRepresentation = BE32(0x10000000); // Little endian, ASCII charset, IEEE floating point
  538. RequestHeader->CallId = LE32(CallId);
  539. RequestHeader->FragLength = LE16(size);
  540. }
  541. /*
  542. * Sends a KMS request via RPC and receives a response.
  543. * Parameters are raw (encrypted) reqeuests / responses.
  544. * Returns 0 on success.
  545. */
  546. RpcStatus rpcSendRequest(const RpcCtx sock, const BYTE *const KmsRequest, const size_t requestSize, BYTE **KmsResponse, size_t *const responseSize)
  547. {
  548. #define MAX_EXCESS_BYTES 16
  549. RPC_HEADER *RequestHeader, ResponseHeader;
  550. RPC_REQUEST64 *RpcRequest;
  551. RPC_RESPONSE64 _Response;
  552. int status = 0;
  553. int_fast8_t useNdr64 = UseRpcNDR64 && firstPacketSent;
  554. size_t size = sizeof(RPC_HEADER) + (useNdr64 ? sizeof(RPC_REQUEST64) : sizeof(RPC_REQUEST)) + requestSize;
  555. size_t responseSize2;
  556. *KmsResponse = NULL;
  557. BYTE *_Request = (BYTE*)vlmcsd_malloc(size);
  558. RequestHeader = (RPC_HEADER*)_Request;
  559. RpcRequest = (RPC_REQUEST64*)(_Request + sizeof(RPC_HEADER));
  560. createRpcRequestHeader(RequestHeader, RPC_PT_REQUEST, size);
  561. // Increment CallId for next Request
  562. CallId++;
  563. RpcRequest->Opnum = 0;
  564. if (useNdr64)
  565. {
  566. RpcRequest->ContextId = LE16(1); // We negotiate NDR64 always as context 1
  567. RpcRequest->AllocHint = LE32(requestSize + sizeof(RpcRequest->Ndr64));
  568. RpcRequest->Ndr64.DataLength = LE64((uint64_t)requestSize);
  569. RpcRequest->Ndr64.DataSizeIs = LE64((uint64_t)requestSize);
  570. memcpy(RpcRequest->Ndr64.Data, KmsRequest, requestSize);
  571. }
  572. else
  573. {
  574. RpcRequest->ContextId = 0; // We negotiate NDR32 always as context 0
  575. RpcRequest->AllocHint = LE32(requestSize + sizeof(RpcRequest->Ndr));
  576. RpcRequest->Ndr.DataLength = LE32(requestSize);
  577. RpcRequest->Ndr.DataSizeIs = LE32(requestSize);
  578. memcpy(RpcRequest->Ndr.Data, KmsRequest, requestSize);
  579. }
  580. for(;;)
  581. {
  582. int bytesread;
  583. if (!_send(sock, _Request, size))
  584. {
  585. errorout("\nFatal: Could not send RPC request\n");
  586. status = !0;
  587. break;
  588. }
  589. if (!_recv(sock, &ResponseHeader, sizeof(RPC_HEADER)))
  590. {
  591. errorout("\nFatal: No RPC response received from server\n");
  592. status = !0;
  593. break;
  594. }
  595. if ((status = checkRpcResponseHeader(&ResponseHeader, RequestHeader, RPC_PT_RESPONSE, &errorout))) break;
  596. size = useNdr64 ? sizeof(RPC_RESPONSE64) : sizeof(RPC_RESPONSE);
  597. if (size > LE16(ResponseHeader.FragLength) - sizeof(ResponseHeader))
  598. size = LE16(ResponseHeader.FragLength) - sizeof(ResponseHeader);
  599. if (!_recv(sock, &_Response, size))
  600. {
  601. errorout("\nFatal: RPC response is incomplete\n");
  602. status = !0;
  603. break;
  604. }
  605. if (_Response.CancelCount != 0)
  606. {
  607. errorout("\nFatal: RPC response cancel count is not 0\n");
  608. status = !0;
  609. }
  610. if (_Response.ContextId != (useNdr64 ? LE16(1) : 0))
  611. {
  612. errorout("\nFatal: RPC response context id %u is not bound\n", (unsigned int)LE16(_Response.ContextId));
  613. status = !0;
  614. }
  615. int_fast8_t sizesMatch;
  616. if (useNdr64)
  617. {
  618. *responseSize = (size_t)LE64(_Response.Ndr64.DataLength);
  619. responseSize2 = (size_t)LE64(_Response.Ndr64.DataSizeIs);
  620. if (!*responseSize || !_Response.Ndr64.DataSizeMax)
  621. {
  622. status = (int)LE32(_Response.Ndr64.status);
  623. break;
  624. }
  625. sizesMatch = (size_t)LE64(_Response.Ndr64.DataLength) == responseSize2;
  626. }
  627. else
  628. {
  629. *responseSize = (size_t)LE32(_Response.Ndr.DataLength);
  630. responseSize2 = (size_t)LE32(_Response.Ndr.DataSizeIs);
  631. if (!*responseSize || !_Response.Ndr.DataSizeMax)
  632. {
  633. status = (int)LE32(_Response.Ndr.status);
  634. break;
  635. }
  636. sizesMatch = (size_t)LE32(_Response.Ndr.DataLength) == responseSize2;
  637. }
  638. if (!sizesMatch)
  639. {
  640. errorout("\nFatal: NDR data length (%u) does not match NDR data size (%u)\n",
  641. (uint32_t)*responseSize,
  642. (uint32_t)LE32(_Response.Ndr.DataSizeIs)
  643. );
  644. status = !0;
  645. }
  646. *KmsResponse = (BYTE*)vlmcsd_malloc(*responseSize + MAX_EXCESS_BYTES);
  647. // If RPC stub is too short, assume missing bytes are zero (same ill behavior as MS RPC)
  648. memset(*KmsResponse, 0, *responseSize + MAX_EXCESS_BYTES);
  649. // Read up to 16 bytes more than bytes expected to detect faulty KMS emulators
  650. if ((bytesread = recv(sock, (char*)*KmsResponse, *responseSize + MAX_EXCESS_BYTES, 0)) < (int)*responseSize)
  651. {
  652. errorout("\nFatal: No or incomplete KMS response received. Required %u bytes but only got %i\n",
  653. (uint32_t)*responseSize,
  654. (int32_t)(bytesread < 0 ? 0 : bytesread)
  655. );
  656. status = !0;
  657. break;
  658. }
  659. DWORD *pReturnCode;
  660. size_t len = *responseSize + (useNdr64 ? sizeof(_Response.Ndr64) : sizeof(_Response.Ndr)) + sizeof(*pReturnCode);
  661. size_t pad = ((~len & 3) + 1) & 3;
  662. if (len + pad != LE32(_Response.AllocHint))
  663. {
  664. errorout("\nWarning: RPC stub size is %u, should be %u (probably incorrect padding)\n", (uint32_t)LE32(_Response.AllocHint), (uint32_t)(len + pad));
  665. }
  666. else
  667. {
  668. size_t i;
  669. for (i = 0; i < pad; i++)
  670. {
  671. if (*(*KmsResponse + *responseSize + sizeof(*pReturnCode) + i))
  672. {
  673. errorout("\nWarning: RPC stub data not padded to zeros according to Microsoft standard\n");
  674. break;
  675. }
  676. }
  677. }
  678. pReturnCode = (DWORD*)(*KmsResponse + *responseSize + pad);
  679. status = LE32(UA32(pReturnCode));
  680. if (status) errorout("\nWarning: RPC stub data reported Error %u\n", (uint32_t)status);
  681. break;
  682. }
  683. free(_Request);
  684. firstPacketSent = TRUE;
  685. return status;
  686. #undef MAX_EXCESS_BYTES
  687. }
  688. static int_fast8_t IsNullGuid(BYTE* guidPtr)
  689. {
  690. int_fast8_t i;
  691. for (i = 0; i < 16; i++)
  692. {
  693. if (guidPtr[i]) return FALSE;
  694. }
  695. return TRUE;
  696. }
  697. /*
  698. * Perform RPC client bind. Accepts a connected client socket.
  699. * Returns 0 on success. RPC binding is required before any payload can be
  700. * exchanged. It negotiates about protocol details.
  701. */
  702. RpcStatus rpcBindOrAlterClientContext(const RpcCtx sock, BYTE packetType, const int_fast8_t verbose)
  703. {
  704. RPC_HEADER *RequestHeader, ResponseHeader;
  705. RPC_BIND_REQUEST *bindRequest;
  706. RPC_BIND_RESPONSE *bindResponse;
  707. int status;
  708. WORD ctxItems = 1 + (packetType == RPC_PT_BIND_REQ ? UseRpcNDR64 + UseRpcBTFN : 0);
  709. size_t rpcBindSize = (sizeof(RPC_HEADER) + sizeof(RPC_BIND_REQUEST) + (ctxItems - 1) * sizeof(bindRequest->CtxItems[0]));
  710. WORD ctxIndex = 0;
  711. WORD i;
  712. WORD CtxBTFN = (WORD)~0, CtxNDR64 = (WORD)~0;
  713. BYTE _Request[rpcBindSize];
  714. RequestHeader = (RPC_HEADER*)_Request;
  715. bindRequest = (RPC_BIND_REQUEST* )(_Request + sizeof(RPC_HEADER));
  716. createRpcRequestHeader(RequestHeader, packetType, rpcBindSize);
  717. RequestHeader->PacketFlags |= UseMultiplexedRpc ? RPC_PF_MULTIPLEX : 0;
  718. bindRequest->AssocGroup = 0;
  719. bindRequest->MaxRecvFrag = bindRequest->MaxXmitFrag = LE16(5840);
  720. bindRequest->NumCtxItems = LE32(ctxItems);
  721. // data that is identical in all Ctx items
  722. for (i = 0; i < ctxItems; i++)
  723. {
  724. bindRequest->CtxItems[i].ContextId = LE16(i);
  725. bindRequest->CtxItems[i].InterfaceVerMajor = LE16(1);
  726. bindRequest->CtxItems[i].InterfaceVerMinor = 0;
  727. bindRequest->CtxItems[i].NumTransItems = LE16(1);
  728. bindRequest->CtxItems[i].SyntaxVersion = i ? LE32(1) : LE32(2);
  729. memcpy(&bindRequest->CtxItems[i].InterfaceUUID, InterfaceUuid, sizeof(GUID));
  730. }
  731. memcpy(&bindRequest->CtxItems[0].TransferSyntax, TransferSyntaxNDR32, sizeof(GUID));
  732. if (UseRpcNDR64 && packetType == RPC_PT_BIND_REQ)
  733. {
  734. memcpy(&bindRequest->CtxItems[++ctxIndex].TransferSyntax, TransferSyntaxNDR64, sizeof(GUID));
  735. CtxNDR64 = ctxIndex;
  736. }
  737. if (UseRpcBTFN && packetType == RPC_PT_BIND_REQ)
  738. {
  739. memcpy(&bindRequest->CtxItems[++ctxIndex].TransferSyntax, BindTimeFeatureNegotiation, sizeof(GUID));
  740. CtxBTFN = ctxIndex;
  741. }
  742. if (!_send(sock, _Request, rpcBindSize))
  743. {
  744. errorout("\nFatal: Sending RPC bind request failed\n");
  745. return !0;
  746. }
  747. if (!_recv(sock, &ResponseHeader, sizeof(RPC_HEADER)))
  748. {
  749. errorout("\nFatal: Did not receive a response from server\n");
  750. return !0;
  751. }
  752. if ((status = checkRpcResponseHeader
  753. (
  754. &ResponseHeader,
  755. RequestHeader,
  756. packetType == RPC_PT_BIND_REQ ? RPC_PT_BIND_ACK : RPC_PT_ALTERCONTEXT_ACK,
  757. &errorout
  758. )))
  759. {
  760. return status;
  761. }
  762. bindResponse = (RPC_BIND_RESPONSE*)vlmcsd_malloc(LE16(ResponseHeader.FragLength) - sizeof(RPC_HEADER));
  763. BYTE* bindResponseBytePtr = (BYTE*)bindResponse;
  764. if (!_recv(sock, bindResponse, LE16(ResponseHeader.FragLength) - sizeof(RPC_HEADER)))
  765. {
  766. errorout("\nFatal: Incomplete RPC bind acknowledgement received\n");
  767. free(bindResponseBytePtr);
  768. return !0;
  769. }
  770. else
  771. {
  772. /*
  773. * checking, whether a bind or alter context response is as expected.
  774. * This check is very strict and checks whether a KMS emulator behaves exactly the same way
  775. * as Microsoft's RPC does.
  776. */
  777. status = 0;
  778. if (bindResponse->SecondaryAddressLength < LE16(3))
  779. bindResponse = (RPC_BIND_RESPONSE*)(bindResponseBytePtr - 4);
  780. if (bindResponse->NumResults != bindRequest->NumCtxItems)
  781. {
  782. errorout("\nFatal: Expected %u CTX items but got %u\n",
  783. (uint32_t)LE32(bindRequest->NumCtxItems),
  784. (uint32_t)LE32(bindResponse->NumResults)
  785. );
  786. status = !0;
  787. }
  788. for (i = 0; i < ctxItems; i++)
  789. {
  790. const char* transferSyntaxName =
  791. i == CtxBTFN ? "BTFN" : i == CtxNDR64 ? "NDR64" : "NDR32";
  792. if (bindResponse->Results[i].AckResult == RPC_BIND_NACK) // transfer syntax was declined
  793. {
  794. if (!IsNullGuid((BYTE*)&bindResponse->Results[i].TransferSyntax))
  795. {
  796. errorout(
  797. "\nWarning: Rejected transfer syntax %s did not return NULL Guid\n",
  798. transferSyntaxName
  799. );
  800. }
  801. if (bindResponse->Results[i].SyntaxVersion)
  802. {
  803. errorout(
  804. "\nWarning: Rejected transfer syntax %s did not return syntax version 0 but %u\n",
  805. transferSyntaxName,
  806. LE32(bindResponse->Results[i].SyntaxVersion)
  807. );
  808. }
  809. if (bindResponse->Results[i].AckReason == RPC_ABSTRACTSYNTAX_UNSUPPORTED)
  810. {
  811. errorout(
  812. "\nWarning: Transfer syntax %s does not support KMS activation\n",
  813. transferSyntaxName
  814. );
  815. }
  816. else if (bindResponse->Results[i].AckReason != RPC_SYNTAX_UNSUPPORTED)
  817. {
  818. errorout(
  819. "\nWarning: Rejected transfer syntax %s did not return ack reason RPC_SYNTAX_UNSUPPORTED\n",
  820. transferSyntaxName
  821. );
  822. }
  823. continue;
  824. }
  825. if (i == CtxBTFN) // BTFN
  826. {
  827. if (bindResponse->Results[i].AckResult != RPC_BIND_ACK)
  828. {
  829. errorout("\nWarning: BTFN did not respond with RPC_BIND_ACK or RPC_BIND_NACK\n");
  830. }
  831. if (bindResponse->Results[i].AckReason != LE16(3))
  832. {
  833. errorout("\nWarning: BTFN did not return expected feature mask 0x3 but 0x%X\n", (unsigned int)LE16(bindResponse->Results[i].AckReason));
  834. }
  835. if (verbose) printf("... BTFN ");
  836. RpcFlags.HasBTFN = TRUE;
  837. continue;
  838. }
  839. // NDR32 or NDR64 Ctx
  840. if (bindResponse->Results[i].AckResult != RPC_BIND_ACCEPT)
  841. {
  842. errorout(
  843. "\nFatal: transfer syntax %s returned an invalid status, neither RPC_BIND_ACCEPT nor RPC_BIND_NACK\n",
  844. transferSyntaxName
  845. );
  846. status = !0;
  847. }
  848. if (!IsEqualGUID(&bindResponse->Results[i].TransferSyntax, &bindRequest->CtxItems[i].TransferSyntax))
  849. {
  850. errorout(
  851. "\nFatal: Transfer syntax of RPC bind request and response does not match\n"
  852. );
  853. status = !0;
  854. }
  855. if (bindResponse->Results[i].SyntaxVersion != bindRequest->CtxItems[i].SyntaxVersion)
  856. {
  857. errorout("\nFatal: Expected transfer syntax version %u for %s but got %u\n",
  858. (uint32_t)LE32(bindRequest->CtxItems[0].SyntaxVersion),
  859. transferSyntaxName,
  860. (uint32_t)LE32(bindResponse->Results[0].SyntaxVersion)
  861. );
  862. status = !0;
  863. }
  864. // The ack reason field is actually undefined here but Microsoft sets this to 0
  865. if (bindResponse->Results[i].AckReason != 0)
  866. {
  867. errorout(
  868. "\nWarning: Ack reason should be 0 but is %u\n",
  869. LE16(bindResponse->Results[i].AckReason)
  870. );
  871. }
  872. if (!status)
  873. {
  874. if (i == CtxNDR64)
  875. {
  876. RpcFlags.HasNDR64 = TRUE;
  877. if (verbose) printf("... NDR64 ");
  878. }
  879. if (!i)
  880. {
  881. RpcFlags.HasNDR32 = TRUE;
  882. if (verbose) printf("... NDR32 ");
  883. }
  884. }
  885. }
  886. }
  887. free(bindResponseBytePtr);
  888. if (!RpcFlags.HasNDR64 && !RpcFlags.HasNDR32)
  889. {
  890. errorout("\nFatal: Could neither negotiate NDR32 nor NDR64 with the RPC server\n");
  891. status = !0;
  892. }
  893. return status;
  894. }
  895. RpcStatus rpcBindClient(const RpcCtx sock, const int_fast8_t verbose)
  896. {
  897. firstPacketSent = FALSE;
  898. RpcFlags.mask = 0;
  899. RpcStatus status =
  900. rpcBindOrAlterClientContext(sock, RPC_PT_BIND_REQ, verbose);
  901. if (status) return status;
  902. if (!RpcFlags.HasNDR32)
  903. status = rpcBindOrAlterClientContext(sock, RPC_PT_ALTERCONTEXT_REQ, verbose);
  904. return status;
  905. }
  906. #endif // USE_MSRPC