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.

3419 lines
93 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1990 - 1999
  6. //
  7. // File: handle.cxx
  8. //
  9. //--------------------------------------------------------------------------
  10. /* --------------------------------------------------------------------
  11. Microsoft OS/2 LAN Manager
  12. Copyright(c) Microsoft Corp., 1990
  13. -------------------------------------------------------------------- */
  14. /* --------------------------------------------------------------------
  15. File: handle.cxx
  16. Description:
  17. The actual code for all of the classes specified by handle.hxx is
  18. contained in this file. These routines are independent of the actual RPC
  19. protocol / transport layer. In addition, these routines are also
  20. independent of the specific operating system in use.
  21. History :
  22. mikemon ??-??-?? First bit in the bucket.
  23. mikemon 12-28-90 Cleaned up the comments.
  24. Kamen Moutafov (KamenM) Dec 99 - Feb 2000 - Support for cell debugging stuff
  25. -------------------------------------------------------------------- */
  26. #include <precomp.hxx>
  27. #include <epmap.h>
  28. #include <rpccfg.h>
  29. #include <dispatch.h>
  30. #include <crypt.h>
  31. #include <charconv.hxx>
  32. #include <lmcons.h>
  33. #include <ntlsa.h>
  34. #include <lmerr.h>
  35. #include <secobj.h>
  36. #undef UNUSED // netlib also defined UNUSED, but doesn't protect it with #ifndef
  37. // Undef it here so that netlib compiles
  38. #include <netlib.h>
  39. extern unsigned DefaultMaxDatagramLength = DEFAULT_MAX_DATAGRAM_LENGTH;
  40. extern unsigned DefaultConnectionBufferLength = DEFAULT_CONNECTION_BUFFER_LENGTH;
  41. /*
  42. A helper routine to capture the logon ID of this thread, if it is
  43. impersonating another process.
  44. Routine returns RPC_S_OK on success. If the process is not impersonating,
  45. but running under its own process identity, this routine will fail.
  46. All failures, currently, get treated as if the thread is not impersonating
  47. */
  48. RPC_STATUS
  49. GetTokenStats(TOKEN_STATISTICS *pTokenStats)
  50. {
  51. BOOL Result;
  52. HANDLE Handle;
  53. unsigned long Size;
  54. Result = OpenThreadToken(
  55. GetCurrentThread(),
  56. TOKEN_READ,
  57. TRUE,
  58. &Handle
  59. );
  60. if (Result != TRUE)
  61. {
  62. return (GetLastError());
  63. }
  64. Result = GetTokenInformation(
  65. Handle,
  66. TokenStatistics,
  67. pTokenStats,
  68. sizeof(TOKEN_STATISTICS),
  69. &Size
  70. );
  71. CloseHandle(Handle);
  72. if (Result != TRUE)
  73. {
  74. return (GetLastError());
  75. }
  76. return RPC_S_OK;
  77. }
  78. RPC_STATUS
  79. CaptureModifiedId(
  80. LUID * ModifiedId
  81. )
  82. {
  83. TOKEN_STATISTICS TokenStatisticsInformation;
  84. RPC_STATUS Status;
  85. Status = GetTokenStats(&TokenStatisticsInformation);
  86. if (Status != RPC_S_OK)
  87. {
  88. return Status;
  89. }
  90. RpcpMemoryCopy(ModifiedId,
  91. &TokenStatisticsInformation.ModifiedId, sizeof(LUID));
  92. return (RPC_S_OK);
  93. }
  94. void WipeOutAuthIdentity (
  95. IN SEC_WINNT_AUTH_IDENTITY_W *AuthIdentity
  96. )
  97. /*++
  98. Routine Description:
  99. Wipes out the important parts of an auth identity structure.
  100. Works on encrypted and decrypted identities.
  101. Arguments:
  102. AuthIdentity - the auth identity to wipe out.
  103. Return Value:
  104. --*/
  105. {
  106. if (AuthIdentity == NULL)
  107. return;
  108. if (AuthIdentity->User != NULL)
  109. {
  110. RpcpMemorySet(AuthIdentity->User, 0, AuthIdentity->UserLength * sizeof(RPC_CHAR));
  111. }
  112. if (AuthIdentity->Domain != NULL)
  113. {
  114. RpcpMemorySet(AuthIdentity->Domain, 0, AuthIdentity->DomainLength * sizeof(RPC_CHAR));
  115. }
  116. if (AuthIdentity->Password != NULL)
  117. {
  118. RpcpMemorySet(AuthIdentity->Password, 0, AuthIdentity->PasswordLength * sizeof(RPC_CHAR));
  119. }
  120. }
  121. // if RTL_ENCRYPT_MEMORY_SIZE gets changed, the padding logic below
  122. // must get changed also
  123. C_ASSERT(RTL_ENCRYPT_MEMORY_SIZE == 8);
  124. RPC_CHAR *
  125. ReallocAndPad8IfNeccessary (
  126. IN RPC_CHAR *OldBuffer,
  127. IN OUT ULONG *Length
  128. )
  129. /*++
  130. Routine Description:
  131. Encrypts the important parts of an auth identity structure.
  132. On success, if reallocation was done, the old buffer is deleted.
  133. Arguments:
  134. OldBuffer - the old, unpadded buffer
  135. Length - on input, the length of the old unpadded buffer in characters without
  136. the terminating null. On output the length of the encrypted buffer with
  137. padding. Unmodified on failure.
  138. Return Value:
  139. The new buffer (may be the same as the old) or NULL if there is
  140. insufficient memory.
  141. --*/
  142. {
  143. ULONG NewLength;
  144. ULONG InputLength = *Length;
  145. RPC_CHAR *NewBuffer;
  146. NewLength = Align8(InputLength);
  147. if (NewLength == InputLength)
  148. {
  149. *Length = NewLength;
  150. return OldBuffer;
  151. }
  152. NewBuffer = new RPC_CHAR[NewLength + 1];
  153. if (NewBuffer == NULL)
  154. return NULL;
  155. RpcpMemoryCopy(NewBuffer, OldBuffer, (InputLength + 1) * sizeof(RPC_CHAR));
  156. // wipe out the old buffer before freeing it
  157. RpcpMemorySet(OldBuffer, 0, (InputLength + 1) * sizeof(RPC_CHAR));
  158. delete [] OldBuffer;
  159. *Length = NewLength;
  160. return NewBuffer;
  161. }
  162. RPC_STATUS EncryptAuthIdentity (
  163. IN SEC_WINNT_AUTH_IDENTITY_W *AuthIdentity
  164. )
  165. /*++
  166. Routine Description:
  167. Encrypts the important parts of an auth identity structure.
  168. Arguments:
  169. AuthIdentity - the auth identity to encrypt.
  170. Return Value:
  171. RPC_S_OK or RPC_S_* error
  172. --*/
  173. {
  174. RPC_STATUS RpcStatus;
  175. NTSTATUS NtStatus;
  176. if (AuthIdentity->User != NULL)
  177. {
  178. AuthIdentity->User = ReallocAndPad8IfNeccessary(AuthIdentity->User,
  179. &AuthIdentity->UserLength
  180. );
  181. if (AuthIdentity->User == NULL)
  182. {
  183. WipeOutAuthIdentity(AuthIdentity);
  184. return RPC_S_OUT_OF_MEMORY;
  185. }
  186. NtStatus = RtlEncryptMemory(AuthIdentity->User,
  187. AuthIdentity->UserLength * sizeof(RPC_CHAR),
  188. 0);
  189. if (!NT_SUCCESS(NtStatus))
  190. {
  191. ASSERT(NtStatus != STATUS_INVALID_PARAMETER);
  192. WipeOutAuthIdentity(AuthIdentity);
  193. return RPC_S_OUT_OF_MEMORY;
  194. }
  195. }
  196. if (AuthIdentity->Domain != NULL)
  197. {
  198. AuthIdentity->Domain = ReallocAndPad8IfNeccessary(AuthIdentity->Domain,
  199. &AuthIdentity->DomainLength
  200. );
  201. if (AuthIdentity->Domain == NULL)
  202. {
  203. WipeOutAuthIdentity(AuthIdentity);
  204. return RPC_S_OUT_OF_MEMORY;
  205. }
  206. NtStatus = RtlEncryptMemory(AuthIdentity->Domain,
  207. AuthIdentity->DomainLength * sizeof(RPC_CHAR),
  208. 0);
  209. if (!NT_SUCCESS(NtStatus))
  210. {
  211. ASSERT(NtStatus != STATUS_INVALID_PARAMETER);
  212. WipeOutAuthIdentity(AuthIdentity);
  213. return RPC_S_OUT_OF_MEMORY;
  214. }
  215. }
  216. if (AuthIdentity->Password != NULL)
  217. {
  218. AuthIdentity->Password = ReallocAndPad8IfNeccessary(AuthIdentity->Password,
  219. &AuthIdentity->PasswordLength
  220. );
  221. if (AuthIdentity->Password == NULL)
  222. {
  223. WipeOutAuthIdentity(AuthIdentity);
  224. return RPC_S_OUT_OF_MEMORY;
  225. }
  226. NtStatus = RtlEncryptMemory(AuthIdentity->Password,
  227. AuthIdentity->PasswordLength * sizeof(RPC_CHAR),
  228. 0);
  229. if (!NT_SUCCESS(NtStatus))
  230. {
  231. ASSERT(NtStatus != STATUS_INVALID_PARAMETER);
  232. WipeOutAuthIdentity(AuthIdentity);
  233. return RPC_S_OUT_OF_MEMORY;
  234. }
  235. }
  236. return RPC_S_OK;
  237. }
  238. RPC_STATUS DecryptAuthIdentity (
  239. IN SEC_WINNT_AUTH_IDENTITY_W *AuthIdentity
  240. )
  241. /*++
  242. Routine Description:
  243. Decrypts the important parts of an auth identity structure.
  244. If decryption fails half way through, the auth identity will
  245. be wiped out.
  246. Arguments:
  247. AuthIdentity - the auth identity to decrypt.
  248. Return Value:
  249. RPC_S_OK or RPC_S_* error
  250. --*/
  251. {
  252. RPC_STATUS RpcStatus;
  253. NTSTATUS NtStatus;
  254. if (AuthIdentity->User != NULL)
  255. {
  256. NtStatus = RtlDecryptMemory(AuthIdentity->User,
  257. AuthIdentity->UserLength * sizeof(RPC_CHAR),
  258. 0);
  259. if (!NT_SUCCESS(NtStatus))
  260. {
  261. WipeOutAuthIdentity(AuthIdentity);
  262. return RPC_S_OUT_OF_MEMORY;
  263. }
  264. AuthIdentity->UserLength = RpcpStringLength(AuthIdentity->User);
  265. }
  266. if (AuthIdentity->Domain != NULL)
  267. {
  268. NtStatus = RtlDecryptMemory(AuthIdentity->Domain,
  269. AuthIdentity->DomainLength * sizeof(RPC_CHAR),
  270. 0);
  271. if (!NT_SUCCESS(NtStatus))
  272. {
  273. WipeOutAuthIdentity(AuthIdentity);
  274. return RPC_S_OUT_OF_MEMORY;
  275. }
  276. AuthIdentity->DomainLength = RpcpStringLength(AuthIdentity->Domain);
  277. }
  278. if (AuthIdentity->Password != NULL)
  279. {
  280. NtStatus = RtlDecryptMemory(AuthIdentity->Password,
  281. AuthIdentity->PasswordLength * sizeof(RPC_CHAR),
  282. 0);
  283. if (!NT_SUCCESS(NtStatus))
  284. {
  285. WipeOutAuthIdentity(AuthIdentity);
  286. return RPC_S_OUT_OF_MEMORY;
  287. }
  288. AuthIdentity->PasswordLength = RpcpStringLength(AuthIdentity->Password);
  289. }
  290. return RPC_S_OK;
  291. }
  292. void FreeAuthIdentity (
  293. IN SEC_WINNT_AUTH_IDENTITY_W *AuthIdentity
  294. )
  295. /*++
  296. Routine Description:
  297. Frees an auth identity structure.
  298. Arguments:
  299. AuthIdentity - the auth identity to free.
  300. Return Value:
  301. Notes:
  302. Does not wipe out the auth identity! It must
  303. have been wiped out by the caller.
  304. --*/
  305. {
  306. if (AuthIdentity->User != NULL)
  307. {
  308. delete [] AuthIdentity->User;
  309. AuthIdentity->User = NULL;
  310. }
  311. if (AuthIdentity->Domain != NULL)
  312. {
  313. delete [] AuthIdentity->Domain;
  314. AuthIdentity->Domain = NULL;
  315. }
  316. if (AuthIdentity->Password != NULL)
  317. {
  318. delete [] AuthIdentity->Password;
  319. AuthIdentity->Password = NULL;
  320. }
  321. delete AuthIdentity;
  322. }
  323. SEC_WINNT_AUTH_IDENTITY_W *DuplicateAuthIdentity (
  324. IN SEC_WINNT_AUTH_IDENTITY_W *AuthIdentity
  325. )
  326. /*++
  327. Routine Description:
  328. Duplicates an auth identity structure. It works on both
  329. encrypted and decrypted auth identity.
  330. Arguments:
  331. AuthIdentity - the auth identity to copy from.
  332. Return Value:
  333. Duplicated auth identity of NULL for failure
  334. --*/
  335. {
  336. SEC_WINNT_AUTH_IDENTITY_W *NewAuthIdentity;
  337. NewAuthIdentity = new SEC_WINNT_AUTH_IDENTITY_W;
  338. if (NewAuthIdentity == NULL)
  339. return NULL;
  340. RpcpMemoryCopy(NewAuthIdentity, AuthIdentity, sizeof(SEC_WINNT_AUTH_IDENTITY_W));
  341. NewAuthIdentity->User = NULL;
  342. NewAuthIdentity->Domain = NULL;
  343. NewAuthIdentity->Password = NULL;
  344. if (AuthIdentity->User)
  345. {
  346. NewAuthIdentity->User = new RPC_CHAR [AuthIdentity->UserLength + 1];
  347. if (NewAuthIdentity->User == NULL)
  348. {
  349. FreeAuthIdentity(NewAuthIdentity);
  350. return NULL;
  351. }
  352. RpcpMemoryCopy(NewAuthIdentity->User,
  353. AuthIdentity->User,
  354. (AuthIdentity->UserLength + 1) * sizeof(RPC_CHAR));
  355. }
  356. if (AuthIdentity->Domain)
  357. {
  358. NewAuthIdentity->Domain = new RPC_CHAR [AuthIdentity->DomainLength + 1];
  359. if (NewAuthIdentity->Domain == NULL)
  360. {
  361. WipeOutAuthIdentity(NewAuthIdentity);
  362. FreeAuthIdentity(NewAuthIdentity);
  363. return NULL;
  364. }
  365. RpcpMemoryCopy(NewAuthIdentity->Domain,
  366. AuthIdentity->Domain,
  367. (AuthIdentity->DomainLength + 1) * sizeof(RPC_CHAR));
  368. }
  369. if (AuthIdentity->Password)
  370. {
  371. NewAuthIdentity->Password = new RPC_CHAR [AuthIdentity->PasswordLength + 1];
  372. if (NewAuthIdentity->Password == NULL)
  373. {
  374. WipeOutAuthIdentity(NewAuthIdentity);
  375. FreeAuthIdentity(NewAuthIdentity);
  376. return NULL;
  377. }
  378. RpcpMemoryCopy(NewAuthIdentity->Password,
  379. AuthIdentity->Password,
  380. (AuthIdentity->PasswordLength + 1) * sizeof(RPC_CHAR));
  381. }
  382. return NewAuthIdentity;
  383. }
  384. int CompareAuthIdentity (
  385. IN SEC_WINNT_AUTH_IDENTITY_W *AuthIdentity1,
  386. IN SEC_WINNT_AUTH_IDENTITY_W *AuthIdentity2
  387. )
  388. /*++
  389. Routine Description:
  390. Compares 2 auth identity structures. Works on both
  391. encrypted and decrypted auth identities?
  392. Arguments:
  393. AuthIdentity1 - first auth identity structure
  394. AuthIdentity2 - second auth identity structure
  395. Return Value:
  396. 0 if they are equal. non-zero otherwise.
  397. --*/
  398. {
  399. if (AuthIdentity1 == NULL)
  400. return (AuthIdentity2 != NULL);
  401. else if (AuthIdentity2 == NULL)
  402. return 1;
  403. if (AuthIdentity1->Flags != AuthIdentity2->Flags)
  404. return 1;
  405. if (AuthIdentity1->User)
  406. {
  407. if (AuthIdentity2->User == NULL)
  408. return 1;
  409. if (AuthIdentity1->UserLength != AuthIdentity2->UserLength)
  410. return 1;
  411. if (RpcpMemoryCompare(AuthIdentity1->User,
  412. AuthIdentity2->User,
  413. AuthIdentity1->UserLength * sizeof(RPC_CHAR)) != 0)
  414. return 1;
  415. }
  416. else if (AuthIdentity2->User != NULL)
  417. return 1;
  418. if (AuthIdentity1->Domain)
  419. {
  420. if (AuthIdentity2->Domain == NULL)
  421. return 1;
  422. if (AuthIdentity1->DomainLength != AuthIdentity2->DomainLength)
  423. return 1;
  424. if (RpcpMemoryCompare(AuthIdentity1->Domain,
  425. AuthIdentity2->Domain,
  426. AuthIdentity1->DomainLength * sizeof(RPC_CHAR)) != 0)
  427. return 1;
  428. }
  429. else if (AuthIdentity2->Domain != NULL)
  430. return 1;
  431. if (AuthIdentity1->Password)
  432. {
  433. if (AuthIdentity2->Password == NULL)
  434. return 1;
  435. if (AuthIdentity1->PasswordLength != AuthIdentity2->PasswordLength)
  436. return 1;
  437. if (RpcpMemoryCompare(AuthIdentity1->Password,
  438. AuthIdentity2->Password,
  439. AuthIdentity1->PasswordLength * sizeof(RPC_CHAR)) != 0)
  440. return 1;
  441. }
  442. else if (AuthIdentity2->Password != NULL)
  443. return 1;
  444. return 0;
  445. }
  446. SEC_WINNT_AUTH_IDENTITY_W *ConvertAuthIdentity (
  447. IN SEC_WINNT_AUTH_IDENTITY_A *AuthIdentity
  448. )
  449. /*++
  450. Routine Description:
  451. Converts an auth identity structure.
  452. Conversion is done on a separate copy.
  453. Arguments:
  454. AuthIdentity - the auth identity to convert.
  455. Return Value:
  456. Pointer to duplicated/converted auth identity. If failure,
  457. NULL.
  458. --*/
  459. {
  460. SEC_WINNT_AUTH_IDENTITY_W *NewAuthIdentity;
  461. ASSERT(AuthIdentity->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI);
  462. NewAuthIdentity = new SEC_WINNT_AUTH_IDENTITY_W;
  463. if (NewAuthIdentity == NULL)
  464. return NULL;
  465. RpcpMemoryCopy(NewAuthIdentity, AuthIdentity, sizeof(SEC_WINNT_AUTH_IDENTITY_W));
  466. NewAuthIdentity->User = NULL;
  467. NewAuthIdentity->Domain = NULL;
  468. NewAuthIdentity->Password = NULL;
  469. NewAuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  470. if (AuthIdentity->User)
  471. {
  472. NewAuthIdentity->User = new RPC_CHAR [AuthIdentity->UserLength + 1];
  473. if (NewAuthIdentity->User == NULL)
  474. {
  475. FreeAuthIdentity(NewAuthIdentity);
  476. return NULL;
  477. }
  478. FullAnsiToUnicode((char *)AuthIdentity->User, NewAuthIdentity->User);
  479. }
  480. if (AuthIdentity->Domain)
  481. {
  482. NewAuthIdentity->Domain = new RPC_CHAR [AuthIdentity->DomainLength + 1];
  483. if (NewAuthIdentity->Domain == NULL)
  484. {
  485. WipeOutAuthIdentity(NewAuthIdentity);
  486. FreeAuthIdentity(NewAuthIdentity);
  487. return NULL;
  488. }
  489. FullAnsiToUnicode((char *)AuthIdentity->Domain, NewAuthIdentity->Domain);
  490. }
  491. if (AuthIdentity->Password)
  492. {
  493. NewAuthIdentity->Password = new RPC_CHAR [AuthIdentity->PasswordLength + 1];
  494. if (NewAuthIdentity->Password == NULL)
  495. {
  496. WipeOutAuthIdentity(NewAuthIdentity);
  497. FreeAuthIdentity(NewAuthIdentity);
  498. return NULL;
  499. }
  500. FullAnsiToUnicode((char *)AuthIdentity->Password, NewAuthIdentity->Password);
  501. }
  502. return NewAuthIdentity;
  503. }
  504. void FreeHttpTransportCredentials (
  505. IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *Credentials
  506. )
  507. /*++
  508. Routine Description:
  509. Duplicates Http transport credentials.
  510. Arguments:
  511. Credentials - the credentials to free.
  512. Return Value:
  513. --*/
  514. {
  515. if (Credentials->AuthnSchemes != NULL)
  516. {
  517. delete [] Credentials->AuthnSchemes;
  518. Credentials->AuthnSchemes = NULL;
  519. }
  520. if (Credentials->ServerCertificateSubject != NULL)
  521. {
  522. delete [] Credentials->ServerCertificateSubject;
  523. Credentials->ServerCertificateSubject = NULL;
  524. }
  525. if (Credentials->TransportCredentials != NULL)
  526. {
  527. FreeAuthIdentity(Credentials->TransportCredentials);
  528. Credentials->TransportCredentials = NULL;
  529. }
  530. }
  531. RPC_HTTP_TRANSPORT_CREDENTIALS_W *DuplicateHttpTransportCredentials (
  532. const IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *SourceCredentials
  533. )
  534. /*++
  535. Routine Description:
  536. Duplicates Http transport credentials.
  537. Arguments:
  538. SourceCredentials - the credentials to duplicate.
  539. Return Value:
  540. Duplicated credentials or NULL if there was not enough memory.
  541. --*/
  542. {
  543. RPC_HTTP_TRANSPORT_CREDENTIALS_W *NewCredentials;
  544. NewCredentials = new RPC_HTTP_TRANSPORT_CREDENTIALS_W;
  545. if (NewCredentials == NULL)
  546. return NewCredentials;
  547. NewCredentials->Flags = SourceCredentials->Flags;
  548. NewCredentials->AuthenticationTarget = SourceCredentials->AuthenticationTarget;
  549. NewCredentials->NumberOfAuthnSchemes = SourceCredentials->NumberOfAuthnSchemes;
  550. NewCredentials->AuthnSchemes = NULL;
  551. NewCredentials->ServerCertificateSubject = NULL;
  552. NewCredentials->TransportCredentials = NULL;
  553. if (SourceCredentials->AuthnSchemes)
  554. {
  555. NewCredentials->AuthnSchemes = new ULONG [SourceCredentials->NumberOfAuthnSchemes];
  556. if (NewCredentials->AuthnSchemes == NULL)
  557. {
  558. FreeHttpTransportCredentials(NewCredentials);
  559. return NULL;
  560. }
  561. RpcpMemoryCopy(NewCredentials->AuthnSchemes,
  562. SourceCredentials->AuthnSchemes,
  563. SourceCredentials->NumberOfAuthnSchemes * sizeof(ULONG)
  564. );
  565. }
  566. if (SourceCredentials->ServerCertificateSubject)
  567. {
  568. NewCredentials->ServerCertificateSubject
  569. = DuplicateString(SourceCredentials->ServerCertificateSubject);
  570. if (NewCredentials->ServerCertificateSubject == NULL)
  571. {
  572. FreeHttpTransportCredentials(NewCredentials);
  573. return NULL;
  574. }
  575. }
  576. if (SourceCredentials->TransportCredentials)
  577. {
  578. NewCredentials->TransportCredentials
  579. = DuplicateAuthIdentity(SourceCredentials->TransportCredentials);
  580. if (NewCredentials->TransportCredentials == NULL)
  581. {
  582. FreeHttpTransportCredentials(NewCredentials);
  583. return NULL;
  584. }
  585. }
  586. return NewCredentials;
  587. }
  588. int CompareHttpTransportCredentials (
  589. const IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *Credentials1,
  590. const IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *Credentials2
  591. )
  592. /*++
  593. Routine Description:
  594. Compares Http transport credentials.
  595. Arguments:
  596. Credentials1 - first set of credentials
  597. Credentials2 - second set of credentials
  598. Return Value:
  599. 0 if they are equal or non-zero if they are different
  600. --*/
  601. {
  602. if (Credentials1->Flags != Credentials2->Flags)
  603. return 1;
  604. if (Credentials1->AuthenticationTarget != Credentials2->AuthenticationTarget)
  605. return 1;
  606. if (Credentials1->NumberOfAuthnSchemes != Credentials2->NumberOfAuthnSchemes)
  607. return 1;
  608. if (Credentials1->AuthnSchemes != NULL)
  609. {
  610. if (RpcpMemoryCompare(Credentials1->AuthnSchemes,
  611. Credentials2->AuthnSchemes,
  612. Credentials1->NumberOfAuthnSchemes) != 0)
  613. {
  614. return 1;
  615. }
  616. }
  617. else if (Credentials1->AuthnSchemes != NULL)
  618. return 1;
  619. if (Credentials1->ServerCertificateSubject != NULL)
  620. {
  621. if (RpcpStringCompare(Credentials1->ServerCertificateSubject,
  622. Credentials2->ServerCertificateSubject) != 0)
  623. {
  624. return 1;
  625. }
  626. }
  627. else if (Credentials1->ServerCertificateSubject != NULL)
  628. return 1;
  629. return CompareAuthIdentity(Credentials1->TransportCredentials, Credentials2->TransportCredentials);
  630. }
  631. RPC_HTTP_TRANSPORT_CREDENTIALS_W *ConvertToUnicodeHttpTransportCredentials (
  632. const IN RPC_HTTP_TRANSPORT_CREDENTIALS_A *SourceCredentials
  633. )
  634. /*++
  635. Routine Description:
  636. Converts Http transport credentials from ANSI to Unicode.
  637. Conversion is done on a separate copy.
  638. Arguments:
  639. SourceCredentials - the credentials to convert.
  640. Return Value:
  641. Pointer to duplicated/converted credentials. If failure,
  642. NULL.
  643. --*/
  644. {
  645. RPC_HTTP_TRANSPORT_CREDENTIALS_W *NewCredentials;
  646. ULONG Length;
  647. NewCredentials = new RPC_HTTP_TRANSPORT_CREDENTIALS_W;
  648. if (NewCredentials == NULL)
  649. return NewCredentials;
  650. NewCredentials->Flags = SourceCredentials->Flags;
  651. NewCredentials->AuthenticationTarget = SourceCredentials->AuthenticationTarget;
  652. NewCredentials->NumberOfAuthnSchemes = SourceCredentials->NumberOfAuthnSchemes;
  653. NewCredentials->AuthnSchemes = NULL;
  654. NewCredentials->ServerCertificateSubject = NULL;
  655. NewCredentials->TransportCredentials = NULL;
  656. if (SourceCredentials->AuthnSchemes)
  657. {
  658. NewCredentials->AuthnSchemes = new ULONG [SourceCredentials->NumberOfAuthnSchemes];
  659. if (NewCredentials->AuthnSchemes == NULL)
  660. {
  661. FreeHttpTransportCredentials(NewCredentials);
  662. return NULL;
  663. }
  664. RpcpMemoryCopy(NewCredentials->AuthnSchemes,
  665. SourceCredentials->AuthnSchemes,
  666. SourceCredentials->NumberOfAuthnSchemes * sizeof(ULONG)
  667. );
  668. }
  669. if (SourceCredentials->ServerCertificateSubject)
  670. {
  671. Length = RpcpStringLengthA((const char *)SourceCredentials->ServerCertificateSubject) + 1;
  672. NewCredentials->ServerCertificateSubject = new RPC_CHAR[Length];
  673. if (NewCredentials->ServerCertificateSubject == NULL)
  674. {
  675. FreeHttpTransportCredentials(NewCredentials);
  676. return NULL;
  677. }
  678. FullAnsiToUnicode((char *)SourceCredentials->ServerCertificateSubject,
  679. NewCredentials->ServerCertificateSubject);
  680. }
  681. if (SourceCredentials->TransportCredentials)
  682. {
  683. NewCredentials->TransportCredentials
  684. = ConvertAuthIdentity(SourceCredentials->TransportCredentials);
  685. if (NewCredentials->TransportCredentials == NULL)
  686. {
  687. FreeHttpTransportCredentials(NewCredentials);
  688. return NULL;
  689. }
  690. }
  691. return NewCredentials;
  692. }
  693. RPC_HTTP_TRANSPORT_CREDENTIALS_W *
  694. I_RpcTransGetHttpCredentials (
  695. const IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *SourceCredentials
  696. )
  697. /*++
  698. Routine Description:
  699. Takes runtime encrypted credentials and returns a duplicate,
  700. decrypted credentials.
  701. Arguments:
  702. SourceCredentials - the encrypted runtime credentials given to the
  703. transport during Open.
  704. Return Value:
  705. Pointer to duplicated/converted credentials. If failure,
  706. NULL.
  707. --*/
  708. {
  709. RPC_HTTP_TRANSPORT_CREDENTIALS_W *NewCredentials;
  710. RPC_STATUS RpcStatus;
  711. NewCredentials = DuplicateHttpTransportCredentials(SourceCredentials);
  712. if (NewCredentials && NewCredentials->TransportCredentials)
  713. {
  714. RpcStatus = DecryptAuthIdentity(NewCredentials->TransportCredentials);
  715. if (RpcStatus != RPC_S_OK)
  716. {
  717. // if Decrypt fails, it will wipe out the auth identity
  718. FreeHttpTransportCredentials(NewCredentials);
  719. NewCredentials = NULL;
  720. }
  721. // the credentials are not encrypted anymore
  722. NewCredentials->Flags &= ~RPC_C_HTTP_FLAG_AUTH_IDENTITY_ENCRYPTED;
  723. }
  724. return NewCredentials;
  725. }
  726. void I_RpcTransFreeHttpCredentials (
  727. IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *SourceCredentials
  728. )
  729. /*++
  730. Routine Description:
  731. Frees credentials obtained by the transport through
  732. I_RpcTransGetHttpCredentials.
  733. Arguments:
  734. SourceCredentials - the credentials to free.
  735. Return Value:
  736. --*/
  737. {
  738. ASSERT(SourceCredentials);
  739. WipeOutAuthIdentity(SourceCredentials->TransportCredentials);
  740. FreeHttpTransportCredentials(SourceCredentials);
  741. }
  742. /* ====================================================================
  743. GENERIC_OBJECT
  744. ==================================================================== */
  745. /* --------------------------------------------------------------------
  746. This routine validates a handle. The HandleType argument is a set of
  747. flags specifying the valid handle types. Note that the handle types
  748. defined in handle.hxx are flags rather than being enumerated.
  749. -------------------------------------------------------------------- */
  750. unsigned int
  751. GENERIC_OBJECT::InvalidHandle ( // Validate a handle.
  752. IN HANDLE_TYPE BaseType
  753. )
  754. {
  755. // Checking for a 0 handle should work for all operating environments. Where
  756. // we can (such as on NT), we should check for readable and writeable memory.
  757. if (this == 0)
  758. {
  759. return(1);
  760. }
  761. // Check the magic long. This allows us to catch stale handles and handles
  762. // which are just passed in as arbitray pointers into memory. It does not
  763. // handle the case of copying the contents of a handle.
  764. if (MagicLong != MAGICLONG)
  765. {
  766. return(1);
  767. }
  768. //
  769. // Finally, check that the type of handle is one of the allowed ones
  770. // specified by the HandleType argument. Remember that the call to Type
  771. // is a virtual method which each type of handle will implement.
  772. //
  773. if (ObjectType & BaseType)
  774. {
  775. return 0;
  776. }
  777. return(1);
  778. }
  779. RPC_STATUS
  780. MESSAGE_OBJECT::BindingCopy (
  781. OUT BINDING_HANDLE * PAPI * DestinationBinding,
  782. IN unsigned int MaintainContext
  783. )
  784. {
  785. UNUSED(this);
  786. UNUSED(DestinationBinding);
  787. UNUSED(MaintainContext);
  788. ASSERT( 0 );
  789. return(RPC_S_INTERNAL_ERROR);
  790. }
  791. void
  792. CLIENT_AUTH_INFO::ReferenceCredentials() const
  793. {
  794. if (Credentials != 0)
  795. {
  796. Credentials->ReferenceCredentials();
  797. }
  798. }
  799. int
  800. CLIENT_AUTH_INFO::CredentialsMatch(
  801. SECURITY_CREDENTIALS PAPI * SuppliedCredentials
  802. ) const
  803. {
  804. return(Credentials->CompareCredentials(SuppliedCredentials) == 0);
  805. }
  806. CLIENT_AUTH_INFO::CLIENT_AUTH_INFO(
  807. const CLIENT_AUTH_INFO * SourceAuthInfo,
  808. RPC_STATUS __RPC_FAR * pStatus
  809. )
  810. {
  811. if (SourceAuthInfo)
  812. {
  813. *this = *SourceAuthInfo;
  814. if (SourceAuthInfo->ServerSid)
  815. {
  816. PSID NewSid;
  817. NewSid = DuplicateSID (SourceAuthInfo->ServerSid);
  818. ServerSid = NewSid;
  819. if (0 == NewSid)
  820. {
  821. *pStatus = RPC_S_OUT_OF_MEMORY;
  822. }
  823. }
  824. if (SourceAuthInfo->ServerPrincipalName)
  825. {
  826. RPC_CHAR * NewString;
  827. NewString = DuplicateString(SourceAuthInfo->ServerPrincipalName);
  828. ServerPrincipalName = NewString;
  829. if (0 == NewString)
  830. {
  831. *pStatus = RPC_S_OUT_OF_MEMORY;
  832. }
  833. }
  834. ASSERT((AdditionalTransportCredentialsType == RPC_C_AUTHN_INFO_TYPE_HTTP)
  835. || (AdditionalTransportCredentialsType == 0));
  836. if (SourceAuthInfo->AdditionalTransportCredentialsType == RPC_C_AUTHN_INFO_TYPE_HTTP)
  837. {
  838. ASSERT(SourceAuthInfo->AdditionalCredentials != NULL);
  839. AdditionalCredentials = DuplicateHttpTransportCredentials(
  840. (const RPC_HTTP_TRANSPORT_CREDENTIALS_W *)SourceAuthInfo->AdditionalCredentials);
  841. if (AdditionalCredentials == NULL)
  842. {
  843. *pStatus = RPC_S_OUT_OF_MEMORY;
  844. }
  845. }
  846. SourceAuthInfo->ReferenceCredentials();
  847. }
  848. else
  849. {
  850. AuthenticationLevel = RPC_C_AUTHN_LEVEL_NONE;
  851. AuthenticationService = RPC_C_AUTHN_NONE;
  852. AuthorizationService = RPC_C_AUTHZ_NONE;
  853. ServerPrincipalName = 0;
  854. AuthIdentity = 0;
  855. Credentials = 0;
  856. ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
  857. IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
  858. Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
  859. DefaultLogonId = 1;
  860. AdditionalTransportCredentialsType = 0;
  861. AdditionalCredentials = NULL;
  862. ServerSid = NULL;
  863. }
  864. }
  865. CLIENT_AUTH_INFO::~CLIENT_AUTH_INFO(
  866. )
  867. {
  868. delete ServerPrincipalName;
  869. delete [] ServerSid;
  870. if (Credentials)
  871. {
  872. Credentials->DereferenceCredentials();
  873. }
  874. ASSERT((AdditionalTransportCredentialsType == RPC_C_AUTHN_INFO_TYPE_HTTP)
  875. || (AdditionalTransportCredentialsType == 0));
  876. if (AdditionalTransportCredentialsType == RPC_C_AUTHN_INFO_TYPE_HTTP)
  877. {
  878. ASSERT(AdditionalCredentials != NULL);
  879. FreeHttpTransportCredentials((RPC_HTTP_TRANSPORT_CREDENTIALS_W *)AdditionalCredentials);
  880. AdditionalCredentials = NULL;
  881. }
  882. }
  883. RPC_STATUS
  884. CLIENT_AUTH_INFO::IsSupportedAuthInfo (
  885. IN const CLIENT_AUTH_INFO * ClientAuthInfo,
  886. IN NamedPipeType NPType,
  887. IN BOOL IsExclusiveConnection,
  888. OUT BOOL *Supported
  889. ) const
  890. /*++
  891. Arguments:
  892. ClientAuthInfo - Supplies the authentication and authorization information
  893. required of this connection. A value of zero (the pointer is
  894. zero) indicates that we want an unauthenticated connection.
  895. NPType - the type of transport w.r.t. to named pipes. See the definition
  896. of NamedPipeType for description of the bitmasks
  897. IsExclusiveConnection - if NPType is not named pipe, this parameter is ignored.
  898. Otherwise non-zero means the connection is exclusive. Zero means the
  899. connection is non-exclusive.
  900. Supported - on output, non-zero if the auth info is supported, zero otherwise.
  901. Undefined on failure.
  902. Return Value:
  903. RPC_S_OK or RPC_S_* error
  904. --*/
  905. {
  906. if ( ClientAuthInfo == 0 )
  907. {
  908. *Supported = (AuthenticationLevel == RPC_C_AUTHN_LEVEL_NONE);
  909. return RPC_S_OK;
  910. }
  911. // presume failure for now
  912. *Supported = FALSE;
  913. if ( ClientAuthInfo->AuthenticationService != AuthenticationService )
  914. {
  915. return RPC_S_OK;
  916. }
  917. if (ClientAuthInfo->AuthenticationService == RPC_C_AUTHN_NONE)
  918. {
  919. // if this is a named pipe, and it is either remote, or static, or non-exclusive
  920. // we must match the identity. For full description of the named pipe
  921. // transport logic, see the comment in the NPType member in OSF_BINDING_HANDLE
  922. if (IsNamedPipe(NPType)
  923. &&
  924. (
  925. (IsStaticNamedPipe(NPType))
  926. ||
  927. (IsRemoteNamedPipe(NPType))
  928. ||
  929. (IsExclusiveConnection == FALSE)
  930. ) )
  931. {
  932. if ((ClientAuthInfo->DefaultLogonId != DefaultLogonId)
  933. || ((ClientAuthInfo->DefaultLogonId == FALSE)
  934. && (!FastCompareLUIDAligned(&ClientAuthInfo->ModifiedId, &ModifiedId))))
  935. {
  936. return RPC_S_OK;
  937. }
  938. }
  939. if (ClientAuthInfo->ServerSid && ServerSid)
  940. *Supported = EqualSid (ClientAuthInfo->ServerSid, ServerSid);
  941. else
  942. *Supported = TRUE;
  943. return RPC_S_OK;
  944. }
  945. if ( ClientAuthInfo->AuthenticationLevel
  946. != AuthenticationLevel )
  947. {
  948. return RPC_S_OK;
  949. }
  950. if ( ClientAuthInfo->AuthorizationService != AuthorizationService )
  951. {
  952. return RPC_S_OK;
  953. }
  954. if (CredentialsMatch(ClientAuthInfo->Credentials) == 0)
  955. {
  956. //Credentials Dont Match
  957. return RPC_S_OK;
  958. }
  959. if ( ClientAuthInfo->ImpersonationType != ImpersonationType )
  960. {
  961. return RPC_S_OK;
  962. }
  963. if ( (ClientAuthInfo->IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC)
  964. && (IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC)
  965. && (
  966. (ClientAuthInfo->DefaultLogonId != DefaultLogonId)
  967. || (
  968. (ClientAuthInfo->DefaultLogonId == FALSE)
  969. && (!FastCompareLUIDAligned(&ClientAuthInfo->ModifiedId, &ModifiedId))
  970. )
  971. )
  972. || (ClientAuthInfo->IdentityTracking != IdentityTracking) )
  973. {
  974. return RPC_S_OK;
  975. }
  976. if ( (ClientAuthInfo->Capabilities != Capabilities)
  977. &&(ClientAuthInfo->Capabilities != RPC_C_QOS_CAPABILITIES_DEFAULT) )
  978. {
  979. return RPC_S_OK;
  980. }
  981. ASSERT((AdditionalTransportCredentialsType == RPC_C_AUTHN_INFO_TYPE_HTTP)
  982. || (AdditionalTransportCredentialsType == 0));
  983. if (AdditionalTransportCredentialsType == RPC_C_AUTHN_INFO_TYPE_HTTP)
  984. {
  985. if (CompareHttpTransportCredentials((RPC_HTTP_TRANSPORT_CREDENTIALS_W *)AdditionalCredentials,
  986. (RPC_HTTP_TRANSPORT_CREDENTIALS_W *)ClientAuthInfo->AdditionalCredentials) != 0)
  987. {
  988. return RPC_S_OK;
  989. }
  990. }
  991. // if the SPN and SID are equal, this is supported
  992. return CompareSPNAndSID (ClientAuthInfo, Supported);
  993. }
  994. RPC_STATUS
  995. CLIENT_AUTH_INFO::CompareSPNAndSID (
  996. IN const CLIENT_AUTH_INFO *AuthInfo,
  997. OUT BOOL *Equal
  998. ) const
  999. /*++
  1000. Routine Description:
  1001. Compares the SPN and SID of two auth info classes
  1002. and determines whether they are equal
  1003. Arguments:
  1004. AuthInfo - the second class to compare to.
  1005. Equal - on output, if non-zero, they are equal. If zero,
  1006. they are not equal. Undefined on failure.
  1007. Return Value:
  1008. RPC_S_OK or RPC_S_* error
  1009. --*/
  1010. {
  1011. PSID Sid;
  1012. RPC_STATUS RpcStatus;
  1013. // Bypass the cache for all comparisons
  1014. BOOL fCachedSid = FALSE;
  1015. // the table of relationships b/n SID and SPN is as follows:
  1016. // Case This: AuthInfo:
  1017. // SPN SID SPN SID
  1018. // 1 0 0 0 0
  1019. // 2 0 0 0 1
  1020. // 3 0 0 1 0
  1021. // 4 0 0 1 1
  1022. // 5 0 1 0 0
  1023. // 6 0 1 0 1
  1024. // 7 0 1 1 0
  1025. // 8 0 1 1 1
  1026. // 9 1 0 0 0
  1027. // 10 1 0 0 1
  1028. // 11 1 0 1 0
  1029. // 12 1 0 1 1
  1030. // 13 1 1 0 0
  1031. // 14 1 1 0 1
  1032. // 15 1 1 1 0
  1033. // 16 1 1 1 1
  1034. // cases 6, 8, 14, 16
  1035. if (AuthInfo->ServerSid && ServerSid)
  1036. {
  1037. // sid comparison is final and authoritative
  1038. *Equal = EqualSid (AuthInfo->ServerSid, ServerSid);
  1039. return RPC_S_OK;
  1040. }
  1041. // cases 11, 12, 15
  1042. if (AuthInfo->ServerPrincipalName && ServerPrincipalName)
  1043. {
  1044. *Equal = !RpcpStringCompare(AuthInfo->ServerPrincipalName,
  1045. ServerPrincipalName);
  1046. return RPC_S_OK;
  1047. }
  1048. // if both SPNs are not present, the SIDs matter. Cases 1, 2, 5
  1049. if ( (AuthInfo->ServerPrincipalName == 0)
  1050. && (ServerPrincipalName == 0) )
  1051. {
  1052. // we know we can't have both SIDs here. At least one of them is NULL
  1053. *Equal = (AuthInfo->ServerSid == ServerSid);
  1054. return RPC_S_OK;
  1055. }
  1056. // if both SIDs are not present, the SPNs matter. Cases 3 and 9
  1057. if ( (AuthInfo->ServerSid == 0)
  1058. && (ServerSid == 0) )
  1059. {
  1060. // we know we can't have both SPNs here. At least one of them is NULL
  1061. *Equal = (AuthInfo->ServerPrincipalName == ServerPrincipalName);
  1062. return RPC_S_OK;
  1063. }
  1064. // here either one has both, and the other neither, or they are criss-crossed
  1065. // case 4
  1066. if (AuthInfo->ServerPrincipalName && AuthInfo->ServerSid)
  1067. {
  1068. ASSERT(ServerPrincipalName == NULL);
  1069. ASSERT(ServerSid == NULL);
  1070. *Equal = FALSE;
  1071. return RPC_S_OK;
  1072. }
  1073. // case 13
  1074. if (ServerPrincipalName && ServerSid)
  1075. {
  1076. ASSERT(AuthInfo->ServerPrincipalName == NULL);
  1077. ASSERT(AuthInfo->ServerSid == NULL);
  1078. *Equal = FALSE;
  1079. return RPC_S_OK;
  1080. }
  1081. // they must be criss-crossed. Convert the one with an SPN to a SID.
  1082. // Case 10
  1083. if (ServerPrincipalName)
  1084. {
  1085. ASSERT(ServerSid == NULL);
  1086. ASSERT(AuthInfo->ServerSid);
  1087. RpcStatus = RpcpLookupAccountName (ServerPrincipalName,
  1088. &fCachedSid,
  1089. &Sid);
  1090. if (RpcStatus != RPC_S_OK)
  1091. return RpcStatus;
  1092. if (InterlockedCompareExchangePointer((PVOID *)&ServerSid,
  1093. Sid,
  1094. NULL) != NULL)
  1095. {
  1096. // somebody beat us to the punch - free the sid
  1097. delete [] Sid;
  1098. }
  1099. // fall through to comparison
  1100. }
  1101. // case 7
  1102. if (AuthInfo->ServerPrincipalName)
  1103. {
  1104. ASSERT(ServerSid);
  1105. ASSERT(AuthInfo->ServerSid == NULL);
  1106. RpcStatus = RpcpLookupAccountName (AuthInfo->ServerPrincipalName,
  1107. &fCachedSid,
  1108. &Sid);
  1109. if (RpcStatus != RPC_S_OK)
  1110. return RpcStatus;
  1111. if (InterlockedCompareExchangePointer((PVOID *)&AuthInfo->ServerSid,
  1112. Sid,
  1113. NULL) != NULL)
  1114. {
  1115. // somebody beat us to the punch - free the sid
  1116. delete [] Sid;
  1117. }
  1118. // fall through to comparison
  1119. }
  1120. ASSERT(AuthInfo->ServerSid);
  1121. ASSERT(ServerSid);
  1122. *Equal = EqualSid (AuthInfo->ServerSid, ServerSid);
  1123. return RPC_S_OK;
  1124. }
  1125. RPC_STATUS
  1126. CALL::Cancel(
  1127. void * ThreadHandle
  1128. )
  1129. {
  1130. return RPC_S_OK;
  1131. }
  1132. unsigned
  1133. CALL::TestCancel(
  1134. )
  1135. {
  1136. return 0;
  1137. }
  1138. /* ====================================================================
  1139. CCALL
  1140. ==================================================================== */
  1141. RPC_STATUS CCALL::SetDebugClientCallInformation(OUT DebugClientCallInfo **ppClientCallInfo,
  1142. OUT CellTag *ClientCallInfoCellTag,
  1143. OUT DebugCallTargetInfo **ppCallTargetInfo,
  1144. OUT CellTag *CallTargetInfoCellTag,
  1145. IN OUT PRPC_MESSAGE Message,
  1146. IN DebugThreadInfo *ThreadDebugCell OPTIONAL,
  1147. IN CellTag ThreadCellTag OPTIONAL)
  1148. {
  1149. RPC_STATUS Status;
  1150. DebugClientCallInfo *ClientCallInfo;
  1151. DebugCallTargetInfo *CallTargetInfo;
  1152. Status = InitializeServerSideCellHeapIfNecessary();
  1153. if (Status != RPC_S_OK)
  1154. return Status;
  1155. ClientCallInfo = (DebugClientCallInfo *) AllocateCell(ClientCallInfoCellTag);
  1156. if (ClientCallInfo == NULL)
  1157. {
  1158. return RPC_S_OUT_OF_MEMORY;
  1159. }
  1160. CallTargetInfo = (DebugCallTargetInfo *) AllocateCell(CallTargetInfoCellTag);
  1161. if (CallTargetInfo == NULL)
  1162. {
  1163. FreeCell(ClientCallInfo, ClientCallInfoCellTag);
  1164. return RPC_S_OUT_OF_MEMORY;
  1165. }
  1166. ClientCallInfo->TypeHeader = 0;
  1167. ClientCallInfo->Type = dctClientCallInfo;
  1168. ClientCallInfo->IfStart = *((DWORD *)Message->RpcInterfaceInformation + 1);
  1169. ClientCallInfo->ProcNum = (unsigned short)Message->ProcNum;
  1170. GetDebugCellIDFromDebugCell((DebugCellUnion *)CallTargetInfo,
  1171. CallTargetInfoCellTag, &ClientCallInfo->CallTargetID);
  1172. if (ThreadDebugCell)
  1173. {
  1174. GetDebugCellIDFromDebugCell((DebugCellUnion *)ThreadDebugCell,
  1175. &ThreadCellTag, &ClientCallInfo->ServicingThread);
  1176. }
  1177. else
  1178. {
  1179. ClientCallInfo->ServicingThread.CellID = 0;
  1180. ClientCallInfo->ServicingThread.SectionID = 0;
  1181. }
  1182. CallTargetInfo->TypeHeader = 0;
  1183. CallTargetInfo->Type = dctCallTargetInfo;
  1184. CallTargetInfo->LastUpdateTime = NtGetTickCount();
  1185. *ppClientCallInfo = ClientCallInfo;
  1186. *ppCallTargetInfo = CallTargetInfo;
  1187. return RPC_S_OK;
  1188. }
  1189. /* ====================================================================
  1190. BINDING_HANDLE
  1191. ==================================================================== */
  1192. BINDING_HANDLE::BINDING_HANDLE (
  1193. IN OUT RPC_STATUS *pStatus
  1194. ) : BindingMutex(pStatus)
  1195. /*++
  1196. Routine Description:
  1197. In addition to initializing a binding handle instance in this
  1198. constructor, we also need to put the binding handle into a global
  1199. set of binding handle. This is necessary only for windows.
  1200. --*/
  1201. {
  1202. Timeout = RPC_C_BINDING_DEFAULT_TIMEOUT;
  1203. NullObjectUuidFlag = 1;
  1204. ObjectUuid.SetToNullUuid();
  1205. EntryNameSyntax = 0;
  1206. EntryName = 0;
  1207. EpLookupHandle = 0;
  1208. pvTransportOptions = NULL;
  1209. OptionsVector = NULL;
  1210. }
  1211. BINDING_HANDLE::~BINDING_HANDLE (
  1212. )
  1213. {
  1214. if (EpLookupHandle != 0)
  1215. {
  1216. EpFreeLookupHandle(EpLookupHandle);
  1217. }
  1218. delete EntryName;
  1219. if (pvTransportOptions)
  1220. {
  1221. I_RpcFree(pvTransportOptions);
  1222. }
  1223. if (OptionsVector)
  1224. {
  1225. I_RpcFree(OptionsVector);
  1226. }
  1227. }
  1228. RPC_STATUS
  1229. BINDING_HANDLE::BaseClone (
  1230. BINDING_HANDLE * Handle
  1231. )
  1232. {
  1233. RPC_STATUS Status = 0;
  1234. Timeout = Handle->Timeout;
  1235. ObjectUuid = Handle->ObjectUuid;
  1236. NullObjectUuidFlag = Handle->NullObjectUuidFlag;
  1237. /*
  1238. All of these duplicate what is done in the constructor.
  1239. EntryName = 0;
  1240. EntryNameSyntax = 0;
  1241. EpLookupHandle = 0;
  1242. pvTransportOptions = 0;
  1243. OptionsVector = 0;
  1244. */
  1245. if (Handle->OptionsVector)
  1246. {
  1247. OptionsVector = new ULONG_PTR[ RPC_C_OPT_MAX_OPTIONS ];
  1248. if (OptionsVector == 0)
  1249. {
  1250. return RPC_S_OUT_OF_MEMORY;
  1251. }
  1252. RpcpMemoryCopy( OptionsVector, Handle->OptionsVector, RPC_C_OPT_MAX_OPTIONS * sizeof( ULONG_PTR) );
  1253. }
  1254. return Status;
  1255. }
  1256. RPC_STATUS
  1257. BINDING_HANDLE::Clone (
  1258. BINDING_HANDLE * Handle
  1259. )
  1260. {
  1261. RPC_STATUS Status = 0;
  1262. Status = BaseClone(Handle);
  1263. if(Status != RPC_S_OK)
  1264. {
  1265. return Status;
  1266. }
  1267. CLIENT_AUTH_INFO * AuthInfo;
  1268. if ((AuthInfo = Handle->InquireAuthInformation()) != 0)
  1269. {
  1270. Status = SetAuthInformation(
  1271. AuthInfo->ServerPrincipalName,
  1272. AuthInfo->AuthenticationLevel,
  1273. AuthInfo->AuthenticationService,
  1274. AuthInfo->AuthIdentity,
  1275. AuthInfo->AuthorizationService,
  1276. AuthInfo->Credentials,
  1277. AuthInfo->ImpersonationType,
  1278. AuthInfo->IdentityTracking,
  1279. AuthInfo->Capabilities,
  1280. FALSE, // bAcquireNewCredentials
  1281. AuthInfo->AdditionalTransportCredentialsType,
  1282. AuthInfo->AdditionalCredentials,
  1283. AuthInfo->ServerSid
  1284. );
  1285. if (Status != RPC_S_OK)
  1286. {
  1287. ASSERT(Status == RPC_S_OUT_OF_MEMORY);
  1288. //
  1289. // Previous code maps all security errors to this.
  1290. //
  1291. return RPC_S_OUT_OF_MEMORY;
  1292. }
  1293. }
  1294. return Status;
  1295. }
  1296. void
  1297. BINDING_HANDLE::InquireObjectUuid (
  1298. OUT RPC_UUID PAPI * ObjectUuid
  1299. )
  1300. /*++
  1301. Routine Description:
  1302. This routine copies the object uuid from the binding handle into
  1303. the supplied ObjectUuid argument.
  1304. Arguments:
  1305. ObjectUuid - Returns a copy of the object uuid in the binding handle.
  1306. --*/
  1307. {
  1308. ObjectUuid->CopyUuid(&(this->ObjectUuid));
  1309. }
  1310. void
  1311. BINDING_HANDLE::SetObjectUuid (
  1312. IN RPC_UUID PAPI * ObjectUuid
  1313. )
  1314. /*++
  1315. Routine Description:
  1316. This routine copies the object uuid supplied in the ObjectUuid argument
  1317. into the binding handle.
  1318. Arguments:
  1319. ObjectUuid - Supplies the object uuid to copy into the binding handle.
  1320. --*/
  1321. {
  1322. if ( ( ObjectUuid == 0 )
  1323. || ( ObjectUuid->IsNullUuid() != 0 ) )
  1324. {
  1325. NullObjectUuidFlag = 1;
  1326. this->ObjectUuid.SetToNullUuid();
  1327. }
  1328. else
  1329. {
  1330. this->ObjectUuid.CopyUuid(ObjectUuid);
  1331. NullObjectUuidFlag = 0;
  1332. }
  1333. }
  1334. RPC_STATUS
  1335. BINDING_HANDLE::SetComTimeout (
  1336. IN unsigned int Timeout
  1337. )
  1338. /*++
  1339. Routine Description:
  1340. This routine sets the communications timeout value in this binding
  1341. handle. The specified timeout is range checked.
  1342. Arguments:
  1343. Timeout - Supplies the new communications timeout value for this
  1344. binding handle.
  1345. Return Value:
  1346. RPC_S_OK - The operation completed successfully.
  1347. RPC_S_INVALID_TIMEOUT - The specified timeout value is not in the
  1348. correct range.
  1349. --*/
  1350. {
  1351. // We just need to check to see if the timeout value is too large,
  1352. // since the timeout is unsigned and the lowest value is zero.
  1353. if (Timeout > RPC_C_BINDING_INFINITE_TIMEOUT)
  1354. return(RPC_S_INVALID_TIMEOUT);
  1355. this->Timeout = Timeout;
  1356. return(RPC_S_OK);
  1357. }
  1358. RPC_CHAR *pNS_DLL_NAME = RPC_STRING_LITERAL("RPCNS4");
  1359. const char *pNS_ENTRYPOINT_NAME = "I_GetDefaultEntrySyntax";
  1360. typedef unsigned long (RPC_ENTRY * GET_DEFAULT_ENTRY_FN)();
  1361. RPC_STATUS
  1362. BINDING_HANDLE::InquireEntryName (
  1363. IN unsigned long EntryNameSyntax,
  1364. OUT RPC_CHAR PAPI * PAPI * EntryName
  1365. )
  1366. /*++
  1367. Routine Description:
  1368. This method is used to obtain the entry name for the binding handle,
  1369. if it has one. The entry name is the name of the name service object
  1370. from which a binding handle is imported or looked up. If the binding
  1371. handle was not imported or looked up, then it has no entry name.
  1372. Arguments:
  1373. EntryNameSyntax - Supplies the entry name syntax which the caller
  1374. wants the entry name to be returned in. This may require that
  1375. we convert the entry name in the binding handle into a different
  1376. syntax.
  1377. EntryName - Returns the entry name of the binding handle in the
  1378. requested entry name syntax.
  1379. Return Value:
  1380. RPC_S_OK - This binding handle has an entry name, and we were able
  1381. to convert the entry name in the binding handle into the requested
  1382. entry name syntax.
  1383. RPC_S_NO_ENTRY_NAME - The binding handle does not have an entry
  1384. name. If this value is returned, the entry name return value
  1385. will be set to point to a newly allocated empty string.
  1386. RPC_S_INVALID_NAME_SYNTAX - The entry name in the binding handle
  1387. can not be converted to the entry name syntax requested.
  1388. RPC_S_UNSUPPORTED_NAME_SYNTAX - The entry name syntax requested
  1389. is not supported by the current configuration.
  1390. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  1391. the operation.
  1392. --*/
  1393. {
  1394. if ( this->EntryName == 0 )
  1395. {
  1396. *EntryName = AllocateEmptyStringPAPI();
  1397. if (*EntryName == 0)
  1398. return(RPC_S_OUT_OF_MEMORY);
  1399. return(RPC_S_NO_ENTRY_NAME);
  1400. }
  1401. //
  1402. // If he chose the default syntax and the binding has an entry,
  1403. // ask the name service for the default entry syntax.
  1404. // The NS dll should already be loaded because otherwise we'd not have an
  1405. // associated entry.
  1406. //
  1407. if (EntryNameSyntax == RPC_C_NS_SYNTAX_DEFAULT)
  1408. {
  1409. HINSTANCE NsDll = GetModuleHandle((const RPC_SCHAR *)pNS_DLL_NAME);
  1410. if (NsDll)
  1411. {
  1412. GET_DEFAULT_ENTRY_FN GetDefaultEntry =
  1413. (GET_DEFAULT_ENTRY_FN)
  1414. GetProcAddress(NsDll,
  1415. pNS_ENTRYPOINT_NAME
  1416. );
  1417. if (GetDefaultEntry)
  1418. {
  1419. EntryNameSyntax = (*GetDefaultEntry)();
  1420. }
  1421. else
  1422. {
  1423. //
  1424. // leave EntryNameSyntax zero; the fn will fail
  1425. // with invalid_name_syntax
  1426. //
  1427. }
  1428. }
  1429. else
  1430. {
  1431. //
  1432. // leave EntryNameSyntax zero; the fn will fail
  1433. // with invalid_name_syntax
  1434. //
  1435. }
  1436. }
  1437. if (EntryNameSyntax == this->EntryNameSyntax)
  1438. {
  1439. *EntryName = DuplicateStringPAPI(this->EntryName);
  1440. if (*EntryName == 0)
  1441. return(RPC_S_OUT_OF_MEMORY);
  1442. return(RPC_S_OK);
  1443. }
  1444. return(RPC_S_INVALID_NAME_SYNTAX);
  1445. }
  1446. RPC_STATUS
  1447. BINDING_HANDLE::SetEntryName (
  1448. IN unsigned long EntryNameSyntax,
  1449. IN RPC_CHAR PAPI * EntryName
  1450. )
  1451. /*++
  1452. Routine Description:
  1453. This method is used to set the entry name and entry name syntax
  1454. for a binding handle.
  1455. Arguments:
  1456. EntryNameSyntax - Supplies the syntax of the entry name argument.
  1457. EntryName - Supplies the entry name for this binding handle.
  1458. Return Value:
  1459. RPC_S_OK - We successfully set the entry name (and entry name syntax)
  1460. for this binding handle.
  1461. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to set the
  1462. entry name.
  1463. --*/
  1464. {
  1465. RPC_CHAR * NewEntryName;
  1466. NewEntryName = DuplicateString(EntryName);
  1467. if (NewEntryName == 0)
  1468. return(RPC_S_OUT_OF_MEMORY);
  1469. this->EntryNameSyntax = EntryNameSyntax;
  1470. if (this->EntryName != 0)
  1471. delete this->EntryName;
  1472. this->EntryName = NewEntryName;
  1473. return(RPC_S_OK);
  1474. }
  1475. RPC_STATUS
  1476. BINDING_HANDLE::InquireDynamicEndpoint (
  1477. OUT RPC_CHAR PAPI * PAPI * DynamicEndpoint
  1478. )
  1479. /*++
  1480. Routine Description:
  1481. This routine is used to obtain the dynamic endpoint from a binding
  1482. handle which was created from an rpc address. For all other binding
  1483. handles, we just return the fact that there is no dynamic endpoint.
  1484. Arguments:
  1485. DynamicEndpoint - Returns a pointer to the dynamic endpoint, if there
  1486. is one, or zero.
  1487. Return Value:
  1488. RPC_S_OK - This value will always be returned.
  1489. --*/
  1490. {
  1491. *DynamicEndpoint = 0;
  1492. return(RPC_S_OK);
  1493. }
  1494. unsigned long
  1495. BINDING_HANDLE::MapAuthenticationLevel (
  1496. IN unsigned long AuthenticationLevel
  1497. )
  1498. /*++
  1499. Routine Description:
  1500. This method is to provide a way for a protocol module to map a requested
  1501. authentication level into one supported by that protocol module.
  1502. Arguments:
  1503. AuthenticationLevel - Supplies the proposed authentication level; this
  1504. value has already been validated.
  1505. Return Value:
  1506. The authentication level to be used is returned.
  1507. --*/
  1508. {
  1509. return(AuthenticationLevel);
  1510. }
  1511. BOOL
  1512. BINDING_HANDLE::SetTransportAuthentication(
  1513. IN unsigned long ulAuthenticationLevel,
  1514. IN unsigned long ulAuthenticationService,
  1515. OUT RPC_STATUS *pStatus )
  1516. /*
  1517. Routine Descritpion:
  1518. Called inside of SetAuthInformation(), this function allows for
  1519. transport level authentication to be set. If this function is not
  1520. overridden then it returns RPC_S_NOT_SUPPORTED and the normal RPC
  1521. level authentication is used.
  1522. */
  1523. {
  1524. *pStatus = RPC_S_CANNOT_SUPPORT;
  1525. return TRUE;
  1526. }
  1527. RPC_STATUS
  1528. BINDING_HANDLE::SendReceive (
  1529. IN OUT PRPC_MESSAGE Message
  1530. )
  1531. {
  1532. UNUSED(Message);
  1533. ASSERT( 0 );
  1534. return(RPC_S_INTERNAL_ERROR);
  1535. }
  1536. RPC_STATUS
  1537. BINDING_HANDLE::Send (
  1538. IN OUT PRPC_MESSAGE Message
  1539. )
  1540. {
  1541. UNUSED(Message);
  1542. ASSERT( 0 );
  1543. return(RPC_S_INTERNAL_ERROR);
  1544. }
  1545. RPC_STATUS
  1546. BINDING_HANDLE::Receive (
  1547. IN OUT PRPC_MESSAGE Message,
  1548. IN unsigned int Size
  1549. )
  1550. {
  1551. UNUSED(Message);
  1552. ASSERT( 0 );
  1553. return(RPC_S_INTERNAL_ERROR);
  1554. }
  1555. void
  1556. BINDING_HANDLE::FreeBuffer (
  1557. IN PRPC_MESSAGE Message
  1558. )
  1559. {
  1560. UNUSED(Message);
  1561. ASSERT( 0 );
  1562. }
  1563. RPC_STATUS
  1564. BINDING_HANDLE::ReAcquireCredentialsIfNecessary(
  1565. )
  1566. {
  1567. LUID CurrentModifiedId;
  1568. RPC_STATUS Status = CaptureModifiedId(&CurrentModifiedId);
  1569. SECURITY_CREDENTIALS * SecurityCredentials;
  1570. BOOL MyDefaultLogonId;
  1571. if (Status == RPC_S_OK)
  1572. {
  1573. MyDefaultLogonId = FALSE;
  1574. }
  1575. else
  1576. {
  1577. MyDefaultLogonId = TRUE;
  1578. }
  1579. if (MyDefaultLogonId != ClientAuthInfo.DefaultLogonId
  1580. || (MyDefaultLogonId == FALSE
  1581. && (FastCompareLUIDAligned(&CurrentModifiedId,
  1582. &ClientAuthInfo.ModifiedId) == FALSE)))
  1583. {
  1584. ClientAuthInfo.DefaultLogonId = MyDefaultLogonId;
  1585. Status = RPC_S_OK;
  1586. SecurityCredentials = new SECURITY_CREDENTIALS(&Status);
  1587. if ((SecurityCredentials == 0) || (Status != RPC_S_OK))
  1588. {
  1589. if (SecurityCredentials == 0)
  1590. {
  1591. Status = RPC_S_OUT_OF_MEMORY;
  1592. }
  1593. delete SecurityCredentials;
  1594. return (Status);
  1595. }
  1596. // Dynamic identity tracking - need to get the current credentials.
  1597. Status = SecurityCredentials->AcquireCredentialsForClient(
  1598. ClientAuthInfo.AuthIdentity,
  1599. ClientAuthInfo.AuthenticationService,
  1600. ClientAuthInfo.AuthenticationLevel
  1601. );
  1602. if ( Status != RPC_S_OK )
  1603. {
  1604. VALIDATE(Status)
  1605. {
  1606. RPC_S_OUT_OF_MEMORY,
  1607. RPC_S_UNKNOWN_AUTHN_SERVICE,
  1608. RPC_S_UNKNOWN_AUTHN_LEVEL,
  1609. RPC_S_SEC_PKG_ERROR,
  1610. ERROR_SHUTDOWN_IN_PROGRESS,
  1611. RPC_S_INVALID_AUTH_IDENTITY
  1612. } END_VALIDATE;
  1613. delete SecurityCredentials;
  1614. return(Status);
  1615. }
  1616. if (ClientAuthInfo.CredentialsMatch(SecurityCredentials) != 0)
  1617. {
  1618. SecurityCredentials->DereferenceCredentials();
  1619. }
  1620. else
  1621. {
  1622. BindingMutex.Request();
  1623. if (ClientAuthInfo.Credentials != 0)
  1624. {
  1625. ClientAuthInfo.Credentials->DereferenceCredentials();
  1626. }
  1627. ClientAuthInfo.Credentials = SecurityCredentials;
  1628. BindingMutex.Clear();
  1629. }
  1630. FastCopyLUIDAligned(&ClientAuthInfo.ModifiedId, &CurrentModifiedId);
  1631. }
  1632. return (RPC_S_OK);
  1633. }
  1634. RPC_STATUS
  1635. BINDING_HANDLE::SetTransportOption( IN unsigned long option,
  1636. IN ULONG_PTR optionValue )
  1637. {
  1638. if (option > RPC_C_OPT_MAX_OPTIONS)
  1639. {
  1640. return RPC_S_INVALID_ARG;
  1641. }
  1642. if (OptionsVector == NULL)
  1643. {
  1644. BindingMutex.Request();
  1645. if (OptionsVector == NULL)
  1646. {
  1647. OptionsVector = new ULONG_PTR[ RPC_C_OPT_MAX_OPTIONS ];
  1648. if (OptionsVector == 0)
  1649. {
  1650. BindingMutex.Clear();
  1651. return RPC_S_OUT_OF_MEMORY;
  1652. }
  1653. RpcpMemorySet(OptionsVector, 0, RPC_C_OPT_MAX_OPTIONS * sizeof(OptionsVector[0]) );
  1654. }
  1655. BindingMutex.Clear();
  1656. }
  1657. OptionsVector[option] = optionValue;
  1658. return RPC_S_OK;
  1659. }
  1660. RPC_STATUS
  1661. BINDING_HANDLE::InqTransportOption( IN unsigned long option,
  1662. OUT ULONG_PTR * pOptionValue )
  1663. {
  1664. if (OptionsVector == NULL)
  1665. {
  1666. *pOptionValue = 0;
  1667. }
  1668. else
  1669. {
  1670. *pOptionValue = OptionsVector[option];
  1671. }
  1672. return RPC_S_OK;
  1673. }
  1674. RPC_STATUS
  1675. CALL::Send (
  1676. IN OUT PRPC_MESSAGE Message
  1677. )
  1678. /*++
  1679. Function Name:Send
  1680. Parameters:
  1681. Description:
  1682. Returns:
  1683. --*/
  1684. {
  1685. ASSERT(!"improper CCALL member called\n");
  1686. return (RPC_S_CANNOT_SUPPORT) ;
  1687. }
  1688. RPC_STATUS
  1689. CALL::Receive (
  1690. IN OUT PRPC_MESSAGE Message,
  1691. IN unsigned int Size
  1692. )
  1693. /*++
  1694. Function Name:Receive
  1695. Parameters:
  1696. Description:
  1697. Returns:
  1698. --*/
  1699. {
  1700. ASSERT(!"improper CCALL member called\n");
  1701. return (RPC_S_CANNOT_SUPPORT) ;
  1702. }
  1703. RPC_STATUS
  1704. CALL::AsyncSend (
  1705. IN OUT PRPC_MESSAGE Message
  1706. )
  1707. /*++
  1708. Function Name:AsyncSend
  1709. Parameters:
  1710. Description:
  1711. Returns:
  1712. --*/
  1713. {
  1714. ASSERT(!"improper CCALL member called\n");
  1715. return (RPC_S_CANNOT_SUPPORT) ;
  1716. }
  1717. RPC_STATUS
  1718. CALL::AsyncReceive (
  1719. IN OUT PRPC_MESSAGE Message,
  1720. IN unsigned int Size
  1721. )
  1722. /*++
  1723. Function Name:AsyncReceive
  1724. Parameters:
  1725. Description:
  1726. Returns:
  1727. --*/
  1728. {
  1729. ASSERT(!"improper CCALL member called\n");
  1730. return (RPC_S_CANNOT_SUPPORT) ;
  1731. }
  1732. RPC_STATUS
  1733. CALL::AbortAsyncCall (
  1734. IN PRPC_ASYNC_STATE pAsync,
  1735. IN unsigned long ExceptionCode
  1736. )
  1737. /*++
  1738. Function Name:AbortAsyncCall
  1739. Parameters:
  1740. Description:
  1741. Returns:
  1742. --*/
  1743. {
  1744. ASSERT(!"improper CCALL member called\n");
  1745. return (RPC_S_CANNOT_SUPPORT) ;
  1746. }
  1747. void
  1748. CALL::ProcessResponse (
  1749. IN BOOL fDirectCall
  1750. )
  1751. /*++
  1752. Function Name:ProcessResponse
  1753. Parameters:
  1754. Description:
  1755. Returns:
  1756. --*/
  1757. {
  1758. }
  1759. void
  1760. CALL::FreeAPCInfo (
  1761. IN RPC_APC_INFO *pAPCInfo
  1762. )
  1763. /*++
  1764. Function Name:FreeAPCInfo
  1765. Parameters:
  1766. Description:
  1767. Returns:
  1768. --*/
  1769. {
  1770. if (pAPCInfo == &CachedAPCInfo)
  1771. {
  1772. CachedAPCInfoAvailable = 1;
  1773. }
  1774. else
  1775. {
  1776. delete pAPCInfo ;
  1777. }
  1778. }
  1779. BOOL
  1780. CALL::QueueAPC (
  1781. IN RPC_ASYNC_EVENT Event,
  1782. IN void *Context
  1783. )
  1784. /*++
  1785. Function Name:QueueAPC
  1786. Parameters:
  1787. Description:
  1788. Returns:
  1789. --*/
  1790. {
  1791. RPC_APC_INFO *pAPCInfo ;
  1792. HANDLE hThread ;
  1793. if (CachedAPCInfoAvailable)
  1794. {
  1795. pAPCInfo = &CachedAPCInfo ;
  1796. CachedAPCInfoAvailable = 0;
  1797. }
  1798. else
  1799. {
  1800. pAPCInfo = new RPC_APC_INFO ;
  1801. }
  1802. if (pAPCInfo == 0)
  1803. {
  1804. return 0 ;
  1805. }
  1806. pAPCInfo->Context = Context;
  1807. pAPCInfo->Event = Event ;
  1808. pAPCInfo->pAsync = pAsync ;
  1809. pAPCInfo->hCall = this ;
  1810. if (pAsync->u.APC.hThread)
  1811. {
  1812. hThread = pAsync->u.APC.hThread ;
  1813. }
  1814. else
  1815. {
  1816. ASSERT(CallingThread != 0);
  1817. hThread = CallingThread->ThreadHandle() ;
  1818. }
  1819. if (!QueueUserAPC(
  1820. (PAPCFUNC) I_RpcAPCRoutine,
  1821. hThread,
  1822. (ULONG_PTR) pAPCInfo))
  1823. {
  1824. #if DBG
  1825. PrintToDebugger("RPC: QueueUserAPC failed: %d\n", GetLastError());
  1826. #endif
  1827. return 0 ;
  1828. }
  1829. return 1;
  1830. }
  1831. BOOL
  1832. RpcPostMessageWrapper (
  1833. HWND hWnd,
  1834. UINT Msg,
  1835. WPARAM wParam,
  1836. LPARAM lParam);
  1837. typedef BOOL (*RPCPOSTMESSAGE) (
  1838. HWND hWnd,
  1839. UINT Msg,
  1840. WPARAM wParam,
  1841. LPARAM lParam);
  1842. RPCPOSTMESSAGE RpcPostMessage = RpcPostMessageWrapper;
  1843. BOOL
  1844. RpcPostMessageWrapper (
  1845. HWND hWnd,
  1846. UINT Msg,
  1847. WPARAM wParam,
  1848. LPARAM lParam)
  1849. /*++
  1850. Function Name:RpcPostMessageWrapper
  1851. Parameters:
  1852. Description:
  1853. Returns:
  1854. --*/
  1855. {
  1856. HMODULE hLibrary;
  1857. if (RpcPostMessage == RpcPostMessageWrapper)
  1858. {
  1859. GlobalMutexRequest();
  1860. if (RpcPostMessage == RpcPostMessageWrapper)
  1861. {
  1862. hLibrary = LoadLibrary(RPC_CONST_SSTRING("user32.dll"));
  1863. if (hLibrary == 0)
  1864. {
  1865. GlobalMutexClear();
  1866. return FALSE;
  1867. }
  1868. RpcPostMessage =
  1869. (RPCPOSTMESSAGE) GetProcAddress(hLibrary, "PostMessageW");
  1870. if (RpcPostMessage == 0)
  1871. {
  1872. RpcPostMessage = RpcPostMessageWrapper;
  1873. FreeLibrary(hLibrary);
  1874. GlobalMutexClear();
  1875. return FALSE;
  1876. }
  1877. }
  1878. GlobalMutexClear();
  1879. }
  1880. return RpcPostMessage(hWnd, Msg, wParam, lParam);
  1881. }
  1882. BOOL
  1883. CALL::IssueNotificationEntry (
  1884. IN RPC_ASYNC_EVENT Event
  1885. )
  1886. {
  1887. int Retries = 0;
  1888. if (pAsync == 0
  1889. || (Event == RpcCallComplete
  1890. && InterlockedIncrement(&NotificationIssued) > 0))
  1891. {
  1892. #if DBG
  1893. PrintToDebugger("RPC: IssueCallCompleteNotification was a no-op\n") ;
  1894. #endif
  1895. return 0;
  1896. }
  1897. // An unlikely, but possible race condition - the send thread hasn't
  1898. // yet returned to the NDR code, which means the NdrLock is still held -
  1899. // we cannot issue a notification until it is released, or the
  1900. // client thread cannot complete the call.
  1901. //
  1902. // The send thread may still be executing "above" NDR code if it is issuing
  1903. // a send-complete notification during a pipe call, in which case we should not wait.
  1904. // We also should not wait while issuing a receive-complete notification, since
  1905. // one can issue pulls before the call returns from NDR.
  1906. if (Event == RpcCallComplete)
  1907. {
  1908. while (TRUE)
  1909. {
  1910. if (pAsync->Lock > 0)
  1911. {
  1912. PauseExecution(200);
  1913. // yes, we don't break if the Retries go through the roof -
  1914. // this is just to figure out how many times we have looped
  1915. // on a checked build
  1916. Retries ++;
  1917. }
  1918. else
  1919. break;
  1920. }
  1921. }
  1922. ASSERT(pAsync->Size == RPC_ASYNC_VERSION_1_0);
  1923. LogEvent(SU_SCALL, EV_NOTIFY, CallingThread, this, (ULONG_PTR) pAsync, 1);
  1924. pAsync->Event = Event;
  1925. return 1;
  1926. }
  1927. BOOL
  1928. CALL::IssueNotificationMain (
  1929. IN RPC_ASYNC_EVENT Event
  1930. )
  1931. {
  1932. switch (pAsync->NotificationType)
  1933. {
  1934. case RpcNotificationTypeNone:
  1935. break;
  1936. case RpcNotificationTypeHwnd:
  1937. RpcPostMessage(
  1938. pAsync->u.HWND.hWnd,
  1939. pAsync->u.HWND.Msg,
  1940. 0,
  1941. (LPARAM) pAsync) ;
  1942. break;
  1943. case RpcNotificationTypeCallback:
  1944. pAsync->u.NotificationRoutine(pAsync, 0, Event);
  1945. break;
  1946. case RpcNotificationTypeEvent:
  1947. if (!SetEvent(pAsync->u.hEvent))
  1948. {
  1949. #if DBG
  1950. PrintToDebugger("RPC: SetEvent failed: %d\n", GetLastError());
  1951. #endif
  1952. return 0;
  1953. }
  1954. break;
  1955. case RpcNotificationTypeApc:
  1956. if (!QueueAPC(Event))
  1957. {
  1958. #if DBG
  1959. PrintToDebugger("RPC: QueueAPC failed\n");
  1960. #endif
  1961. return 0;
  1962. }
  1963. break;
  1964. case RpcNotificationTypeIoc:
  1965. if (!PostQueuedCompletionStatus(
  1966. pAsync->u.IOC.hIOPort,
  1967. pAsync->u.IOC.dwNumberOfBytesTransferred,
  1968. pAsync->u.IOC.dwCompletionKey,
  1969. pAsync->u.IOC.lpOverlapped))
  1970. {
  1971. #if DBG
  1972. PrintToDebugger("RPC: PostQueuedCompletionStatus failed %d\n",
  1973. GetLastError());
  1974. #endif
  1975. return 0;
  1976. }
  1977. break;
  1978. default:
  1979. ASSERT(!"Invalid notification type") ;
  1980. return 0;
  1981. }
  1982. return 1;
  1983. }
  1984. BOOL
  1985. CALL::IssueNotification (
  1986. IN RPC_ASYNC_EVENT Event
  1987. )
  1988. /*++
  1989. Function Name:IssueNotification
  1990. Parameters:
  1991. Description:
  1992. Returns:
  1993. --*/
  1994. {
  1995. if (IssueNotificationEntry(Event))
  1996. return IssueNotificationMain(Event);
  1997. else
  1998. return 0;
  1999. }
  2000. void
  2001. CALL::ProcessEvent (
  2002. )
  2003. /*++
  2004. Function Name:ProcessEvent
  2005. Parameters:
  2006. Description:
  2007. Returns:
  2008. --*/
  2009. {
  2010. ASSERT(0) ;
  2011. }
  2012. RPC_STATUS
  2013. DispatchCallback(
  2014. IN PRPC_DISPATCH_TABLE DispatchTableCallback,
  2015. IN OUT PRPC_MESSAGE Message,
  2016. OUT RPC_STATUS PAPI * ExceptionCode
  2017. )
  2018. /*++
  2019. Routine Description:
  2020. This method is used to dispatch remote procedure calls to the
  2021. appropriate stub and hence to the appropriate manager entry point.
  2022. This routine is used for calls having a null UUID (implicit or
  2023. explicit).
  2024. Arguments:
  2025. DispatchTableCallback - Callback table.
  2026. Message - Supplies the response message and returns the reply
  2027. message.
  2028. ExceptionCode - Returns the remote exception code if
  2029. RPC_P_EXCEPTION_OCCURED is returned.
  2030. Return Value:
  2031. RPC_S_OK - Everything worked just fine.
  2032. RPC_P_EXCEPTION_OCCURED - An exception of some sort occured. The
  2033. exact exception code will be returned in the ExceptionCode
  2034. argument.
  2035. RPC_S_PROCNUM_OUT_OF_RANGE - The supplied operation number in the
  2036. message is too large.
  2037. --*/
  2038. {
  2039. RPC_STATUS RpcStatus = RPC_S_OK;
  2040. void PAPI *OriginalBuffer = Message->Buffer;
  2041. //
  2042. // Callbacks are unsafe and on their way towards deprication.
  2043. // When running with the RPC verifier, we should flag their use
  2044. // and issue a warning message.
  2045. //
  2046. if (gfRPCVerifierEnabledWithBreaks)
  2047. {
  2048. RPC_VERIFIER_WARNING_MSG("Possible security threat: Client is dispatching a callback",
  2049. RPC_VERIFIER_UNSAFE_FEATURE);
  2050. DbgPrint("RPC: Callback routine: 0x%x\n", DispatchTableCallback->DispatchTable[Message->ProcNum]);
  2051. DbgPrint("RPC: To determine the symbolic name of the callback, do an \"ln\" on the above address in the context of the faulting process.\n\n");
  2052. }
  2053. // N.B. We could reset the flag after sendreceive is completed for
  2054. // each protocol engine
  2055. Message->RpcFlags |= RPC_BUFFER_COMPLETE ;
  2056. if ( Message->ProcNum >= DispatchTableCallback->DispatchTableCount )
  2057. {
  2058. return(RPC_S_PROCNUM_OUT_OF_RANGE);
  2059. }
  2060. Message->ManagerEpv = 0;
  2061. RpcpPurgeEEInfo();
  2062. if ( DispatchToStubInC(DispatchTableCallback->DispatchTable[
  2063. Message->ProcNum], Message, ExceptionCode) != 0 )
  2064. {
  2065. RpcStatus = RPC_P_EXCEPTION_OCCURED;
  2066. }
  2067. if (((MESSAGE_OBJECT *) Message->Handle)->IsSyncCall())
  2068. {
  2069. if (OriginalBuffer == Message->Buffer && RpcStatus == RPC_S_OK)
  2070. {
  2071. //
  2072. // If the stub has NO out data, it may skip the call to
  2073. // I_RpcGetBuffer(). If it called I_RpcGetBuffer and
  2074. // still has the same Buffer, we have a bug!
  2075. //
  2076. Message->BufferLength = 0;
  2077. ((MESSAGE_OBJECT *) Message->Handle)->GetBuffer(Message, 0);
  2078. }
  2079. }
  2080. return(RpcStatus);
  2081. }
  2082. /* ====================================================================
  2083. Client DLL initialization routine.
  2084. ==================================================================== */
  2085. int
  2086. InitializeClientDLL (void
  2087. )
  2088. {
  2089. // We don't want to do this under DOS. The first time
  2090. // LoadableTransportClientInfo (in tranclnt.cxx) is called, it will
  2091. // perform the appropriate initialization. See the first few lines
  2092. // of that routine for more description.
  2093. if (InitializeLoadableTransportClient() != 0)
  2094. return(1);
  2095. if (InitializeRpcProtocolOfsClient() != 0)
  2096. return(1);
  2097. if (InitializeRpcProtocolDgClient() != 0)
  2098. return(1);
  2099. return(0);
  2100. }
  2101. RPC_STATUS
  2102. BINDING_HANDLE::SetAuthInformation (
  2103. IN RPC_CHAR PAPI * ServerPrincipalName, OPTIONAL
  2104. IN unsigned long AuthenticationLevel,
  2105. IN unsigned long AuthenticationService,
  2106. IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
  2107. IN unsigned long AuthorizationService,
  2108. IN SECURITY_CREDENTIALS * Credentials,
  2109. IN unsigned long ImpersonationType,
  2110. IN unsigned long IdentityTracking,
  2111. IN unsigned long Capabilities,
  2112. IN BOOL bAcquireNewCredentials, OPTIONAL
  2113. IN ULONG AdditionalTransportCredentialsType, OPTIONAL
  2114. IN void *AdditionalCredentials, OPTIONAL
  2115. IN PSID Sid OPTIONAL
  2116. )
  2117. /*++
  2118. Routine Description:
  2119. We set the authentication and authorization information in this binding
  2120. handle.
  2121. Arguments:
  2122. ServerPrincipalName - Optionally supplies the server principal name.
  2123. AuthenticationLevel - Supplies the authentication level to use.
  2124. AuthenticationService - Supplies the authentication service to use.
  2125. AuthIdentity - Optionally supplies the security context to use.
  2126. AuthorizationService - Supplies the authorization service to use.
  2127. AdditionalTransportCredentialsType - the type of additional credentials
  2128. supplied in AdditionalCredentials
  2129. AdditionalCredentials - pointer to additional credentials if any
  2130. Sid - the SID to mutually authenticate to
  2131. Return Value:
  2132. RPC_S_OK - The supplied authentication and authorization information has
  2133. been set in the binding handle.
  2134. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  2135. operation.
  2136. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is
  2137. not supported.
  2138. RPC_S_UNKNOWN_AUTHN_LEVEL - The specified authentication level is
  2139. not supported.
  2140. RPC_S_INVALID_AUTH_IDENTITY - The specified security context (supplied
  2141. by the auth identity argument) is invalid.
  2142. RPC_S_UNKNOWN_AUTHZ_SERVICE - The specified authorization service is
  2143. not supported.
  2144. --*/
  2145. {
  2146. RPC_CHAR * NewString;
  2147. RPC_STATUS RpcStatus = RPC_S_OK;
  2148. SECURITY_CREDENTIALS * SecurityCredentials = NULL;
  2149. unsigned long MappedAuthenticationLevel;
  2150. PSID SidToDeleteOnFailure;
  2151. RPC_CHAR *AllocatedSPN;
  2152. BOOL fCachedSid = TRUE;
  2153. RPC_HTTP_TRANSPORT_CREDENTIALS_W *HttpCredentials;
  2154. if ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_DEFAULT )
  2155. {
  2156. RpcpGetDefaultSecurityProviderInfo();
  2157. AuthenticationLevel = DefaultAuthLevel;
  2158. }
  2159. if ( AuthenticationLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY )
  2160. {
  2161. return(RPC_S_UNKNOWN_AUTHN_LEVEL);
  2162. }
  2163. MappedAuthenticationLevel = MapAuthenticationLevel(AuthenticationLevel);
  2164. ASSERT( MappedAuthenticationLevel != RPC_C_AUTHN_LEVEL_DEFAULT &&
  2165. MappedAuthenticationLevel <= RPC_C_AUTHN_LEVEL_PKT_PRIVACY );
  2166. //
  2167. // See if this is transport level authentication:
  2168. //
  2169. if (!SetTransportAuthentication( MappedAuthenticationLevel,
  2170. AuthenticationService,
  2171. &RpcStatus ))
  2172. {
  2173. return RpcStatus;
  2174. }
  2175. RpcStatus = RPC_S_OK;
  2176. //
  2177. // Clear out stuff for NULL AUTHN_SVC
  2178. //
  2179. ASSERT((AdditionalTransportCredentialsType == RPC_C_AUTHN_INFO_TYPE_HTTP)
  2180. || (AdditionalTransportCredentialsType == 0));
  2181. if (AdditionalTransportCredentialsType == RPC_C_AUTHN_INFO_TYPE_HTTP)
  2182. {
  2183. ClientAuthInfo.AdditionalCredentials
  2184. = DuplicateHttpTransportCredentials (
  2185. (const RPC_HTTP_TRANSPORT_CREDENTIALS_W *) AdditionalCredentials);
  2186. if (ClientAuthInfo.AdditionalCredentials == NULL)
  2187. return RPC_S_OUT_OF_MEMORY;
  2188. HttpCredentials = (RPC_HTTP_TRANSPORT_CREDENTIALS_W *)(ClientAuthInfo.AdditionalCredentials);
  2189. if (HttpCredentials->TransportCredentials)
  2190. {
  2191. // encrypt only if we haven't yet
  2192. if ((HttpCredentials->Flags & RPC_C_HTTP_FLAG_AUTH_IDENTITY_ENCRYPTED) == 0)
  2193. {
  2194. RpcStatus = EncryptAuthIdentity(HttpCredentials->TransportCredentials);
  2195. if (RpcStatus != RPC_S_OK)
  2196. {
  2197. FreeAuthIdentity(HttpCredentials->TransportCredentials);
  2198. return RpcStatus;
  2199. }
  2200. // remember that the credentials are encrypted now
  2201. HttpCredentials->Flags |= RPC_C_HTTP_FLAG_AUTH_IDENTITY_ENCRYPTED;
  2202. }
  2203. }
  2204. else
  2205. {
  2206. // no credentials were specified this time around - take down the encryption flag
  2207. HttpCredentials->Flags &= ~RPC_C_HTTP_FLAG_AUTH_IDENTITY_ENCRYPTED;
  2208. }
  2209. }
  2210. else
  2211. {
  2212. ASSERT(AdditionalCredentials == NULL);
  2213. }
  2214. if (Sid)
  2215. {
  2216. SidToDeleteOnFailure = DuplicateSID(Sid);
  2217. if (SidToDeleteOnFailure == NULL)
  2218. return RPC_S_OUT_OF_MEMORY;
  2219. }
  2220. else
  2221. {
  2222. RequestGlobalMutex();
  2223. if (ClientAuthInfo.ServerSid)
  2224. {
  2225. delete [] ClientAuthInfo.ServerSid;
  2226. ClientAuthInfo.ServerSid = NULL;
  2227. }
  2228. ClearGlobalMutex();
  2229. // if we were given the local MA hint, we will need a SID anyway - try to resolve
  2230. // it now
  2231. if (Capabilities & RPC_C_QOS_CAPABILITIES_LOCAL_MA_HINT)
  2232. {
  2233. // we must have an SPN here. Caller should have verified that
  2234. ASSERT(ServerPrincipalName);
  2235. RpcStatus = RpcpLookupAccountName (ServerPrincipalName,
  2236. &fCachedSid,
  2237. &SidToDeleteOnFailure);
  2238. if (RpcStatus != RPC_S_OK)
  2239. return RpcStatus;
  2240. }
  2241. else
  2242. SidToDeleteOnFailure = NULL;
  2243. }
  2244. if (AuthenticationService == RPC_C_AUTHN_NONE)
  2245. {
  2246. //
  2247. // Dereference Credentials.. ServerPrincipal Name is
  2248. // handled by deleting CLIENT_AUTH_INFO .. Each AUTH_INFO explicitly
  2249. // copy the credentials around...
  2250. //
  2251. if (ClientAuthInfo.Credentials != 0)
  2252. {
  2253. ClientAuthInfo.Credentials->DereferenceCredentials();
  2254. ClientAuthInfo.Credentials = 0;
  2255. }
  2256. }
  2257. else
  2258. {
  2259. // if we were asked to do normal mutual auth, but were given only a SID (no SPN),
  2260. // then lookup the SPN now. This doesn't apply to SChannel though, because
  2261. // its SPNs cannot be looked up from SIDs for SChannel
  2262. if ( (AuthenticationService != RPC_C_AUTHN_GSS_SCHANNEL)
  2263. &&
  2264. ((ServerPrincipalName == NULL)
  2265. ||
  2266. (ServerPrincipalName[0] == '\0'))
  2267. && (Sid)
  2268. )
  2269. {
  2270. ASSERT(Sid != NULL);
  2271. RpcStatus = RpcpLookupAccountSid (Sid,
  2272. &ServerPrincipalName
  2273. );
  2274. if (RpcStatus != RPC_S_OK)
  2275. {
  2276. delete [] SidToDeleteOnFailure;
  2277. return RpcStatus;
  2278. }
  2279. AllocatedSPN = ServerPrincipalName;
  2280. }
  2281. else
  2282. {
  2283. AllocatedSPN = NULL;
  2284. }
  2285. if (bAcquireNewCredentials == FALSE)
  2286. {
  2287. ASSERT(Credentials);
  2288. Credentials->ReferenceCredentials();
  2289. SecurityCredentials = Credentials;
  2290. }
  2291. else
  2292. {
  2293. SecurityCredentials = new SECURITY_CREDENTIALS(&RpcStatus);
  2294. if ((SecurityCredentials == 0) || (RpcStatus != RPC_S_OK))
  2295. {
  2296. if (SecurityCredentials == 0)
  2297. {
  2298. RpcStatus = RPC_S_OUT_OF_MEMORY;
  2299. }
  2300. delete SecurityCredentials;
  2301. delete [] SidToDeleteOnFailure;
  2302. delete [] AllocatedSPN;
  2303. return (RpcStatus);
  2304. }
  2305. RpcStatus = SecurityCredentials->AcquireCredentialsForClient(
  2306. AuthIdentity,
  2307. AuthenticationService,
  2308. MappedAuthenticationLevel
  2309. );
  2310. if ( RpcStatus != RPC_S_OK )
  2311. {
  2312. VALIDATE(RpcStatus)
  2313. {
  2314. RPC_S_OUT_OF_MEMORY,
  2315. RPC_S_UNKNOWN_AUTHN_SERVICE,
  2316. RPC_S_UNKNOWN_AUTHN_LEVEL,
  2317. RPC_S_SEC_PKG_ERROR,
  2318. ERROR_SHUTDOWN_IN_PROGRESS,
  2319. RPC_S_INVALID_AUTH_IDENTITY
  2320. } END_VALIDATE;
  2321. delete SecurityCredentials;
  2322. delete [] SidToDeleteOnFailure;
  2323. delete [] AllocatedSPN;
  2324. return(RpcStatus);
  2325. }
  2326. }
  2327. if (ARGUMENT_PRESENT(ServerPrincipalName))
  2328. {
  2329. //
  2330. // SSL has unique SPN requirements.
  2331. //
  2332. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  2333. {
  2334. RpcStatus = ValidateSchannelPrincipalName(ServerPrincipalName);
  2335. if (RpcStatus != RPC_S_OK)
  2336. {
  2337. VALIDATE(RpcStatus)
  2338. {
  2339. ERROR_INVALID_PARAMETER
  2340. }
  2341. END_VALIDATE;
  2342. if (SecurityCredentials)
  2343. SecurityCredentials->DereferenceCredentials();
  2344. delete [] SidToDeleteOnFailure;
  2345. ASSERT(AllocatedSPN == NULL);
  2346. return RpcStatus;
  2347. }
  2348. }
  2349. if (AllocatedSPN)
  2350. {
  2351. NewString = AllocatedSPN;
  2352. AllocatedSPN = NULL;
  2353. }
  2354. else
  2355. NewString = DuplicateString(ServerPrincipalName);
  2356. if ( NewString == 0 )
  2357. {
  2358. if (SecurityCredentials)
  2359. SecurityCredentials->DereferenceCredentials();
  2360. delete [] SidToDeleteOnFailure;
  2361. return(RPC_S_OUT_OF_MEMORY);
  2362. }
  2363. RequestGlobalMutex();
  2364. if ( ClientAuthInfo.ServerPrincipalName != 0 )
  2365. {
  2366. delete ClientAuthInfo.ServerPrincipalName;
  2367. }
  2368. ClientAuthInfo.ServerPrincipalName = NewString;
  2369. ClearGlobalMutex();
  2370. }
  2371. else
  2372. {
  2373. RequestGlobalMutex();
  2374. if ( ClientAuthInfo.ServerPrincipalName != 0 )
  2375. {
  2376. delete ClientAuthInfo.ServerPrincipalName;
  2377. }
  2378. ClientAuthInfo.ServerPrincipalName = NULL;
  2379. ClearGlobalMutex();
  2380. }
  2381. if ( (ClientAuthInfo.Credentials != 0 ) &&
  2382. (ClientAuthInfo.CredentialsMatch(SecurityCredentials) != 0) )
  2383. {
  2384. SecurityCredentials->DereferenceCredentials();
  2385. }
  2386. else
  2387. {
  2388. if (ClientAuthInfo.Credentials != 0)
  2389. {
  2390. ClientAuthInfo.Credentials->DereferenceCredentials();
  2391. }
  2392. ClientAuthInfo.Credentials = SecurityCredentials;
  2393. }
  2394. if (IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC)
  2395. {
  2396. RpcStatus = CaptureModifiedId(&ClientAuthInfo.ModifiedId);
  2397. //
  2398. // If The Thread is not impersonating CaptureLogonId fails
  2399. // All failures get treated as if this process is using *default*
  2400. // identity. Mark the AuthId as such and proceed
  2401. //
  2402. if (RpcStatus != RPC_S_OK)
  2403. {
  2404. ClientAuthInfo.DefaultLogonId = TRUE;
  2405. }
  2406. else
  2407. {
  2408. ClientAuthInfo.DefaultLogonId = FALSE;
  2409. }
  2410. }
  2411. }
  2412. ClientAuthInfo.AuthenticationService = AuthenticationService;
  2413. ClientAuthInfo.AuthorizationService = AuthorizationService;
  2414. ClientAuthInfo.AuthIdentity = AuthIdentity;
  2415. ClientAuthInfo.AdditionalTransportCredentialsType
  2416. = AdditionalTransportCredentialsType;
  2417. if (AuthenticationService == RPC_C_AUTHN_NONE)
  2418. {
  2419. ClientAuthInfo.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
  2420. ClientAuthInfo.AuthenticationLevel = RPC_C_AUTHN_LEVEL_NONE;
  2421. }
  2422. else
  2423. {
  2424. ClientAuthInfo.AuthenticationLevel = MappedAuthenticationLevel;
  2425. ClientAuthInfo.IdentityTracking = IdentityTracking;
  2426. }
  2427. ClientAuthInfo.ImpersonationType = ImpersonationType;
  2428. ClientAuthInfo.Capabilities = Capabilities;
  2429. RequestGlobalMutex();
  2430. if (ClientAuthInfo.ServerSid)
  2431. {
  2432. delete [] ClientAuthInfo.ServerSid;
  2433. ClientAuthInfo.ServerSid = NULL;
  2434. }
  2435. ClearGlobalMutex();
  2436. // we didn't fail - copy the sid
  2437. ClientAuthInfo.ServerSid = SidToDeleteOnFailure;
  2438. return(RPC_S_OK);
  2439. }
  2440. PSID g_pMachineAccountSid = NULL; // a per-process cache for the machine account sid.
  2441. // Once initialized, it never changes. Must be initalized
  2442. // in thread safe manner.
  2443. RPC_STATUS MachineAccountSidLastError = RPC_S_OK; // in case of failure to retrieve the machine
  2444. // account, the last error will be stored here to avoid
  2445. // repeating the failed operation too often.
  2446. ULONG MachineAccountLastFailureTickCount = 0; // the timestamp (as a tick count) of the last
  2447. // failure to retrieve the machine account. Using this variable
  2448. // we can avoid constant machine account lookups in the failure
  2449. // case.
  2450. const ULONG TimeBetweenMachineAccountFailures = 3000; // in milliseconds
  2451. typedef NET_API_STATUS
  2452. (NET_API_FUNCTION *I_NetlogonGetTrustRidFn)
  2453. (
  2454. IN LPWSTR ServerName OPTIONAL,
  2455. IN LPWSTR DomainName OPTIONAL,
  2456. OUT PULONG Rid
  2457. );
  2458. RPC_STATUS GetMachineAccountSid (
  2459. OUT PSID *Sid
  2460. )
  2461. /*++
  2462. Routine Description:
  2463. Gets the machine account sid. The goal is to minimize perf impact
  2464. and to try to avoid at all costs hitting the network. The following approach
  2465. was chosen with ample input and neat tricks from KahrenT & CliffV.
  2466. If machine is in W2K or higher domain:
  2467. I_NetlogonGetTrustRid( NULL, NULL, &Rid ); (In netapi32.dll)
  2468. LsaOpenPolicy (local machine policy)
  2469. LsaQueryInformationPolicy(..., PolicyPrimaryDomainInformation (to use the Sid field)
  2470. LsaClose
  2471. Concatenate the primary domain sid from step 3 and the rid from step 1 using
  2472. NetpDomainIdToSid (in netlib.lib). You could do this step manually or might already
  2473. have a routine to do it.
  2474. If machine is in NT4 domain we apply the following logic.
  2475. A. We know this function is called only as part of NormalizeAccountSid.
  2476. B. We know that NormalizeAccountSid only cares about normalizing the domain SID
  2477. of the machine account
  2478. C. We know that NormalizeSid is only called to normalize a SID, not a machine account
  2479. SPN.
  2480. D. We know that machine accounts cannot be translated to domain SIDs in an NT4 domain.
  2481. We know that the SID we had was produced by translation in an NT4 domain cannot be
  2482. the domain SID of the machine account because of D. We know we have such a SID because
  2483. of A and C. This allows us to conclude that we don't need the machine account in such
  2484. case because of B. Thus in the case of B, we simply return an error we know our caller
  2485. will ignore and thus avoid normalization of the SID in NT4 domain.
  2486. If machine is in NT4 domain, I_NetlogonGetTrustRid will fail with ERROR_NOT_SUPPORTED.
  2487. Arguments:
  2488. Sid - on output will contain the machine account Sid. This is a constant
  2489. pointer that callers must not modify or free. Undefined on failure.
  2490. Return Value:
  2491. RPC_S_OK or RPC_S_* error.
  2492. --*/
  2493. {
  2494. HMODULE NetApi32 = NULL;
  2495. I_NetlogonGetTrustRidFn I_NetlogonGetTrustRidFnPtr;
  2496. RPC_STATUS RpcStatus;
  2497. NET_API_STATUS NetStatus;
  2498. ULONG Rid;
  2499. NTSTATUS NtStatus;
  2500. LSA_OBJECT_ATTRIBUTES loa = { sizeof(LSA_OBJECT_ATTRIBUTES), NULL, NULL, 0, NULL, NULL };
  2501. LSA_HANDLE PolicyHandle;
  2502. POLICY_PRIMARY_DOMAIN_INFO *DomainInfo;
  2503. PSID MachineAccountSid;
  2504. // check the cache first
  2505. if (g_pMachineAccountSid)
  2506. {
  2507. *Sid = g_pMachineAccountSid;
  2508. return RPC_S_OK;
  2509. }
  2510. // before we lookup again, check for recent failure. If there is a recent failure,
  2511. // don't try again for TimeBetweenMachineAccountFailures.
  2512. if (MachineAccountSidLastError)
  2513. {
  2514. RTL_SOFT_ASSERT(MachineAccountLastFailureTickCount != 0);
  2515. if (NtGetTickCount() - MachineAccountLastFailureTickCount < TimeBetweenMachineAccountFailures)
  2516. {
  2517. return MachineAccountSidLastError;
  2518. }
  2519. }
  2520. // there was nothing in the cache - go the long route
  2521. PolicyHandle = NULL;
  2522. DomainInfo = NULL;
  2523. MachineAccountSid = NULL;
  2524. NetApi32 = LoadLibrary(RPC_CONST_SSTRING("netapi32.dll"));
  2525. if (NetApi32 == NULL)
  2526. return RPC_S_OUT_OF_MEMORY;
  2527. I_NetlogonGetTrustRidFnPtr = (I_NetlogonGetTrustRidFn)GetProcAddress(NetApi32, "I_NetlogonGetTrustRid");
  2528. if (I_NetlogonGetTrustRidFnPtr == NULL)
  2529. {
  2530. RpcStatus = RPC_S_INTERNAL_ERROR;
  2531. goto CleanupAndExit;
  2532. }
  2533. // get the RID
  2534. NetStatus = I_NetlogonGetTrustRidFnPtr(NULL, // ServerName
  2535. NULL, // DomainName
  2536. &Rid
  2537. );
  2538. if (NetStatus != NERR_Success)
  2539. {
  2540. if (NetStatus == RPC_S_UNKNOWN_IF
  2541. || NetStatus == ERROR_ACCESS_DENIED)
  2542. return NetStatus;
  2543. if (NetStatus == ERROR_NOT_SUPPORTED)
  2544. {
  2545. // we're in NT4 domain - drop the operation altogether as described
  2546. // in the function header
  2547. NetStatus = ERROR_NO_LOGON_SERVERS;
  2548. }
  2549. if ((NetStatus == ERROR_TRUSTED_RELATIONSHIP_FAILURE)
  2550. || (NetStatus == ERROR_NO_LOGON_SERVERS) )
  2551. {
  2552. MachineAccountSidLastError = NetStatus;
  2553. MachineAccountLastFailureTickCount = NtGetTickCount();
  2554. return NetStatus;
  2555. }
  2556. RpcpErrorAddRecord(EEInfoGCRuntime,
  2557. RPC_S_OUT_OF_MEMORY,
  2558. EEInfoDLGetMachineAccountSid10,
  2559. NetStatus);
  2560. RpcStatus = RPC_S_OUT_OF_MEMORY;
  2561. goto CleanupAndExit;
  2562. }
  2563. // open the local policy
  2564. NtStatus = LsaOpenPolicy (NULL, // SystemName
  2565. &loa, // ObjectAttributes
  2566. POLICY_VIEW_LOCAL_INFORMATION,
  2567. &PolicyHandle
  2568. );
  2569. if (!NT_SUCCESS(NtStatus))
  2570. {
  2571. RpcStatus = RtlNtStatusToDosError(NtStatus);
  2572. RpcpErrorAddRecord(EEInfoGCRuntime,
  2573. RpcStatus,
  2574. EEInfoDLGetMachineAccountSid20,
  2575. NtStatus);
  2576. goto CleanupAndExit;
  2577. }
  2578. // get the domain info
  2579. NtStatus = LsaQueryInformationPolicy (PolicyHandle,
  2580. PolicyPrimaryDomainInformation,
  2581. (PVOID *)&DomainInfo
  2582. );
  2583. if (!NT_SUCCESS(NtStatus))
  2584. {
  2585. RpcStatus = RtlNtStatusToDosError(NtStatus);
  2586. RpcpErrorAddRecord(EEInfoGCRuntime,
  2587. RpcStatus,
  2588. EEInfoDLGetMachineAccountSid30,
  2589. NtStatus);
  2590. goto CleanupAndExit;
  2591. }
  2592. // translate the domain id and the RID to a SID
  2593. NetStatus = NetpDomainIdToSid (DomainInfo->Sid,
  2594. Rid,
  2595. &MachineAccountSid
  2596. );
  2597. if (NetStatus != NERR_Success)
  2598. {
  2599. RpcpErrorAddRecord(EEInfoGCRuntime,
  2600. RPC_S_OUT_OF_MEMORY,
  2601. EEInfoDLGetMachineAccountSid40,
  2602. NetStatus);
  2603. RpcStatus = RPC_S_OUT_OF_MEMORY;
  2604. goto CleanupAndExit;
  2605. }
  2606. // we must have the machine account SID here
  2607. ASSERT(MachineAccountSid);
  2608. if (InterlockedCompareExchangePointer(&g_pMachineAccountSid,
  2609. MachineAccountSid,
  2610. NULL) != NULL)
  2611. {
  2612. // somebody beat us to the punch - free the memory and return
  2613. // the cached value
  2614. NetpMemoryFree(MachineAccountSid);
  2615. }
  2616. *Sid = g_pMachineAccountSid;
  2617. MachineAccountSidLastError = RPC_S_OK;
  2618. RpcStatus = RPC_S_OK;
  2619. CleanupAndExit:
  2620. if (NetApi32 != NULL)
  2621. FreeLibrary(NetApi32);
  2622. if (PolicyHandle)
  2623. {
  2624. NtStatus = LsaClose(PolicyHandle);
  2625. // The underlying context handle may be invalidated under
  2626. // corruption injection.
  2627. CORRUPTION_ASSERT(NT_SUCCESS(NtStatus));
  2628. }
  2629. if (DomainInfo)
  2630. LsaFreeMemory(DomainInfo);
  2631. return RpcStatus;
  2632. }
  2633. RPC_STATUS NormalizeAccountSid (
  2634. IN PSID Sid,
  2635. OUT PSID *NormalizedSid,
  2636. IN OUT int *RetryCount
  2637. )
  2638. /*++
  2639. Routine Description:
  2640. Takes a sid and normalizes it. This involves checking for the machine account
  2641. sid, and if a match is found, translating it to a local system, local service
  2642. or network service SID. If not translation is necessary, the normalized sid
  2643. will be the input sid.
  2644. Arguments:
  2645. Sid - on input, the sid that we are trying to normalize
  2646. NormalizedSid - on output will contain the normalized Sid. This can be a constant
  2647. pointer that callers must not modify or free. Undefined on failure.
  2648. RetryCount - keeps the number of retries to normalize the SID. Caller initializes
  2649. the count to 0 on first call, and this function keeps updating it on each
  2650. retry. If the function sets it to 0 on output, it cannot do any more retries.
  2651. This is necessary because the local machine account sid can be local system,
  2652. network service or local service (S-1-5-18, S-1-5-20 or S-1-5-19) respectively.
  2653. Return Value:
  2654. RPC_S_OK or RPC_S_* error.
  2655. --*/
  2656. {
  2657. PSID MachineAccountSid;
  2658. RPC_STATUS RpcStatus;
  2659. RpcStatus = GetMachineAccountSid (&MachineAccountSid);
  2660. if (RpcStatus != RPC_S_OK)
  2661. {
  2662. // if netlogon hasn't started yet, or isn't configured to run, or
  2663. // the DC cannot be contacted, or we do not have enough priveleges to
  2664. // retrieve the machine account - we cannot retrieve the machine account,
  2665. // and therefore, we will return the original Sid
  2666. if ((RpcStatus == RPC_S_UNKNOWN_IF)
  2667. || (RpcStatus == ERROR_TRUSTED_RELATIONSHIP_FAILURE)
  2668. || (RpcStatus == ERROR_NO_LOGON_SERVERS)
  2669. || (RpcStatus == ERROR_ACCESS_DENIED))
  2670. {
  2671. *NormalizedSid = Sid;
  2672. *RetryCount = 0;
  2673. return RPC_S_OK;
  2674. }
  2675. #if DBG
  2676. DbgPrint("RPCRT4: %X: NormalizeAccountSid: Failed to obtain machine account sid: %X\n",
  2677. GetCurrentProcessId(), RpcStatus);
  2678. #endif // DBG
  2679. return RpcStatus;
  2680. }
  2681. if (EqualSid(MachineAccountSid, Sid))
  2682. {
  2683. switch (*RetryCount)
  2684. {
  2685. case 0:
  2686. *NormalizedSid = (PSID)&LocalSystem;
  2687. (*RetryCount) ++;
  2688. break;
  2689. case 1:
  2690. *NormalizedSid = (PSID)&LocalService;
  2691. (*RetryCount) ++;
  2692. break;
  2693. case 2:
  2694. *NormalizedSid = (PSID)&NetworkService;
  2695. *RetryCount = 0;
  2696. break;
  2697. default:
  2698. ASSERT(!"Invalid RetryCount passed to NormalizeAccountSid");
  2699. }
  2700. }
  2701. else
  2702. {
  2703. *RetryCount = 0;
  2704. *NormalizedSid = Sid;
  2705. }
  2706. return RPC_S_OK;
  2707. }
  2708. const RPC_SYNTAX_IDENTIFIER NDR20TransferSyntaxValue
  2709. = {{0x8A885D04, 0x1CEB, 0x11C9, {0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60}}, {2, 0}};
  2710. const RPC_SYNTAX_IDENTIFIER *NDR20TransferSyntax = &NDR20TransferSyntaxValue;
  2711. const RPC_SYNTAX_IDENTIFIER NDR64TransferSyntaxValue
  2712. = {{0x71710533, 0xBEBA, 0x4937, {0x83, 0x19, 0xB5, 0xDB, 0xEF, 0x9C, 0xCC, 0x36}}, {1, 0}};
  2713. const RPC_SYNTAX_IDENTIFIER *NDR64TransferSyntax = &NDR64TransferSyntaxValue;
  2714. const RPC_SYNTAX_IDENTIFIER NDRTestTransferSyntaxValue
  2715. = {{0xb4537da9, 0x3d03, 0x4f6b, {0xb5, 0x94, 0x52, 0xb2, 0x87, 0x4e, 0xe9, 0xd0}}, {1, 0}};
  2716. const RPC_SYNTAX_IDENTIFIER *NDRTestTransferSyntax = &NDRTestTransferSyntaxValue;