Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1272 lines
38 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. Module Name:
  4. util.c
  5. Abstract:
  6. Various helper and debug functions shared between platforms.
  7. Author:
  8. Mario Goertzel [MarioGo]
  9. Revision History:
  10. MarioGo 95/10/21 Bits 'n pieces
  11. --*/
  12. #include <precomp.hxx>
  13. #include <stdarg.h>
  14. #include <osfpcket.hxx>
  15. #ifdef DEBUGRPC
  16. BOOL ValidateError(
  17. IN unsigned int Status,
  18. IN unsigned int Count,
  19. IN const int ErrorList[])
  20. /*++
  21. Routine Description
  22. Tests that 'Status' is one of an expected set of error codes.
  23. Used on debug builds as part of the VALIDATE() macro.
  24. Example:
  25. VALIDATE(EventStatus)
  26. {
  27. RPC_P_CONNECTION_CLOSED,
  28. RPC_P_RECEIVE_FAILED,
  29. RPC_P_CONNECTION_SHUTDOWN
  30. // more error codes here
  31. } END_VALIDATE;
  32. This function is called with the RpcStatus and expected errors codes
  33. as parameters. If RpcStatus is not one of the expected error
  34. codes and it not zero a message will be printed to the debugger
  35. and the function will return false. The VALIDATE macro ASSERT's the
  36. return value.
  37. Arguments:
  38. Status - Status code in question.
  39. Count - number of variable length arguments
  40. ... - One or more expected status codes. Terminated with 0 (RPC_S_OK).
  41. Return Value:
  42. TRUE - Status code is in the list or the status is 0.
  43. FALSE - Status code is not in the list.
  44. --*/
  45. {
  46. unsigned i;
  47. for (i = 0; i < Count; i++)
  48. {
  49. if (ErrorList[i] == (int) Status)
  50. {
  51. return TRUE;
  52. }
  53. }
  54. PrintToDebugger("RPC Assertion: unexpected failure %lu (0lx%08x)\n",
  55. (unsigned long)Status, (unsigned long)Status);
  56. return(FALSE);
  57. }
  58. #endif // DEBUGRPC
  59. //------------------------------------------------------------------------
  60. #ifdef RPC_ENABLE_WMI_TRACE
  61. #include <wmistr.h>
  62. #include <evntrace.h>
  63. #include "wmlum.h" // private header from clustering
  64. extern "C"
  65. {
  66. DWORD __stdcall
  67. I_RpcEnableWmiTrace(
  68. PWML_TRACE fn,
  69. WMILIB_REG_STRUCT ** pHandle
  70. );
  71. }
  72. typedef DWORD (*WMI_TRACE_FN)();
  73. PWML_TRACE WmiTraceFn = 0;
  74. WMILIB_REG_STRUCT WmiTraceData;
  75. GUID WmiMessageGuid = { /* 41de81c0-aa28-460b-a455-c23809e7c170 */
  76. 0x41de81c0,
  77. 0xaa28,
  78. 0x460b,
  79. {0xa4, 0x55, 0xc2, 0x38, 0x09, 0xe7, 0xc1, 0x70}
  80. };
  81. DWORD __stdcall
  82. I_RpcEnableWmiTrace(
  83. PWML_TRACE fn,
  84. WMILIB_REG_STRUCT ** pHandle
  85. )
  86. {
  87. WmiTraceFn = fn;
  88. *pHandle = &WmiTraceData;
  89. return 0;
  90. }
  91. #endif
  92. BOOL fEnableLog = TRUE;
  93. C_ASSERT(sizeof(LUID) == sizeof(__int64));
  94. struct RPC_EVENT * RpcEvents;
  95. long EventArrayLength = MAX_RPC_EVENT;
  96. long NextEvent = 0;
  97. BOOL DisableEvents = 0;
  98. /*
  99. boolean SubjectExceptions[256];
  100. boolean VerbExceptions[256];
  101. */
  102. #define LOG_VAR( x ) &(x), sizeof(x)
  103. HANDLE hLogFile = 0;
  104. struct RPC_EVENT_LOG
  105. {
  106. DWORD Thread;
  107. union
  108. {
  109. struct
  110. {
  111. unsigned char Subject;
  112. unsigned char Verb;
  113. };
  114. DWORD ZeroSet;
  115. };
  116. void * SubjectPointer;
  117. void * ObjectPointer;
  118. ULONG_PTR Data;
  119. void * EventStackTrace[STACKTRACE_DEPTH];
  120. };
  121. void
  122. TrulyLogEvent(
  123. IN unsigned char Subject,
  124. IN unsigned char Verb,
  125. IN void * SubjectPointer,
  126. IN void * ObjectPointer,
  127. IN ULONG_PTR Data,
  128. IN BOOL fCaptureStackTrace,
  129. IN int AdditionalFramesToSkip
  130. )
  131. {
  132. /*
  133. if (DisableEvents != SubjectExceptions[Subject] ||
  134. DisableEvents != VerbExceptions[Verb])
  135. {
  136. return;
  137. }
  138. */
  139. //
  140. // Allocate the event table if it isn't already there.
  141. //
  142. if (!RpcEvents)
  143. {
  144. struct RPC_EVENT * Temp = (struct RPC_EVENT *) HeapAlloc( GetProcessHeap(),
  145. HEAP_ZERO_MEMORY,
  146. EventArrayLength * sizeof(RPC_EVENT) );
  147. HANDLE LocalFile;
  148. if (!Temp)
  149. {
  150. return;
  151. }
  152. if (InterlockedCompareExchangePointer((void **) &RpcEvents, Temp, 0) != 0)
  153. {
  154. HeapFree(GetProcessHeap(), 0, Temp);
  155. }
  156. /*
  157. if (wcsstr(GetCommandLine(), L"fs.exe") != NULL)
  158. {
  159. LocalFile = CreateFile(L"d:\\rpcclnt.log", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
  160. FILE_ATTRIBUTE_NORMAL, NULL);
  161. if (LocalFile != INVALID_HANDLE_VALUE)
  162. {
  163. hLogFile = LocalFile;
  164. }
  165. else
  166. {
  167. if (hLogFile == 0)
  168. {
  169. DbgPrint("ERROR: Could not create RPC log file: %d\n", GetLastError());
  170. }
  171. // else
  172. // somebody already set it - ignore
  173. }
  174. }
  175. else if (wcsstr(GetCommandLine(), L"fssvr.exe") != NULL)
  176. {
  177. LocalFile = CreateFile(L"d:\\rpcsvr.log", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
  178. FILE_ATTRIBUTE_NORMAL, NULL);
  179. if (LocalFile != INVALID_HANDLE_VALUE)
  180. {
  181. hLogFile = LocalFile;
  182. }
  183. else
  184. {
  185. if (hLogFile == 0)
  186. {
  187. DbgPrint("ERROR: Could not create RPC log file: %d\n", GetLastError());
  188. }
  189. // else
  190. // somebody already set it - ignore
  191. }
  192. }
  193. */
  194. /*
  195. DisableEvents = TRUE;
  196. SubjectExceptions[SU_ADDRESS] = TRUE;
  197. VerbExceptions[EV_CREATE] = TRUE;
  198. VerbExceptions[EV_DELETE] = TRUE;
  199. */
  200. /*
  201. SubjectExceptions[SU_HEAP] = TRUE;
  202. SubjectExceptions[SU_EVENT] = TRUE;
  203. SubjectExceptions[SU_BCACHE] = TRUE;
  204. */
  205. /*
  206. DisableEvents = TRUE;
  207. SubjectExceptions['a'] = TRUE;
  208. SubjectExceptions['g'] = TRUE;
  209. SubjectExceptions['G'] = TRUE;
  210. SubjectExceptions['W'] = TRUE;
  211. SubjectExceptions['X'] = TRUE;
  212. SubjectExceptions['Y'] = TRUE;
  213. SubjectExceptions['Z'] = TRUE;
  214. SubjectExceptions['w'] = TRUE;
  215. SubjectExceptions['x'] = TRUE;
  216. SubjectExceptions['y'] = TRUE;
  217. SubjectExceptions['z'] = TRUE;
  218. VerbExceptions['t'] = TRUE;
  219. VerbExceptions['G'] = TRUE;
  220. VerbExceptions['g'] = TRUE;
  221. VerbExceptions['w'] = TRUE;
  222. VerbExceptions['x'] = TRUE;
  223. VerbExceptions['y'] = TRUE;
  224. VerbExceptions['z'] = TRUE;
  225. VerbExceptions['W'] = TRUE;
  226. VerbExceptions['X'] = TRUE;
  227. VerbExceptions['Y'] = TRUE;
  228. VerbExceptions['Z'] = TRUE;
  229. */
  230. }
  231. unsigned index = InterlockedIncrement(&NextEvent);
  232. index %= EventArrayLength;
  233. RpcEvents[index].Time = GetTickCount();
  234. RpcEvents[index].Verb = Verb;
  235. RpcEvents[index].Subject = Subject;
  236. RpcEvents[index].Thread = (short) GetCurrentThreadId();
  237. RpcEvents[index].SubjectPointer = SubjectPointer;
  238. RpcEvents[index].ObjectPointer = ObjectPointer;
  239. RpcEvents[index].Data = Data;
  240. RpcEvents[index].EventStackTrace[0] = NULL;
  241. RpcEvents[index].EventStackTrace[1] = NULL;
  242. RpcEvents[index].EventStackTrace[2] = NULL;
  243. RpcEvents[index].EventStackTrace[3] = NULL;
  244. CallTestHook( TH_RPC_LOG_EVENT, &RpcEvents[index], 0 );
  245. #ifdef RPC_ENABLE_WMI_TRACE
  246. if (WmiTraceData.EnableFlags)
  247. {
  248. TraceMessage(
  249. WmiTraceData.LoggerHandle,
  250. TRACE_MESSAGE_SEQUENCE | TRACE_MESSAGE_GUID | TRACE_MESSAGE_SYSTEMINFO | TRACE_MESSAGE_TIMESTAMP,
  251. &WmiMessageGuid,
  252. Verb,
  253. LOG_VAR(Subject),
  254. LOG_VAR(SubjectPointer),
  255. LOG_VAR(ObjectPointer),
  256. LOG_VAR(Data),
  257. 0
  258. );
  259. }
  260. #endif
  261. if (fCaptureStackTrace)
  262. {
  263. ULONG ignore;
  264. RtlCaptureStackBackTrace(
  265. 1 + AdditionalFramesToSkip,
  266. STACKTRACE_DEPTH,
  267. (void **) &RpcEvents[index].EventStackTrace,
  268. &ignore);
  269. }
  270. else
  271. {
  272. RpcEvents[index].EventStackTrace[0] = 0;
  273. }
  274. if (hLogFile)
  275. {
  276. DWORD BytesWritten;
  277. /*
  278. RPC_EVENT_LOG logEntry;
  279. RPC_EVENT *CurrentEvent = &RpcEvents[index];
  280. logEntry.Thread = CurrentEvent->Thread;
  281. logEntry.ZeroSet = 0;
  282. logEntry.Subject = CurrentEvent->Subject;
  283. logEntry.Verb = CurrentEvent->Verb;
  284. logEntry.Data = CurrentEvent->Data;
  285. logEntry.ObjectPointer = CurrentEvent->ObjectPointer;
  286. logEntry.SubjectPointer = CurrentEvent->SubjectPointer;
  287. memcpy(logEntry.EventStackTrace, CurrentEvent->EventStackTrace, sizeof(logEntry.EventStackTrace));
  288. WriteFile(hLogFile, &logEntry, sizeof(logEntry), &BytesWritten, NULL);
  289. */
  290. WriteFile(hLogFile, &RpcEvents[index], sizeof(RpcEvents[index]), &BytesWritten, NULL);
  291. }
  292. }
  293. void RPC_ENTRY
  294. I_RpcLogEvent (
  295. IN unsigned char Subject,
  296. IN unsigned char Verb,
  297. IN void * SubjectPointer,
  298. IN void * ObjectPointer,
  299. IN unsigned Data,
  300. IN BOOL fCaptureStackTrace,
  301. IN int AdditionalFramesToSkip
  302. )
  303. {
  304. LogEvent(Subject, Verb, SubjectPointer, ObjectPointer, Data,
  305. fCaptureStackTrace, AdditionalFramesToSkip);
  306. }
  307. #if 0
  308. BOOL
  309. IsLoggingEnabled()
  310. {
  311. RPC_CHAR ModulePath[ MAX_PATH ];
  312. RPC_CHAR * ModuleName;
  313. //
  314. // Find out the .EXE name.
  315. //
  316. if (!GetModuleFileName( NULL, ModulePath, sizeof(ModulePath)))
  317. {
  318. return FALSE;
  319. }
  320. signed i;
  321. for (i=RpcpStringLength(ModulePath)-1; i >= 0; --i)
  322. {
  323. if (ModulePath[i] == '\\')
  324. {
  325. break;
  326. }
  327. }
  328. ModuleName = ModulePath + i + 1;
  329. //
  330. // See whether logging should be enabled.
  331. //
  332. HANDLE hImeo;
  333. HANDLE hMyProcessOptions;
  334. DWORD Error;
  335. DWORD Value;
  336. DWORD Length = sizeof(Value);
  337. DWORD Type;
  338. Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  339. RPC_CONST_STRING("Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"),
  340. 0,
  341. KEY_READ,
  342. &hImeo
  343. );
  344. if (Error)
  345. {
  346. return FALSE;
  347. }
  348. Error = RegOpenKeyEx( hImeo,
  349. ModuleName,
  350. 0,
  351. KEY_READ,
  352. &hMyProcessOptions
  353. );
  354. RegCloseKey( hImeo );
  355. if (Error)
  356. {
  357. return FALSE;
  358. }
  359. Error = RegQueryValueEx( hMyProcessOptions,
  360. RPC_CONST_STRING("Enable RPC Logging"),
  361. 0,
  362. &Type,
  363. &Value,
  364. &Length
  365. );
  366. RegCloseKey( hMyProcessOptions );
  367. if (Error)
  368. {
  369. return FALSE;
  370. }
  371. if (Type == REG_DWORD && Value)
  372. {
  373. return TRUE;
  374. }
  375. if (Type == REG_SZ && 0 == RpcpStringCompare((RPC_CHAR *) Value, RPC_CONST_CHAR('Y')))
  376. {
  377. return TRUE;
  378. }
  379. return FALSE;
  380. }
  381. #endif
  382. extern "C" int __cdecl _purecall(void)
  383. {
  384. #ifdef DEBUGRPC
  385. ASSERT(!"PureVirtualCalled");
  386. #endif
  387. return 0;
  388. }
  389. PUNICODE_STRING
  390. FastGetImageBaseNameUnicodeString (
  391. void
  392. )
  393. /*++
  394. Routine Description
  395. Retrieves the image base name with touching minimal amount of
  396. other memory. Returns a UNICODE_STRING structure.
  397. Arguments:
  398. Return Value:
  399. A pointer to LDR private UNICODE_STRING string with the image name.
  400. Don't write or delete it!
  401. --*/
  402. {
  403. PLIST_ENTRY Module;
  404. PLDR_DATA_TABLE_ENTRY Entry;
  405. Module = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;
  406. Entry = CONTAINING_RECORD(Module,
  407. LDR_DATA_TABLE_ENTRY,
  408. InLoadOrderLinks);
  409. return &(Entry->BaseDllName);
  410. }
  411. const RPC_CHAR *
  412. FastGetImageBaseName (
  413. void
  414. )
  415. /*++
  416. Routine Description
  417. Retrieves the image base name with touching minimal amount of
  418. other memory.
  419. Arguments:
  420. Return Value:
  421. A pointer to LDR private string with the image name. Don't write or
  422. delete it!
  423. --*/
  424. {
  425. return (FastGetImageBaseNameUnicodeString())->Buffer;
  426. }
  427. //
  428. // RPC Verifier utility functions
  429. //
  430. unsigned int
  431. RndInteger (
  432. void
  433. )
  434. /*++
  435. Routine Description:
  436. A private fast implementation of a congruential random
  437. number generator. We do not really care about its being
  438. "good" and use the results for fault injeciton.
  439. Return Value:
  440. A "random" integer between 0 and UINT_MAX
  441. --*/
  442. {
  443. static BOOL fInit;
  444. static unsigned short nCalls;
  445. static unsigned long seed;
  446. RPC_STATUS Status;
  447. if (fInit == false || nCalls > 1000)
  448. {
  449. fInit = true;
  450. nCalls = 0;
  451. // Get a seed as a "true" random number.
  452. Status = GenerateRandomNumber((unsigned char *)&seed, sizeof(unsigned long));
  453. if (Status != RPC_S_OK)
  454. {
  455. // On failure, still try to get some entropy.
  456. ASSERT(Status == RPC_S_OUT_OF_MEMORY);
  457. seed = GetTickCount();
  458. }
  459. }
  460. // Use a simple Pi-enspired congruence f-la.
  461. seed = 3141592653 * seed + 2718281829;
  462. VERIFIER_DBG_PRINT_1("RndInteger() returned 0x%x\n", seed);
  463. return seed;
  464. }
  465. inline BOOL
  466. RndBool(
  467. unsigned int Prob
  468. )
  469. /*++
  470. Routine Description:
  471. Generates a boolean with probability of True Prob/10000
  472. Return Value:
  473. A boolean with the given probability of truth
  474. --*/
  475. {
  476. BOOL ret = RndInteger() < Prob*(0xffffffff/10000);
  477. VERIFIER_DBG_PRINT_1("RndBool() returned %d\n", ret);
  478. return (ret);
  479. }
  480. // Rounding of an unsigned float.
  481. #define URound(f) (unsigned int)(f+0.5)
  482. inline unsigned int RndIntegerInRange(
  483. unsigned int min,
  484. unsigned int max
  485. )
  486. /*++
  487. Routine Description:
  488. Returns a random integer from min to max.
  489. The distribution of the possible value is uniform.
  490. Return Value:
  491. A random integer within a given range
  492. --*/
  493. {
  494. unsigned int ret = min + URound( (float)(max-min) * ((float)RndInteger() / (float)0xffffffff) );
  495. VERIFIER_DBG_PRINT_3("RndIntegerInRange(0x%x, 0x%x) returned 0x%x\n", min, max, ret);
  496. return (ret);
  497. }
  498. #define BitFlip(arg,pos) ((arg) ^ (1L << (pos)))
  499. inline void
  500. RndBitFlip(
  501. unsigned char *addr,
  502. unsigned int len
  503. )
  504. /*++
  505. Routine Description:
  506. Flips one bit in each of len bytes starting at addr
  507. Return Value:
  508. None
  509. --*/
  510. {
  511. for (unsigned int d = 0; d<len; d++)
  512. {
  513. unsigned char bit = (unsigned char)RndIntegerInRange(1,8);
  514. VERIFIER_DBG_PRINT_2("RndBitFlip() flipping bit %u at address 0x%x\n", bit, &(addr[d]));
  515. addr[d] = BitFlip(addr[d], bit);
  516. }
  517. }
  518. inline void
  519. RndIncDec(
  520. unsigned char *addr,
  521. unsigned int len
  522. )
  523. /*++
  524. Routine Description:
  525. Flips one bit in each of len bytes starting at addr
  526. Return Value:
  527. None
  528. --*/
  529. {
  530. for (unsigned int d = 0; d<len; d++)
  531. {
  532. if (RndBool(5000))
  533. {
  534. addr[d]++;
  535. VERIFIER_DBG_PRINT_1("RndIncDec() inc byte at address 0x%x\n", &(addr[d]));
  536. }
  537. else
  538. {
  539. addr[d]--;
  540. VERIFIER_DBG_PRINT_1("RndIncDec() dec byte at address 0x%x\n", &(addr[d]));
  541. }
  542. }
  543. }
  544. void
  545. CorruptBuffer(
  546. unsigned int BufferLength,
  547. unsigned char *Buffer
  548. )
  549. /*++
  550. Routine Description:
  551. Corrupts the buffer in accordance with the RPC verifier settings.
  552. Return Value:
  553. none
  554. --*/
  555. {
  556. unsigned int Size;
  557. unsigned int Start;
  558. VERIFIER_DBG_PRINT_2("CorruptBuffer() length=%d buffer=0x%x\n",
  559. BufferLength, Buffer);
  560. // Determine the size of the corruption.
  561. if (pRpcVerifierSettings->CorruptionSizeType == FixedSize)
  562. {
  563. Size = pRpcVerifierSettings->CorruptionSize;
  564. }
  565. else if (pRpcVerifierSettings->CorruptionSizeType == RandomSize)
  566. {
  567. Size = RndIntegerInRange(1, min(pRpcVerifierSettings->CorruptionSize,BufferLength));
  568. }
  569. else
  570. {
  571. ASSERT(0 && "Unexpected CorruptionSizeType\n");
  572. }
  573. // Determine the start of the corruption.
  574. Start = RndIntegerInRange(0, BufferLength-Size);
  575. VERIFIER_DBG_PRINT_2("CorruptBuffer() Size=%d Start=%d\n",
  576. Size, Start);
  577. if (pRpcVerifierSettings->CorruptionPattern == ZeroOut)
  578. {
  579. // For localized corruption, zero out random block of size Size.
  580. if (pRpcVerifierSettings->CorruptionDistributionType == LocalizedDistribution)
  581. {
  582. RtlZeroMemory((PVOID)(Buffer+Start), Size);
  583. }
  584. // For randomized corruption, zero out Size random bytes from the buffer.
  585. else
  586. {
  587. for (unsigned int i=0; i<Size; i++)
  588. {
  589. Buffer[RndIntegerInRange(0, BufferLength-1)] = 0;
  590. }
  591. }
  592. }
  593. else if (pRpcVerifierSettings->CorruptionPattern == Negate)
  594. {
  595. // For localized corruption, negate random block of size Size.
  596. if (pRpcVerifierSettings->CorruptionDistributionType == LocalizedDistribution)
  597. {
  598. for (unsigned int i = 0; i<Size; i++)
  599. {
  600. Buffer[Start+i] = 0xff;
  601. }
  602. }
  603. // For randomized corruption, negate Size random bytes from the buffer.
  604. else
  605. {
  606. for (unsigned int i=0; i<Size; i++)
  607. {
  608. Buffer[RndIntegerInRange(0, BufferLength-1)] = 0xff;
  609. }
  610. }
  611. }
  612. else if (pRpcVerifierSettings->CorruptionPattern == BitFlip)
  613. {
  614. // For localized corruption, flip bits on Size consecutive bytes.
  615. if (pRpcVerifierSettings->CorruptionDistributionType == LocalizedDistribution)
  616. {
  617. RndBitFlip(Buffer+Start, Size);
  618. }
  619. // For randomized corruption, flip random bits in Size bytes all over the buffer.
  620. else
  621. {
  622. for (unsigned int i=0; i<Size; i++)
  623. {
  624. RndBitFlip(Buffer + RndIntegerInRange(0, BufferLength-1),1);
  625. }
  626. }
  627. }
  628. else if (pRpcVerifierSettings->CorruptionPattern == IncDec)
  629. {
  630. // For localized corruption, increment or decrement Size consecutive bytes.
  631. if (pRpcVerifierSettings->CorruptionDistributionType == LocalizedDistribution)
  632. {
  633. RndIncDec(Buffer+Start, Size);
  634. }
  635. // For randomized corruption, inc/dec Size bytes all over the buffer.
  636. else
  637. {
  638. for (unsigned int i=0; i<Size; i++)
  639. {
  640. RndIncDec(Buffer + RndIntegerInRange(0, BufferLength-1),1);
  641. }
  642. }
  643. }
  644. else if (pRpcVerifierSettings->CorruptionPattern == Randomize)
  645. {
  646. // For localized corruption distribution, randomize block of size Size.
  647. if (pRpcVerifierSettings->CorruptionDistributionType == LocalizedDistribution)
  648. {
  649. for (unsigned int i = 0; i<Size; i++)
  650. {
  651. Buffer[Start+i] = (unsigned char) RndInteger();
  652. }
  653. }
  654. // For randomized corruption distribution, randomize Size bytes all over the buffer.
  655. else
  656. {
  657. for (unsigned int i=0; i<Size; i++)
  658. {
  659. Buffer[RndIntegerInRange(0, BufferLength-1)] = (unsigned char) RndInteger();
  660. }
  661. }
  662. }
  663. else if (pRpcVerifierSettings->CorruptionPattern == AllPatterns)
  664. {
  665. // Choose a random pattern of corrupion only for the duration of this call.
  666. // This may affect other corruptions taking place, but it's OK since the overal
  667. // bahavior is correct.
  668. pRpcVerifierSettings->CorruptionPattern = (tCorruptionPattern)RndIntegerInRange(MIN_CORRUPTION_PATTERN_ID,
  669. MAX_CORRUPTION_PATTERN_ID);
  670. CorruptBuffer(BufferLength, Buffer);
  671. pRpcVerifierSettings->CorruptionPattern = AllPatterns;
  672. }
  673. else
  674. {
  675. ASSERT(0 && "Unexpected CorruptionPattern\n");
  676. }
  677. }
  678. void
  679. CorruptionInject(
  680. tBufferType BufferType,
  681. unsigned int *pBufferLength,
  682. void **pBuffer
  683. )
  684. /*++
  685. Routine Description:
  686. Injects corruption into a buffer if necesssary.
  687. Injection is done according to the RPC verifier settings for this buffer type.
  688. Return Value:
  689. none
  690. --*/
  691. {
  692. BOOL fSecure = false;
  693. void *Buffer = *pBuffer;
  694. unsigned int BufferLength = *pBufferLength;
  695. VERIFIER_DBG_PRINT_3("CorruptionInject() type=%d length=%d buffer=0x%x\n",
  696. BufferType, *pBufferLength, *pBuffer);
  697. // Check if there is a buffer to corrupt and if
  698. // this type of buffer should have corruption injected into it.
  699. if (*pBuffer
  700. && ((BufferType == ServerReceive && pRpcVerifierSettings->fCorruptionInjectServerReceives) ||
  701. (BufferType == ClientReceive && pRpcVerifierSettings->fCorruptionInjectClientReceives)))
  702. {
  703. // If yes, corrupt the buffer if necessary.
  704. // First, we will try to truncate the buffer.
  705. if (pRpcVerifierSettings->ProbBufferTruncation &&
  706. RndBool(pRpcVerifierSettings->ProbBufferTruncation))
  707. {
  708. VERIFIER_DBG_PRINT_0("CorruptionInject() - truncating the buffer\n");
  709. // We truncate OSF buffers only. The scenario is not interesting
  710. // for DG. The way we can tell the difference between the two types of packets
  711. // is by the header.
  712. // For OSF the packet header will look like:
  713. // rpcconn_common
  714. // +0x000 rpc_vers : 5
  715. // +0x001 rpc_vers_minor : 0
  716. // For DG it will be:
  717. // NCA_PACKET_HEADER
  718. // +0x000 RpcVersion : 0x4
  719. // +0x001 PacketType : 0
  720. // So we just want the first 2 bytes to be 5,0.
  721. if (BufferLength >= sizeof(rpcconn_common) &&
  722. ((unsigned short)*((unsigned char*)Buffer + 0x0) == 5 &&
  723. (unsigned short)*((unsigned char*)Buffer + 0x1) == 0
  724. )
  725. )
  726. {
  727. unsigned short NewBufferLength = BufferLength - RndIntegerInRange(1, pRpcVerifierSettings->MaxBufferTruncationSize);
  728. NewBufferLength = max(NewBufferLength, sizeof(rpcconn_common));
  729. // We have a connection-oriented buffer - truncate it.
  730. I_RpcTransConnectionReallocPacket(
  731. NULL, // The connection argument is ignored by the realloc routine.
  732. pBuffer,
  733. *pBufferLength,
  734. NewBufferLength);
  735. VERIFIER_DBG_PRINT_3("CorruptionInject() - truncated buffer 0x%x from 0x%x to 0x%x\n",
  736. *pBuffer,
  737. *pBufferLength,
  738. NewBufferLength);
  739. // Update the buffer size so that the right value is seen by the caller.
  740. Buffer = *pBuffer;
  741. *pBufferLength = NewBufferLength;
  742. BufferLength = NewBufferLength;
  743. // Adjust the frag_length so that it is equal to the new packetlength.
  744. // We need to do this since the runtime relies on these being in agreement and the
  745. // transports guarantee it.
  746. *((unsigned int*)((unsigned char*)Buffer + 0x8)) = BufferLength;
  747. }
  748. }
  749. // After the buffer has been truncated, we may corrupt it.
  750. // Check if we can corrupt the RPC header section.
  751. if (RndBool(pRpcVerifierSettings->ProbRpcHeaderCorruption))
  752. {
  753. // Corrupt it if we can.
  754. CorruptBuffer(
  755. min(sizeof(rpcconn_common),BufferLength), // This will mostly whack the common RPC header.
  756. (unsigned char *)Buffer);
  757. }
  758. //
  759. // Determine whether this is a secure buffer.
  760. // The way we tell is by looking for the signature of rpcconn_common.auth_length != 0.
  761. // We will query this field directly, using the following offsets:
  762. //
  763. // rpcconn_common
  764. // +0x000 rpc_vers : UChar
  765. // ...
  766. // +0x008 frag_length : Uint2B
  767. // +0x00a auth_length : Uint2B
  768. // +0x00c call_id : Uint4B
  769. //
  770. // This may falsely count some packets as secure occasionally,
  771. // say in the case of fragmentation, but we can take this downside and the benefits of
  772. // a compact check outweigh it.
  773. //
  774. fSecure = ( (BufferLength > sizeof(rpcconn_common)) &&
  775. ((unsigned short)*((unsigned char*)Buffer + 0xa) != 0) );
  776. VERIFIER_DBG_PRINT_1("CorruptionInject() fSecure=%d\n", fSecure);
  777. // Check if we can corrupt the Data section.
  778. if ((!fSecure && RndBool(pRpcVerifierSettings->ProbDataCorruption)) ||
  779. (fSecure && RndBool(pRpcVerifierSettings->ProbSecureDataCorruption)))
  780. {
  781. // Corrupt it if we can.
  782. CorruptBuffer(
  783. BufferLength,
  784. (unsigned char *)Buffer);
  785. }
  786. }
  787. }
  788. #define MAX_STACK_TRACE 8
  789. PVOID LastEventStackTrace[MAX_STACK_TRACE];
  790. void
  791. PrintCurrentStackTrace(
  792. unsigned int FramesToSkip,
  793. unsigned int Size
  794. )
  795. /*++
  796. Routine Description:
  797. Prints a stack trace of Size frames after the first FramesToSkip frames.
  798. Only the addresses are printed since there is no way to get to the
  799. symbolic information from here.
  800. Return Value:
  801. none
  802. --*/
  803. {
  804. Size = min (Size, MAX_STACK_TRACE);
  805. PVOID *EventStackTrace = (PVOID *)alloca(Size*sizeof(PVOID));
  806. // Capture and print the stack trace.
  807. RtlCaptureStackBackTrace(FramesToSkip,
  808. Size,
  809. EventStackTrace,
  810. NULL);
  811. for (unsigned int i=0; i<Size; i++)
  812. {
  813. DbgPrint("\t0x%x\n", EventStackTrace[i]);
  814. }
  815. // To simplify debugging, save the local stack trace into a global variable.
  816. memcpy(LastEventStackTrace, EventStackTrace, Size*sizeof(PVOID));
  817. }
  818. void
  819. PrintUUID(
  820. GUID *Uuid
  821. )
  822. /*++
  823. Routine Description:
  824. Prints a UUID
  825. Return Value:
  826. none
  827. --*/
  828. {
  829. unsigned long *Data = (unsigned long *)Uuid;
  830. if ((Data[0] == 0) &&
  831. (Data[1] == 0) &&
  832. (Data[2] == 0) &&
  833. (Data[3] == 0))
  834. {
  835. DbgPrint("(Null Uuid)");
  836. }
  837. else
  838. {
  839. DbgPrint("%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  840. Uuid->Data1, Uuid->Data2, Uuid->Data3, Uuid->Data4[0], Uuid->Data4[1],
  841. Uuid->Data4[2], Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5],
  842. Uuid->Data4[6], Uuid->Data4[7] );
  843. }
  844. }
  845. //
  846. // Per-interface security check exemption settings.
  847. //
  848. // The structure mapping an interface onto a flag.
  849. // An array of these defines interfaces exempt from some of the rpc verifier checks.
  850. typedef struct _tRpcVerifierIfExemption
  851. {
  852. GUID IfUuid; // An interface UUID.
  853. DWORD ExemptionFlags; // Which security checks are to be disabled.
  854. } tRpcVerifierIfExemption;
  855. //
  856. // This is a list of interface UUID's exempt from some or all checks.
  857. // We match the interfaces by their syntax GUIDs.
  858. //
  859. const tRpcVerifierIfExemption RpcVerifierExemptInterfaces[] = {
  860. // 000001A0-0000-0000-C000-000000000046
  861. // ok to be remotely accessible, not secured, clear text traffic and no mutual authentication.
  862. {{0x000001A0, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}, ALLOW_EVERYTHING},
  863. // 12345678-1234-ABCD-EF00-01234567CFFB
  864. // Netlogon implements its own authentication protocol via the NetrServerReqChallenge
  865. // and NetrServerAuthenticate3 rpc calls. These rpc calls happen without packet privacy and result
  866. // in the servers being mutually authenticated and a key exchange between client and server.
  867. // After that all calls use privacy via the netlogon package.
  868. {{0x12345678, 0x1234, 0xABCD, {0xEF, 0x00, 0x01, 0x23, 0x45, 0x67, 0xCF, 0xFB}}, ALLOW_NO_MUTUAL_AUTH_REMOTE_ACCESS|ALLOW_UNENCRYPTED_REMOTE_ACCESS},
  869. // 338cd001-2244-31f1-aaaa-900038001003
  870. // ok to be remotely accessible, not secured. It uses an access check in the server routine instead
  871. // of a callback because it must support downlevel clients which used native named pipes transport security.
  872. {{0x338cd001, 0x2244, 0x31f1, {0xaa, 0xaa, 0x90, 0x00, 0x38, 0x00, 0x10, 0x03}}, ALLOW_EVERYTHING},
  873. // 4d9f4ab8-7d1c-11cf-861e-0020af6e7c57
  874. // ok to be remotely accessible, not secured, clear text traffic and no mutual authentication.
  875. {{0x4d9f4ab8, 0x7d1c, 0x11cf, {0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57}}, ALLOW_EVERYTHING},
  876. // 99fcfec4-5260-101b-bbcb-00aa0021347a
  877. // ok to be remotely accessible, not secured, clear text traffic and no mutual authentication.
  878. {{0x99fcfec4, 0x5260, 0x101b, {0xbb, 0xcb, 0x00, 0xaa, 0x00, 0x21, 0x34, 0x7a}}, ALLOW_EVERYTHING},
  879. // e1af8308-5d1f-11c9-91a4-08002b14a0fa
  880. // ok to be remotely accessible, not secured, clear text traffic and no mutual authentication.
  881. {{0xe1af8308, 0x5d1f, 0x11c9, {0x91, 0xa4, 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa}}, ALLOW_EVERYTHING},
  882. // e60c73e6-88f9-11cf-9af1-0020af6e72f4
  883. // ok to be remotely accessible, not secured, clear text traffic and no mutual authentication.
  884. {{0xe60c73e6, 0x88f9, 0x11cf, {0x9a, 0xf1, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4}}, ALLOW_EVERYTHING},
  885. // We make all of the locator interfaces exempt. There will be a message
  886. // on locator start-up giving a warning for the service as a whole.
  887. // Also, the locator server manager routines will be protected in the user code.
  888. // e33c0cc4-0482-101a-bc0c-02608c6ba218 - LocToLoc
  889. {{0xe33c0cc4, 0x0482, 0x101a, {0xbc, 0x0c, 0x02, 0x60, 0x8c, 0x6b, 0xa2, 0x18}}, ALLOW_EVERYTHING},
  890. // d3fbb514-0e3b-11cb-8fad-08002b1d29c3 - NsiC
  891. {{0xd3fbb514, 0x0e3b, 0x11cb, {0x8f, 0xad, 0x08, 0x00, 0x2b, 0x1d, 0x29, 0xc3}}, ALLOW_EVERYTHING},
  892. // d6d70ef0-0e3b-11cb-acc3-08002b1d29c4 - NsiM
  893. {{0xd6d70ef0, 0x0e3b, 0x11cb, {0xac, 0xc3, 0x08, 0x00, 0x2b, 0x1d, 0x29, 0xc4}}, ALLOW_EVERYTHING},
  894. // d6d70ef0-0e3b-11cb-acc3-08002b1d29c3 - NsiS
  895. {{0xd6d70ef0, 0x0e3b, 0x11cb, {0xac, 0xc3, 0x08, 0x00, 0x2b, 0x1d, 0x29, 0xc3}}, ALLOW_EVERYTHING},
  896. // The following lsa and sam interfaces are secure in virtue of using a well-known
  897. // endpoint and relying on the transport np security.
  898. // They can't use RPC security because of backward compatibility.
  899. // 12345778-1234-ABCD-EF00-0123456789AC - SAM
  900. {{0x12345778, 0x1234, 0xABCD, {0xEF, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAC}}, ALLOW_EVERYTHING},
  901. // 12345778-1234-ABCD-EF00-0123456789AB - LSA
  902. {{0x12345778, 0x1234, 0xABCD, {0xEF, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB}}, ALLOW_EVERYTHING},
  903. // 3919286a-b10c-11d0-9ba8-00c04fd92ef5 - dsrole.
  904. {{0x3919286a, 0xb10c, 0x11d0, {0x9b, 0xa8, 0x00, 0xc0, 0x4f, 0xd9, 0x2e, 0xf5}}, ALLOW_EVERYTHING},
  905. // The DFS interface can't use RPC security because of the compatibility considerations.
  906. // 4fc742e0-4a10-11cf-8273-00aa004ae673 - DFS
  907. {{0x4fc742e0, 0x4a10, 0x11cf, {0x82, 0x73, 0x00, 0xaa, 0x00, 0x4a, 0xe6, 0x73}}, ALLOW_EVERYTHING},
  908. // The licensing server is listening on the following interface.
  909. // This is a temp fix to be removed after .NET RC1 after which point the underlying bug will be fixed.
  910. // 2f59a331-bf7d-48cb-9e5c-7c090d76e8b8
  911. {{0x2f59a331, 0xbf7d, 0x48cb, {0x9e, 0x5c, 0x7c, 0x09, 0x0d, 0x76, 0xe8, 0xb8}}, ALLOW_EVERYTHING},
  912. // srvsvc.dll has backwards compatibility reasons preventing it from using encryption.
  913. // 4B324FC8-1670-01D3-1278-5A47BF6EE188
  914. {{0x4B324FC8, 0x1670, 0x01D3, {0x12, 0x78, 0x5A, 0x47, 0xBF, 0x6E, 0xE1, 0x88}}, ALLOW_UNENCRYPTED_REMOTE_ACCESS},
  915. // EFS has backwards compatibility considerations and were not able to fix the code on time.
  916. // c681d488-d850-11d0-8c52-00c04fd90f7e
  917. {{0xc681d488, 0xd850, 0x11d0, {0x8c, 0x52, 0x00, 0xc0, 0x4f, 0xd9, 0x0f, 0x7e}}, ALLOW_EVERYTHING}
  918. };
  919. BOOL
  920. IsInterfaceExempt (
  921. IN GUID *IfUuid,
  922. IN DWORD CheckFlag
  923. )
  924. /*++
  925. Function Name: IsInterfaceExempt
  926. Parameters:
  927. If - A UUID for the interface for which we want to look-up the exemption.
  928. CheckFlag - Flag for the check being tested for exemption.
  929. Description:
  930. Verifies whether an interface is exempt from a particular security check.
  931. Returns:
  932. TRUE - If an interface is exempt from a given check.
  933. FALSE - Otherwise.
  934. --*/
  935. {
  936. // Go through all exempt interfaces.
  937. for (int i=0; i<sizeof(RpcVerifierExemptInterfaces)/sizeof(tRpcVerifierIfExemption); i++)
  938. {
  939. // Check if one of them matches the provided UUID.
  940. if (RpcpMemoryCompare(&(RpcVerifierExemptInterfaces[i].IfUuid), IfUuid, sizeof(UUID)) == 0)
  941. {
  942. // If it does, check whether the exemption is enabled for the flag being queried.
  943. if (RpcVerifierExemptInterfaces[i].ExemptionFlags & CheckFlag)
  944. {
  945. return true;
  946. }
  947. else
  948. {
  949. return false;
  950. }
  951. }
  952. }
  953. // If we could not find the interface then it is not exempt from the check.
  954. return false;
  955. }
  956. //
  957. // Unsafe protseqs detection.
  958. //
  959. // List of protocol sequences that are not actively used and are unsafe as a result.
  960. const RPC_CHAR *RpcVerifierUnsafeProtseqs[] = {
  961. RPC_CONST_STRING("ncadg_ip_udp"),
  962. RPC_CONST_STRING("ncacn_spx"),
  963. RPC_CONST_STRING("ncacn_at_dsp")
  964. };
  965. BOOL
  966. IsProtseqUnsafe (
  967. IN RPC_CHAR *ProtocolSequence
  968. )
  969. /*++
  970. Function Name: IsProtseqUnsafe
  971. Parameters:
  972. ProtocolSequence - A string specifying the protseq to be checked for safety.
  973. Description:
  974. Verifies whether a protseq is one of the rarely used and unsafe ones.
  975. Returns:
  976. TRUE - The protseq specified is unsafe.
  977. FALSE - Otherwise.
  978. --*/
  979. {
  980. // Go through all the unsafe protseqs.
  981. for (int i=0; i<sizeof(RpcVerifierUnsafeProtseqs)/sizeof(const RPC_CHAR *); i++)
  982. {
  983. // Check if one of them matches the provided protocol.
  984. if (RpcpStringNCompare(RpcVerifierUnsafeProtseqs[i],
  985. ProtocolSequence,
  986. RpcpStringLength(RpcVerifierUnsafeProtseqs[i])) == 0)
  987. {
  988. return true;
  989. }
  990. }
  991. // If none match, the protseq is safe.
  992. return false;
  993. }
  994. //
  995. // Security-related utility functions
  996. //
  997. RPC_STATUS
  998. IsCurrentUserAdmin(
  999. void
  1000. )
  1001. /*++
  1002. Routine Description:
  1003. Checks if the current thread's or process' token is that of an admin.
  1004. Return Value:
  1005. RPC_S_OK - if the token is that of an admin.
  1006. RPC_S_ACESS_DENIED - the user is not an admin or a failure occurred.
  1007. --*/
  1008. {
  1009. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  1010. PSID psidAdministrators = NULL;
  1011. BOOL b;
  1012. RPC_STATUS Status = RPC_S_OK;
  1013. BOOL fIsMember = false;
  1014. b = AllocateAndInitializeSid(
  1015. &siaNtAuthority,
  1016. 2,
  1017. SECURITY_BUILTIN_DOMAIN_RID,
  1018. DOMAIN_ALIAS_RID_ADMINS,
  1019. 0, 0, 0, 0, 0, 0,
  1020. &psidAdministrators
  1021. );
  1022. if(b)
  1023. {
  1024. // When TokenHandle is NULL, CheckTokenMembership uses
  1025. // the impersonation token of the calling thread.
  1026. // If the thread is not impersonating, the function duplicates
  1027. // the thread's primary token to create an impersonation token.
  1028. b = CheckTokenMembership(NULL, psidAdministrators, &fIsMember);
  1029. // Token is not that of an admin or token membership could
  1030. // not be verified.
  1031. if(!b || !fIsMember)
  1032. {
  1033. Status = RPC_S_ACCESS_DENIED;
  1034. }
  1035. }
  1036. // We could not allocate a SID.
  1037. else
  1038. {
  1039. Status = RPC_S_OUT_OF_MEMORY;
  1040. }
  1041. if(psidAdministrators)
  1042. FreeSid(psidAdministrators);
  1043. return Status;
  1044. }
  1045. const SID LocalSystem = { 1, 1, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID};
  1046. const SID LocalService = { 1, 1, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SERVICE_RID};
  1047. const SID NetworkService = { 1, 1, SECURITY_NT_AUTHORITY, SECURITY_NETWORK_SERVICE_RID};
  1048. const RPC_SID2 Admin1 = { 1, 2, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS};