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.

956 lines
25 KiB

  1. /*++
  2. Copyright (c) 1987-1996 Microsoft Corporation
  3. Module Name:
  4. ssiauth.c
  5. Abstract:
  6. Authentication related functions
  7. Author:
  8. Ported from Lan Man 2.0
  9. Environment:
  10. User mode only.
  11. Contains NT-specific code.
  12. Requires ANSI C extensions: slash-slash comments, long external names.
  13. Revision History:
  14. 12-Jul-1991 (cliffv)
  15. Ported to NT. Converted to NT style.
  16. --*/
  17. //
  18. // Common include files.
  19. //
  20. #include "logonsrv.h" // Include files common to entire service
  21. #pragma hdrstop
  22. #include <cryptdll.h>
  23. #include <wincrypt.h> // Crypto apis
  24. LONG NlGlobalSessionCounter = 0;
  25. NTSTATUS
  26. NlMakeSessionKey(
  27. IN ULONG NegotiatedFlags,
  28. IN PNT_OWF_PASSWORD CryptKey,
  29. IN PNETLOGON_CREDENTIAL ClientChallenge,
  30. IN PNETLOGON_CREDENTIAL ServerChallenge,
  31. OUT PNETLOGON_SESSION_KEY SessionKey
  32. )
  33. /*++
  34. Routine Description:
  35. Build an encryption key for use in authentication for
  36. this RequestorName.
  37. Arguments:
  38. NegotiatedFlags - Determines the strength of the key.
  39. CryptKey -- The OWF password of the user account being used.
  40. ClientChallenge -- 8 byte (64 bit) number generated by caller
  41. ServerChallenge -- 8 byte (64 bit) number generated by primary
  42. SessionKey -- 16 byte (128 bit) number generated at both ends
  43. If the key strength is weak, the last 64 bits will be zero.
  44. Return Value:
  45. TRUE: Success
  46. FALSE: Failure
  47. NT status code.
  48. --*/
  49. {
  50. NTSTATUS Status;
  51. BLOCK_KEY BlockKey;
  52. NETLOGON_SESSION_KEY TempSessionKey;
  53. #ifndef NETSETUP_JOIN
  54. PCHECKSUM_BUFFER CheckBuffer = NULL;
  55. PCHECKSUM_FUNCTION Check;
  56. #endif // NETSETUP_JOIN
  57. //
  58. // Start with a zero key
  59. //
  60. RtlZeroMemory(SessionKey, sizeof(NETLOGON_SESSION_KEY));
  61. #ifdef NETSETUP_JOIN
  62. UNREFERENCED_PARAMETER( NegotiatedFlags );
  63. #else // NETSETUP_JOIN
  64. //
  65. // If the caller wants a strong key,
  66. // Compute it.
  67. //
  68. if ( NegotiatedFlags & NETLOGON_SUPPORTS_STRONG_KEY ) {
  69. // PCRYPTO_SYSTEM CryptSystem;
  70. UCHAR LocalChecksum[sizeof(*SessionKey)];
  71. // ULONG OutputSize;
  72. //
  73. // Initialize the checksum routines.
  74. //
  75. Status = CDLocateCheckSum( KERB_CHECKSUM_MD5_HMAC, &Check);
  76. if (!NT_SUCCESS(Status)) {
  77. NlPrint(( NL_CRITICAL,"NlMakeSessionKey: Failed to load checksum routines: 0x%x\n", Status));
  78. goto Cleanup;
  79. }
  80. NlAssert(Check->CheckSumSize <= sizeof(LocalChecksum));
  81. Status = Check->InitializeEx(
  82. (LPBYTE)CryptKey,
  83. sizeof( *CryptKey ),
  84. 0, // no message type
  85. &CheckBuffer );
  86. if (!NT_SUCCESS(Status)) {
  87. NlPrint(( NL_CRITICAL,"NlMakeSessionKey: Failed to initialize checksum routines: 0x%x\n", Status));
  88. goto Cleanup;
  89. }
  90. //
  91. // Sum in the client challenge, a constant, and the server challenge
  92. //
  93. Check->Sum( CheckBuffer,
  94. sizeof(*ClientChallenge),
  95. (PUCHAR)ClientChallenge );
  96. Check->Sum( CheckBuffer,
  97. sizeof(*ServerChallenge),
  98. (PUCHAR)ServerChallenge );
  99. //
  100. // Finish the checksum
  101. //
  102. (void) Check->Finalize(CheckBuffer, LocalChecksum);
  103. //
  104. // Copy the checksum into the message.
  105. //
  106. NlAssert( sizeof(LocalChecksum) >= sizeof(*SessionKey) );
  107. RtlCopyMemory( SessionKey, LocalChecksum, sizeof(*SessionKey) );
  108. //
  109. // Compute weaker (but backward compatible key)
  110. //
  111. } else {
  112. #endif // NETSETUP_JOIN
  113. //
  114. // we will have a 128 bit key (64 bit encrypted rest padded with 0s)
  115. //
  116. // SessionKey = C + P (arithmetic sum ignore carry)
  117. //
  118. *((unsigned long * ) SessionKey) =
  119. *((unsigned long * ) ClientChallenge) +
  120. *((unsigned long * ) ServerChallenge);
  121. *((unsigned long * )((LPBYTE)SessionKey + 4)) =
  122. *((unsigned long * )((LPBYTE)ClientChallenge + 4)) +
  123. *((unsigned long * )((LPBYTE)ServerChallenge + 4));
  124. //
  125. // CryptKey is our 16 byte key to be used as described in codespec
  126. // use first 7 bytes of CryptKey for first encryption
  127. //
  128. RtlCopyMemory( &BlockKey, CryptKey, BLOCK_KEY_LENGTH );
  129. Status = RtlEncryptBlock(
  130. (PCLEAR_BLOCK) SessionKey, // Clear text
  131. &BlockKey, // Key
  132. (PCYPHER_BLOCK) &TempSessionKey); // Cypher Block
  133. if ( !NT_SUCCESS( Status ) ) {
  134. goto Cleanup;
  135. }
  136. //
  137. // Further encrypt the encrypted "SessionKey" using upper 7 bytes
  138. //
  139. NlAssert( LM_OWF_PASSWORD_LENGTH == 2*BLOCK_KEY_LENGTH+2 );
  140. RtlCopyMemory( &BlockKey,
  141. ((PUCHAR)CryptKey) + 2 + BLOCK_KEY_LENGTH,
  142. BLOCK_KEY_LENGTH );
  143. Status = RtlEncryptBlock(
  144. (PCLEAR_BLOCK) &TempSessionKey, // Clear text
  145. &BlockKey, // Key
  146. (PCYPHER_BLOCK) SessionKey); // Cypher Block
  147. if ( !NT_SUCCESS( Status ) ) {
  148. goto Cleanup;
  149. }
  150. #ifndef NETSETUP_JOIN
  151. }
  152. #endif // NETSETUP_JOIN
  153. Cleanup:
  154. #ifndef NETSETUP_JOIN
  155. if (CheckBuffer != NULL) {
  156. Status = Check->Finish(&CheckBuffer);
  157. if (!NT_SUCCESS(Status)) {
  158. NlPrint(( NL_CRITICAL,"NlMakeSessionKey: Failed to finish checksum: 0x%x\n", Status));
  159. }
  160. }
  161. #endif // NETSETUP_JOIN
  162. return Status;
  163. }
  164. #ifdef _DC_NETLOGON
  165. NTSTATUS
  166. NlCheckAuthenticator(
  167. IN OUT PSERVER_SESSION ServerSession,
  168. IN PNETLOGON_AUTHENTICATOR Authenticator,
  169. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator
  170. )
  171. /*++
  172. Routine Description:
  173. Verify that supplied Authenticator is valid.
  174. It is intended for use by the server side after initial authentication
  175. has succeeded. This routine will modify the seed by
  176. first adding the time-of-day received from the Authenticator
  177. and then by incrementing it.
  178. A ReturnAuthenticator is built based on the final seed.
  179. Arguments:
  180. ServerSession - Pointer to the ServerSession structure. The following
  181. fields are used:
  182. SsAuthenticationSeed - Supplies the seed used for authentication and
  183. returns the updated seed.
  184. SsSessionKey - The session key used for encryption.
  185. SsCheck - Is zeroed to indicate successful communication with the client.
  186. Authenticator - The authenticator passed by the caller.
  187. ReturnAuthenticator - The authenticator we'll return to the caller.
  188. Return Value:
  189. STATUS_SUCCESS;
  190. STATUS_ACCESS_DENIED;
  191. STATUS_TIME_DIFFERENCE_AT_DC;
  192. --*/
  193. {
  194. NETLOGON_CREDENTIAL TargetCredential;
  195. NlPrint((NL_CHALLENGE_RES,"NlCheckAuthenticator: Seed = " ));
  196. NlpDumpBuffer(NL_CHALLENGE_RES, &ServerSession->SsAuthenticationSeed, sizeof(ServerSession->SsAuthenticationSeed) );
  197. NlPrint((NL_CHALLENGE_RES, "NlCheckAuthenticator: SessionKey = " ));
  198. NlpDumpBuffer(NL_CHALLENGE_RES, &ServerSession->SsSessionKey, sizeof(ServerSession->SsSessionKey) );
  199. NlPrint((NL_CHALLENGE_RES, "NlCheckAuthenticator: Client Authenticator GOT = " ));
  200. NlpDumpBuffer(NL_CHALLENGE_RES, &Authenticator->Credential, sizeof(Authenticator->Credential) );
  201. NlPrint((NL_CHALLENGE_RES, "NlCheckAuthenticator: Time = " ));
  202. NlpDumpBuffer(NL_CHALLENGE_RES, &Authenticator->timestamp, sizeof(Authenticator->timestamp) );
  203. //
  204. // modify the seed before computing auth_credential for verification
  205. // Two long words are added and overflow carry (if any) ignored
  206. // This will leave upper 4 bytes unchanged
  207. //
  208. *((unsigned long * ) &ServerSession->SsAuthenticationSeed) += Authenticator->timestamp;
  209. NlPrint((NL_CHALLENGE_RES, "NlCheckAuthenticator: Seed + TIME = " ));
  210. NlpDumpBuffer(NL_CHALLENGE_RES, &ServerSession->SsAuthenticationSeed, sizeof(ServerSession->SsAuthenticationSeed) );
  211. //
  212. // Compute TargetCredential to verify the one supplied in the Authenticator
  213. //
  214. NlComputeCredentials( &ServerSession->SsAuthenticationSeed,
  215. &TargetCredential,
  216. &ServerSession->SsSessionKey );
  217. NlPrint((NL_CHALLENGE_RES, "NlCheckAuthenticator: Client Authenticator MADE = " ));
  218. NlpDumpBuffer(NL_CHALLENGE_RES, &TargetCredential, sizeof(TargetCredential) );
  219. //
  220. // verify the computed credentials with those supplied
  221. // Authenticator must have used seed + time_of_day as seed
  222. //
  223. if (!RtlEqualMemory( &Authenticator->Credential,
  224. &TargetCredential,
  225. sizeof(TargetCredential)) ) {
  226. return STATUS_ACCESS_DENIED;
  227. }
  228. //
  229. // modify our seed before computing the ReturnAuthenticator.
  230. // The requestor will increment his seed if he matches this credentials.
  231. //
  232. (*((unsigned long * ) &ServerSession->SsAuthenticationSeed))++;
  233. //
  234. // compute ClientCredential to send back to requestor
  235. //
  236. NlComputeCredentials( &ServerSession->SsAuthenticationSeed,
  237. &ReturnAuthenticator->Credential,
  238. &ServerSession->SsSessionKey);
  239. NlPrint((NL_CHALLENGE_RES,
  240. "NlCheckAuthenticator: Server Authenticator SEND = " ));
  241. NlpDumpBuffer(NL_CHALLENGE_RES, &ReturnAuthenticator->Credential, sizeof(ReturnAuthenticator->Credential) );
  242. NlPrint((NL_CHALLENGE_RES, "NlCheckAuthenticator: Seed + time + 1= " ));
  243. NlpDumpBuffer(NL_CHALLENGE_RES, &ServerSession->SsAuthenticationSeed, sizeof(ServerSession->SsAuthenticationSeed) );
  244. //
  245. // Indicate successful communication with the client
  246. //
  247. ServerSession->SsCheck = 0;
  248. ServerSession->SsPulseTimeoutCount = 0;
  249. ServerSession->SsFlags &= ~SS_PULSE_SENT;
  250. return STATUS_SUCCESS;
  251. }
  252. #endif // _DC_NETLOGON
  253. VOID
  254. NlComputeCredentials(
  255. IN PNETLOGON_CREDENTIAL Challenge,
  256. OUT PNETLOGON_CREDENTIAL Credential,
  257. IN PNETLOGON_SESSION_KEY SessionKey
  258. )
  259. /*++
  260. Routine Description:
  261. Calculate the credentials by encrypting the 8 byte
  262. challenge with first 7 bytes of sessionkey and then
  263. further encrypting it by next 7 bytes of sessionkey.
  264. Arguments:
  265. Challenge - Supplies the 8 byte (64 bit) challenge
  266. Credential - Returns the 8 byte (64 bit) number generated
  267. SessionKey - Supplies 14 byte (112 bit) encryption key
  268. The buffer is 16 bytes (128 bits) long. For a weak key, the trailing 8 bytes
  269. are zero. For a strong key, this routine ingored that trailing 2 bytes of
  270. useful key.
  271. Return Value:
  272. NONE
  273. --*/
  274. {
  275. NTSTATUS Status;
  276. BLOCK_KEY BlockKey;
  277. CYPHER_BLOCK IntermediateBlock;
  278. RtlZeroMemory(Credential, sizeof(*Credential));
  279. //
  280. // use first 7 bytes of SessionKey for first encryption
  281. //
  282. RtlCopyMemory( &BlockKey, SessionKey, BLOCK_KEY_LENGTH );
  283. Status = RtlEncryptBlock( (PCLEAR_BLOCK) Challenge, // Cleartext
  284. &BlockKey, // Key
  285. &IntermediateBlock ); // Cypher Block
  286. NlAssert( NT_SUCCESS(Status) );
  287. //
  288. // further encrypt the encrypted Credential using next 7 bytes
  289. //
  290. RtlCopyMemory( &BlockKey,
  291. ((PUCHAR)SessionKey) + BLOCK_KEY_LENGTH,
  292. BLOCK_KEY_LENGTH );
  293. Status = RtlEncryptBlock( (PCLEAR_BLOCK) &IntermediateBlock, // Cleartext
  294. &BlockKey, // Key
  295. Credential ); // Cypher Block
  296. NlAssert( NT_SUCCESS(Status) );
  297. return;
  298. }
  299. VOID
  300. NlComputeChallenge(
  301. OUT PNETLOGON_CREDENTIAL Challenge
  302. )
  303. /*++
  304. Routine Description:
  305. Generates a 64 bit challenge
  306. Arguments:
  307. Challenge - Returns the computed challenge
  308. Return Value:
  309. None.
  310. --*/
  311. {
  312. //
  313. // Use an ideal random bit generator.
  314. //
  315. if (!NlGenerateRandomBits( (LPBYTE)Challenge, sizeof(*Challenge) )) {
  316. NlPrint((NL_CRITICAL, "Can't NlGenerateRandomBits\n" ));
  317. }
  318. return;
  319. }
  320. VOID
  321. NlBuildAuthenticator(
  322. IN OUT PNETLOGON_CREDENTIAL AuthenticationSeed,
  323. IN PNETLOGON_SESSION_KEY SessionKey,
  324. OUT PNETLOGON_AUTHENTICATOR Authenticator
  325. )
  326. /*++
  327. Routine Description:
  328. Build the authenticator to be sent to primary.
  329. This routine will modify the seed by adding the
  330. time-of-day before computing the credentials.
  331. Arguments:
  332. AuthenticationSeed -- The current authentication seed. This seed will
  333. have the current time of day added to it prior to building the
  334. Authenticator.
  335. SessionKey - The Session Key used for encrypting the Authenticator.
  336. Authenticator - The Authenticator to pass to the PDC for the current
  337. call.
  338. Return Value:
  339. NT Status code
  340. --*/
  341. {
  342. NTSTATUS Status;
  343. LARGE_INTEGER TimeNow;
  344. //
  345. // Use the current time of day to modify the authentication seed
  346. //
  347. RtlZeroMemory(Authenticator, sizeof(*Authenticator));
  348. NlQuerySystemTime( &TimeNow );
  349. Status = RtlTimeToSecondsSince1970( &TimeNow, &Authenticator->timestamp );
  350. NlAssert( NT_SUCCESS(Status) );
  351. //
  352. // Modify the AuthenticationSeed before computing auth_credential for
  353. // verification .
  354. //
  355. // Two long words are added and overflow carry (if any) ignored
  356. // This will leave upper 4 bytes unchanged
  357. //
  358. NlPrint((NL_CHALLENGE_RES,"NlBuildAuthenticator: Old Seed = " ));
  359. NlpDumpBuffer(NL_CHALLENGE_RES, AuthenticationSeed, sizeof(*AuthenticationSeed) );
  360. NlPrint((NL_CHALLENGE_RES,"NlBuildAuthenticator: Time = " ));
  361. NlpDumpBuffer(NL_CHALLENGE_RES, &Authenticator->timestamp, sizeof(Authenticator->timestamp) );
  362. *((unsigned long * ) AuthenticationSeed) += Authenticator->timestamp;
  363. NlPrint((NL_CHALLENGE_RES,"NlBuildAuthenticator: New Seed = " ));
  364. NlpDumpBuffer(NL_CHALLENGE_RES, AuthenticationSeed, sizeof(*AuthenticationSeed) );
  365. NlPrint((NL_CHALLENGE_RES, "NlBuildAuthenticator: SessionKey = " ));
  366. NlpDumpBuffer(NL_CHALLENGE_RES, SessionKey, sizeof(*SessionKey) );
  367. //
  368. // compute AuthenticationSeed to verify the one supplied by Requestor
  369. //
  370. NlComputeCredentials( AuthenticationSeed,
  371. &Authenticator->Credential,
  372. SessionKey);
  373. NlPrint((NL_CHALLENGE_RES,"NlBuildAuthenticator: Client Authenticator = " ));
  374. NlpDumpBuffer(NL_CHALLENGE_RES, &Authenticator->Credential, sizeof(Authenticator->Credential) );
  375. return;
  376. }
  377. BOOL
  378. NlUpdateSeed(
  379. IN OUT PNETLOGON_CREDENTIAL AuthenticationSeed,
  380. IN PNETLOGON_CREDENTIAL TargetCredential,
  381. IN PNETLOGON_SESSION_KEY SessionKey
  382. )
  383. /*++
  384. Routine Description:
  385. Called by the initiator of a communication over the secure channel
  386. following a successful transaction.
  387. The PDC would have incremented the seed so we must do so also.
  388. We also verify that the incremented seed builds a credential identical
  389. to the one passed back by the PDC.
  390. Arguments:
  391. AuthenticationSeed - Pointer to the AuthenticationSeed to be incremented.
  392. TargetCredential - Supplies the Credential that the incremented
  393. AuthenticationSeed should encrypt to.
  394. SessionKey - Supplies the encryption key to use for the encryption.
  395. Return Value:
  396. TRUE: Success
  397. FALSE: Failure
  398. --*/
  399. {
  400. NETLOGON_CREDENTIAL NewCredential;
  401. //
  402. // modify our AuthenticationSeed before computing NewCredential to check
  403. // those returned from primary (NewSeed = AuthenticationSeed+1)
  404. //
  405. (*((unsigned long * ) AuthenticationSeed))++;
  406. NlPrint((NL_CHALLENGE_RES,"NlUpdateSeed: Seed + time + 1= " ));
  407. NlpDumpBuffer(NL_CHALLENGE_RES, AuthenticationSeed, sizeof(*AuthenticationSeed) );
  408. //
  409. // Compute ClientCredential to check which came from primary
  410. //
  411. NlComputeCredentials(AuthenticationSeed, &NewCredential, SessionKey);
  412. NlPrint((NL_CHALLENGE_RES,"NlUpdateSeed: Server Authenticator GOT = " ));
  413. NlpDumpBuffer(NL_CHALLENGE_RES, TargetCredential, sizeof(*TargetCredential) );
  414. NlPrint((NL_CHALLENGE_RES,"NlUpdateSeed: Server Authenticator MADE = " ));
  415. NlpDumpBuffer(NL_CHALLENGE_RES, &NewCredential, sizeof(NewCredential) );
  416. if ( !RtlEqualMemory( TargetCredential, &NewCredential, sizeof(NewCredential)) ) {
  417. return FALSE;
  418. }
  419. //
  420. // Done
  421. //
  422. return TRUE;
  423. }
  424. VOID
  425. NlEncryptRC4(
  426. IN OUT PVOID Buffer,
  427. IN ULONG BufferSize,
  428. IN PSESSION_INFO SessionInfo
  429. )
  430. /*++
  431. Routine Description:
  432. Encrypt data using RC4 with the session key as the key.
  433. Arguments:
  434. Buffer -- Buffer containing the data to encrypt in place.
  435. BufferSize -- Size (in bytes) of Buffer.
  436. SessionInfo -- Info describing secure channel
  437. Return Value:
  438. NT status code
  439. --*/
  440. {
  441. NTSTATUS NtStatus;
  442. DATA_KEY KeyData;
  443. CRYPT_BUFFER Data;
  444. //
  445. // Build a data buffer to describe the encryption key.
  446. //
  447. KeyData.Length = sizeof(NETLOGON_SESSION_KEY);
  448. KeyData.MaximumLength = sizeof(NETLOGON_SESSION_KEY);
  449. KeyData.Buffer = (PVOID)&SessionInfo->SessionKey;
  450. NlAssert( SessionInfo->NegotiatedFlags & NETLOGON_SUPPORTS_RC4_ENCRYPTION );
  451. //
  452. // Build a data buffer to decribe the encrypted data.
  453. //
  454. Data.Length = Data.MaximumLength = BufferSize;
  455. Data.Buffer = Buffer;
  456. //
  457. // Encrypt the data.
  458. //
  459. IF_NL_DEBUG( ENCRYPT ) {
  460. NlPrint((NL_ENCRYPT, "NlEncryptRC4: Clear data: " ));
  461. NlpDumpBuffer( NL_ENCRYPT, Data.Buffer, Data.Length );
  462. }
  463. NtStatus = RtlEncryptData2( &Data, &KeyData );
  464. NlAssert( NT_SUCCESS(NtStatus) );
  465. IF_NL_DEBUG( ENCRYPT ) {
  466. NlPrint((NL_ENCRYPT, "NlEncryptRC4: Encrypted data: " ));
  467. NlpDumpBuffer( NL_ENCRYPT, Data.Buffer, Data.Length );
  468. }
  469. }
  470. VOID
  471. NlDecryptRC4(
  472. IN OUT PVOID Buffer,
  473. IN ULONG BufferSize,
  474. IN PSESSION_INFO SessionInfo
  475. )
  476. /*++
  477. Routine Description:
  478. Decrypt data using RC4 with the session key as the key.
  479. Arguments:
  480. Buffer -- Buffer containing the data to decrypt in place.
  481. BufferSize -- Size (in bytes) of Buffer.
  482. SessionInfo -- Info describing secure channel
  483. Return Value:
  484. NT status code
  485. --*/
  486. {
  487. NTSTATUS NtStatus;
  488. DATA_KEY KeyData;
  489. CRYPT_BUFFER Data;
  490. //
  491. // Build a data buffer to describe the encryption key.
  492. //
  493. KeyData.Length = sizeof(NETLOGON_SESSION_KEY);
  494. KeyData.MaximumLength = sizeof(NETLOGON_SESSION_KEY);
  495. KeyData.Buffer = (PVOID)&SessionInfo->SessionKey;
  496. NlAssert( SessionInfo->NegotiatedFlags & NETLOGON_SUPPORTS_RC4_ENCRYPTION );
  497. //
  498. // Build a data buffer to decribe the encrypted data.
  499. //
  500. Data.Length = Data.MaximumLength = BufferSize;
  501. Data.Buffer = Buffer;
  502. //
  503. // Encrypt the data.
  504. //
  505. IF_NL_DEBUG( ENCRYPT ) {
  506. NlPrint((NL_ENCRYPT, "NlDecryptRC4: Encrypted data: " ));
  507. NlpDumpBuffer( NL_ENCRYPT, Data.Buffer, Data.Length );
  508. }
  509. NtStatus = RtlDecryptData2( &Data, &KeyData );
  510. NlAssert( NT_SUCCESS(NtStatus) );
  511. IF_NL_DEBUG( ENCRYPT ) {
  512. NlPrint((NL_ENCRYPT, "NlDecryptRC4: Clear data: " ));
  513. NlpDumpBuffer( NL_ENCRYPT, Data.Buffer, Data.Length );
  514. }
  515. }
  516. BOOLEAN
  517. NlGenerateRandomBits(
  518. PUCHAR Buffer,
  519. ULONG BufferLen
  520. )
  521. /*++
  522. Routine Description:
  523. Generates random bits
  524. Arguments:
  525. pBuffer - Buffer to fill
  526. cbBuffer - Number of bytes in buffer
  527. Return Value:
  528. Status of the operation.
  529. --*/
  530. {
  531. if( !CryptGenRandom( NlGlobalCryptProvider, BufferLen, ( LPBYTE )Buffer ) )
  532. {
  533. NlPrint((NL_CRITICAL, "CryptGenRandom failed with %lu\n", GetLastError() ));
  534. return FALSE;
  535. }
  536. return TRUE;
  537. }
  538. #ifndef NETSETUP_JOIN
  539. VOID
  540. NlPrintTrustedDomain(
  541. PDS_DOMAIN_TRUSTSW TrustedDomain,
  542. IN BOOLEAN VerbosePrint,
  543. IN BOOLEAN AnsiOutput
  544. )
  545. /*++
  546. Routine Description:
  547. Print a trusted domain structure
  548. Arguments:
  549. TrustedDomain -- Structure to print
  550. VerbosePrint - If TRUE, output domain's GUID and SID
  551. AnsiOutput - If TRUE, names are in ansi format
  552. Return Value:
  553. None.
  554. --*/
  555. {
  556. if ( AnsiOutput ) {
  557. if ( TrustedDomain->NetbiosDomainName != NULL ) {
  558. NlPrint(( NL_LOGON, " %s", TrustedDomain->NetbiosDomainName ));
  559. }
  560. if ( TrustedDomain->DnsDomainName != NULL ) {
  561. NlPrint(( NL_LOGON, " %s", TrustedDomain->DnsDomainName ));
  562. }
  563. } else {
  564. if ( TrustedDomain->NetbiosDomainName != NULL ) {
  565. NlPrint(( NL_LOGON, " %ws", TrustedDomain->NetbiosDomainName ));
  566. }
  567. if ( TrustedDomain->DnsDomainName != NULL ) {
  568. NlPrint(( NL_LOGON, " %ws", TrustedDomain->DnsDomainName ));
  569. }
  570. }
  571. switch ( TrustedDomain->TrustType ) {
  572. case TRUST_TYPE_DOWNLEVEL:
  573. NlPrint(( NL_LOGON, " (NT 4)" ); break);
  574. case TRUST_TYPE_UPLEVEL:
  575. NlPrint(( NL_LOGON, " (NT 5)" ); break);
  576. case TRUST_TYPE_MIT:
  577. NlPrint(( NL_LOGON, " (MIT)" ); break);
  578. default:
  579. NlPrint(( NL_LOGON, " (Unknown Trust Type: %ld)", TrustedDomain->TrustType ); break);
  580. }
  581. if ( TrustedDomain->Flags ) {
  582. ULONG Flags;
  583. Flags = TrustedDomain->Flags;
  584. if ( Flags & DS_DOMAIN_IN_FOREST ) {
  585. if ( Flags & DS_DOMAIN_TREE_ROOT ) {
  586. NlPrint(( NL_LOGON, " (Forest Tree Root)" ));
  587. Flags &= ~DS_DOMAIN_TREE_ROOT;
  588. } else {
  589. NlPrint(( NL_LOGON, " (Forest: %ld)", TrustedDomain->ParentIndex ));
  590. }
  591. Flags &= ~DS_DOMAIN_IN_FOREST;
  592. }
  593. if ( Flags & DS_DOMAIN_DIRECT_OUTBOUND ) {
  594. NlPrint(( NL_LOGON, " (Direct Outbound)"));
  595. Flags &= ~DS_DOMAIN_DIRECT_OUTBOUND;
  596. }
  597. if ( Flags & DS_DOMAIN_DIRECT_INBOUND ) {
  598. NlPrint(( NL_LOGON, " (Direct Inbound)"));
  599. Flags &= ~DS_DOMAIN_DIRECT_INBOUND;
  600. }
  601. if ( Flags & DS_DOMAIN_TREE_ROOT ) {
  602. NlPrint(( NL_LOGON, " (Tree Root but not in forest!!!!)"));
  603. Flags &= ~DS_DOMAIN_TREE_ROOT;
  604. }
  605. if ( Flags & DS_DOMAIN_PRIMARY ) {
  606. NlPrint(( NL_LOGON, " (Primary Domain)"));
  607. Flags &= ~DS_DOMAIN_PRIMARY;
  608. }
  609. if ( Flags & DS_DOMAIN_NATIVE_MODE ) {
  610. NlPrint(( NL_LOGON, " (Native)"));
  611. Flags &= ~DS_DOMAIN_NATIVE_MODE;
  612. }
  613. if ( Flags != 0 ) {
  614. NlPrint(( NL_LOGON, " 0x%lX", Flags));
  615. }
  616. }
  617. if ( TrustedDomain->TrustAttributes ) {
  618. ULONG TrustAttributes = TrustedDomain->TrustAttributes;
  619. NlPrint(( NL_LOGON, " ( Attr:" ));
  620. if ( TrustAttributes & TRUST_ATTRIBUTE_NON_TRANSITIVE ) {
  621. NlPrint(( NL_LOGON, " non-trans"));
  622. TrustAttributes &= ~TRUST_ATTRIBUTE_NON_TRANSITIVE;
  623. }
  624. if ( TrustAttributes & TRUST_ATTRIBUTE_UPLEVEL_ONLY ) {
  625. NlPrint(( NL_LOGON, " uplevel-only"));
  626. TrustAttributes &= ~TRUST_ATTRIBUTE_UPLEVEL_ONLY;
  627. }
  628. if ( TrustAttributes & TRUST_ATTRIBUTE_QUARANTINED_DOMAIN ) {
  629. NlPrint(( NL_LOGON, " quarantined"));
  630. TrustAttributes &= ~TRUST_ATTRIBUTE_QUARANTINED_DOMAIN;
  631. }
  632. if ( TrustAttributes != 0 ) {
  633. NlPrint(( NL_LOGON, " 0x%lX", TrustAttributes));
  634. }
  635. NlPrint(( NL_LOGON, " )"));
  636. }
  637. //
  638. // Output domain's GUID and SID
  639. //
  640. if ( VerbosePrint ) {
  641. if ( !IsEqualGUID( &TrustedDomain->DomainGuid, &NlGlobalZeroGuid) ) {
  642. RPC_STATUS RpcStatus;
  643. char *StringGuid;
  644. NlPrint(( NL_LOGON, "\n" ));
  645. NlPrint(( NL_LOGON, " Dom Guid: " ));
  646. RpcStatus = UuidToStringA( &TrustedDomain->DomainGuid, &StringGuid );
  647. if ( RpcStatus == RPC_S_OK ) {
  648. NlPrint(( NL_LOGON, "%s", StringGuid ));
  649. RpcStringFreeA( &StringGuid );
  650. } else {
  651. NlPrint(( NL_LOGON, "Not available because UuidToStringA failed" ));
  652. }
  653. }
  654. NlPrint(( NL_LOGON, "\n" ));
  655. if ( TrustedDomain->DomainSid != NULL ) {
  656. NlPrint(( NL_LOGON, " Dom Sid: " ));
  657. NlpDumpSid( NL_LOGON, TrustedDomain->DomainSid );
  658. }
  659. } else {
  660. NlPrint(( NL_LOGON, "\n" ));
  661. }
  662. }
  663. #endif // NETSETUP_JOIN