Source code of Windows XP (NT5)
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.

2594 lines
63 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. nlp.c
  5. Abstract:
  6. This file is the contains private routines which support
  7. for the LAN Manager portions of the MSV1_0 authentication package.
  8. Author:
  9. Cliff Van Dyke 29-Apr-1991
  10. Revision History:
  11. Chandana Surlu 21-Jul-96 Stolen from \\kernel\razzle3\src\security\msv1_0\nlp.c
  12. --*/
  13. #include <global.h>
  14. #include "msp.h"
  15. #include "nlp.h"
  16. #include "nlpcache.h"
  17. #include "msvwow.h"
  18. DWORD
  19. NlpCopyDomainRelativeSid(
  20. OUT PSID TargetSid,
  21. IN PSID DomainId,
  22. IN ULONG RelativeId
  23. );
  24. VOID
  25. NlpPutString(
  26. IN PUNICODE_STRING OutString,
  27. IN PUNICODE_STRING InString,
  28. IN PUCHAR *Where
  29. )
  30. /*++
  31. Routine Description:
  32. This routine copies the InString string to the memory pointed to by
  33. the Where parameter, and fixes the OutString string to point to that
  34. new copy.
  35. Parameters:
  36. OutString - A pointer to a destination NT string
  37. InString - A pointer to an NT string to be copied
  38. Where - A pointer to space to put the actual string for the
  39. OutString. The pointer is adjusted to point to the first byte
  40. following the copied string.
  41. Return Values:
  42. None.
  43. --*/
  44. {
  45. ASSERT( OutString != NULL );
  46. ASSERT( InString != NULL );
  47. ASSERT( Where != NULL && *Where != NULL);
  48. ASSERT( *Where == ROUND_UP_POINTER( *Where, sizeof(WCHAR) ) );
  49. #ifdef notdef
  50. KdPrint(("NlpPutString: %ld %Z\n", InString->Length, InString ));
  51. KdPrint((" InString: %lx %lx OutString: %lx Where: %lx\n", InString,
  52. InString->Buffer, OutString, *Where ));
  53. #endif
  54. if ( InString->Length > 0 ) {
  55. OutString->Buffer = (PWCH) *Where;
  56. OutString->MaximumLength = (USHORT)(InString->Length + sizeof(WCHAR));
  57. RtlCopyUnicodeString( OutString, InString );
  58. *Where += InString->Length;
  59. // *((WCHAR *)(*Where)) = L'\0';
  60. *(*Where) = '\0';
  61. *(*Where + 1) = '\0';
  62. *Where += 2;
  63. } else {
  64. RtlInitUnicodeString(OutString, NULL);
  65. }
  66. #ifdef notdef
  67. KdPrint((" OutString: %ld %lx\n", OutString->Length, OutString->Buffer));
  68. #endif
  69. return;
  70. }
  71. VOID
  72. NlpInitClientBuffer(
  73. OUT PCLIENT_BUFFER_DESC ClientBufferDesc,
  74. IN PLSA_CLIENT_REQUEST ClientRequest
  75. )
  76. /*++
  77. Routine Description:
  78. This routine initializes a ClientBufferDescriptor to known values.
  79. This routine must be called before any of the other routines that use
  80. the ClientBufferDescriptor.
  81. Parameters:
  82. ClientBufferDesc - Descriptor of a buffer allocated in the client's
  83. address space.
  84. ClientRequest - Is a pointer to an opaque data structure
  85. representing the client's request.
  86. Return Values:
  87. None.
  88. --*/
  89. {
  90. //
  91. // Fill in a pointer to the ClientRequest and zero the rest.
  92. //
  93. ClientBufferDesc->ClientRequest = ClientRequest;
  94. ClientBufferDesc->UserBuffer = NULL;
  95. ClientBufferDesc->MsvBuffer = NULL;
  96. ClientBufferDesc->StringOffset = 0;
  97. ClientBufferDesc->TotalSize = 0;
  98. }
  99. NTSTATUS
  100. NlpAllocateClientBuffer(
  101. IN OUT PCLIENT_BUFFER_DESC ClientBufferDesc,
  102. IN ULONG FixedSize,
  103. IN ULONG TotalSize
  104. )
  105. /*++
  106. Routine Description:
  107. This routine allocates a buffer in the clients address space.
  108. It also allocates a mirror buffer in MSV's address space.
  109. The data will be constructed in the MSV's address space then 'flushed'
  110. into the client's address space.
  111. Parameters:
  112. ClientBufferDesc - Descriptor of a buffer allocated in the client's
  113. address space.
  114. FixedSize - The size in bytes of the fixed portion of the buffer.
  115. TotalSize - The size in bytes of the entire buffer.
  116. Return Values:
  117. Status of the operation.
  118. --*/
  119. {
  120. NTSTATUS Status = STATUS_SUCCESS;
  121. //
  122. // Allocate the Mirror buffer.
  123. //
  124. ASSERT( ClientBufferDesc->MsvBuffer == NULL );
  125. ClientBufferDesc->MsvBuffer = I_NtLmAllocate( TotalSize );
  126. if ( ClientBufferDesc->MsvBuffer == NULL ) {
  127. return STATUS_NO_MEMORY;
  128. }
  129. //
  130. // Allocate the client's buffer
  131. //
  132. ASSERT( ClientBufferDesc->UserBuffer == NULL );
  133. if ((ClientBufferDesc->ClientRequest == (PLSA_CLIENT_REQUEST) (-1)))
  134. {
  135. ClientBufferDesc->UserBuffer = (*(Lsa.AllocateLsaHeap))(TotalSize);
  136. }
  137. else
  138. {
  139. Status = (*Lsa.AllocateClientBuffer)(
  140. ClientBufferDesc->ClientRequest,
  141. TotalSize,
  142. (PVOID *)&ClientBufferDesc->UserBuffer );
  143. }
  144. if ((ClientBufferDesc->ClientRequest == (PLSA_CLIENT_REQUEST) (-1)))
  145. {
  146. if (ClientBufferDesc->UserBuffer == NULL)
  147. {
  148. NlpFreeClientBuffer( ClientBufferDesc );
  149. return STATUS_NO_MEMORY;
  150. }
  151. }
  152. else
  153. {
  154. if ( !NT_SUCCESS( Status ) ) {
  155. ClientBufferDesc->UserBuffer = NULL;
  156. NlpFreeClientBuffer( ClientBufferDesc );
  157. return Status;
  158. }
  159. }
  160. //
  161. // Return
  162. //
  163. ClientBufferDesc->StringOffset = FixedSize;
  164. ClientBufferDesc->TotalSize = TotalSize;
  165. return STATUS_SUCCESS;
  166. }
  167. NTSTATUS
  168. NlpFlushClientBuffer(
  169. IN OUT PCLIENT_BUFFER_DESC ClientBufferDesc,
  170. OUT PVOID* UserBuffer
  171. )
  172. /*++
  173. Routine Description:
  174. Copy the Mirror Buffer into the Client's address space.
  175. Parameters:
  176. ClientBufferDesc - Descriptor of a buffer allocated in the client's
  177. address space.
  178. UserBuffer - If successful, returns a pointer to the user's buffer.
  179. (The caller is now resposible for deallocating the buffer.)
  180. Return Values:
  181. Status of the operation.
  182. --*/
  183. {
  184. NTSTATUS Status = STATUS_SUCCESS;
  185. //
  186. // Copy the data to the client's address space.
  187. //
  188. if ((ClientBufferDesc->ClientRequest == (PLSA_CLIENT_REQUEST) (-1)))
  189. {
  190. RtlCopyMemory(
  191. ClientBufferDesc->UserBuffer,
  192. ClientBufferDesc->MsvBuffer,
  193. ClientBufferDesc->TotalSize);
  194. }
  195. else
  196. {
  197. Status = (*Lsa.CopyToClientBuffer)(
  198. ClientBufferDesc->ClientRequest,
  199. ClientBufferDesc->TotalSize,
  200. ClientBufferDesc->UserBuffer,
  201. ClientBufferDesc->MsvBuffer );
  202. }
  203. if ( !NT_SUCCESS( Status ) ) {
  204. return Status;
  205. }
  206. //
  207. // Mark that we're no longer responsible for the client's buffer.
  208. //
  209. *UserBuffer = (PVOID) ClientBufferDesc->UserBuffer;
  210. ClientBufferDesc->UserBuffer = NULL;
  211. //
  212. // Free the mirror buffer
  213. //
  214. NlpFreeClientBuffer( ClientBufferDesc );
  215. return STATUS_SUCCESS;
  216. }
  217. VOID
  218. NlpFreeClientBuffer(
  219. IN OUT PCLIENT_BUFFER_DESC ClientBufferDesc
  220. )
  221. /*++
  222. Routine Description:
  223. Free any Mirror Buffer or Client buffer.
  224. Parameters:
  225. ClientBufferDesc - Descriptor of a buffer allocated in the client's
  226. address space.
  227. Return Values:
  228. None
  229. --*/
  230. {
  231. //
  232. // Free the mirror buffer.
  233. //
  234. if ( ClientBufferDesc->MsvBuffer != NULL ) {
  235. I_NtLmFree( ClientBufferDesc->MsvBuffer );
  236. ClientBufferDesc->MsvBuffer = NULL;
  237. }
  238. //
  239. // Free the Client's buffer
  240. //
  241. if ((ClientBufferDesc->ClientRequest == (PLSA_CLIENT_REQUEST) (-1)))
  242. {
  243. if ( ClientBufferDesc->UserBuffer != NULL ) {
  244. (*Lsa.FreeLsaHeap)(ClientBufferDesc->UserBuffer);
  245. ClientBufferDesc->UserBuffer = NULL;
  246. }
  247. }
  248. else
  249. {
  250. if ( ClientBufferDesc->UserBuffer != NULL ) {
  251. (VOID) (*Lsa.FreeClientBuffer)( ClientBufferDesc->ClientRequest,
  252. ClientBufferDesc->UserBuffer );
  253. ClientBufferDesc->UserBuffer = NULL;
  254. }
  255. }
  256. }
  257. VOID
  258. NlpPutClientString(
  259. IN OUT PCLIENT_BUFFER_DESC ClientBufferDesc,
  260. IN PUNICODE_STRING OutString,
  261. IN PUNICODE_STRING InString
  262. )
  263. /*++
  264. Routine Description:
  265. This routine copies the InString string to the memory pointed to by
  266. ClientBufferDesc->StringOffset, and fixes the OutString string to point
  267. to that new copy.
  268. Parameters:
  269. ClientBufferDesc - Descriptor of a buffer allocated in the client's
  270. address space.
  271. InString - A pointer to an NT string to be copied
  272. OutString - A pointer to a destination NT string. This string structure
  273. is in the "Mirror" allocated buffer.
  274. Return Status:
  275. STATUS_SUCCESS - Indicates the service completed successfully.
  276. --*/
  277. {
  278. //
  279. // Ensure our caller passed good data.
  280. //
  281. ASSERT( OutString != NULL );
  282. ASSERT( InString != NULL );
  283. ASSERT( COUNT_IS_ALIGNED( ClientBufferDesc->StringOffset, sizeof(WCHAR)) );
  284. ASSERT( (LPBYTE)OutString >= ClientBufferDesc->MsvBuffer );
  285. ASSERT( (LPBYTE)OutString <
  286. ClientBufferDesc->MsvBuffer + ClientBufferDesc->TotalSize - sizeof(UNICODE_STRING) );
  287. ASSERT( ClientBufferDesc->StringOffset + InString->Length + sizeof(WCHAR) <=
  288. ClientBufferDesc->TotalSize );
  289. #ifdef notdef
  290. KdPrint(("NlpPutClientString: %ld %Z\n", InString->Length, InString ));
  291. KdPrint((" Orig: UserBuffer: %lx Offset: 0x%lx TotalSize: 0x%lx\n",
  292. ClientBufferDesc->UserBuffer,
  293. ClientBufferDesc->StringOffset,
  294. ClientBufferDesc->TotalSize ));
  295. #endif
  296. //
  297. // Build a string structure and copy the text to the Mirror buffer.
  298. //
  299. if ( InString->Length > 0 ) {
  300. //
  301. // Copy the string (Add a zero character)
  302. //
  303. RtlCopyMemory(
  304. ClientBufferDesc->MsvBuffer + ClientBufferDesc->StringOffset,
  305. InString->Buffer,
  306. InString->Length );
  307. // Do one byte at a time since some callers don't pass in an even
  308. // InString->Length
  309. *(ClientBufferDesc->MsvBuffer + ClientBufferDesc->StringOffset +
  310. InString->Length) = '\0';
  311. *(ClientBufferDesc->MsvBuffer + ClientBufferDesc->StringOffset +
  312. InString->Length+1) = '\0';
  313. //
  314. // Build the string structure to point to the data in the client's
  315. // address space.
  316. //
  317. OutString->Buffer = (PWSTR)(ClientBufferDesc->UserBuffer +
  318. ClientBufferDesc->StringOffset);
  319. OutString->Length = InString->Length;
  320. OutString->MaximumLength = OutString->Length + sizeof(WCHAR);
  321. //
  322. // Adjust the offset to past the newly copied string.
  323. //
  324. ClientBufferDesc->StringOffset += OutString->MaximumLength;
  325. } else {
  326. RtlInitUnicodeString(OutString, NULL);
  327. }
  328. #ifdef notdef
  329. KdPrint((" New: Offset: 0x%lx StringStart: %lx\n",
  330. ClientBufferDesc->StringOffset,
  331. OutString->Buffer ));
  332. #endif
  333. return;
  334. }
  335. VOID
  336. NlpMakeRelativeString(
  337. IN PUCHAR BaseAddress,
  338. IN OUT PUNICODE_STRING String
  339. )
  340. /*++
  341. Routine Description:
  342. This routine converts the buffer address in the specified string to
  343. be a byte offset from BaseAddress.
  344. Parameters:
  345. BaseAddress - A pointer to make the destination address relative to.
  346. String - A pointer to a NT string to make relative.
  347. Return Values:
  348. None.
  349. --*/
  350. {
  351. ASSERT( BaseAddress != NULL );
  352. ASSERT( String != NULL );
  353. ASSERT( sizeof(ULONG_PTR) == sizeof(String->Buffer) );
  354. if ( String->Buffer != NULL ) {
  355. *((PULONG_PTR)(&String->Buffer)) =
  356. (ULONG_PTR)((PUCHAR)String->Buffer - (PUCHAR)BaseAddress);
  357. }
  358. return;
  359. }
  360. VOID
  361. NlpRelativeToAbsolute(
  362. IN PVOID BaseAddress,
  363. IN OUT PULONG_PTR RelativeValue
  364. )
  365. /*++
  366. Routine Description:
  367. This routine converts the byte offset from BaseAddress to be an
  368. absolute address.
  369. Parameters:
  370. BaseAddress - A pointer the destination address is relative to.
  371. RelativeValue - A pointer to a relative value to make absolute.
  372. Return Values:
  373. None.
  374. --*/
  375. {
  376. ASSERT( BaseAddress != NULL );
  377. ASSERT( RelativeValue != NULL );
  378. if ( *((PUCHAR *)RelativeValue) != NULL ) {
  379. *RelativeValue = (ULONG_PTR)((PUCHAR)BaseAddress + (*RelativeValue));
  380. }
  381. return;
  382. }
  383. BOOLEAN
  384. NlpFindActiveLogon(
  385. IN PLUID LogonId,
  386. OUT PACTIVE_LOGON **ActiveLogon
  387. )
  388. /*++
  389. Routine Description:
  390. This routine finds the specified Logon Id in the ActiveLogon table.
  391. It returns a boolean indicating whether the Logon Id exists in the
  392. ActiveLogon Table. If so, this routine also returns a pointer to a
  393. pointer to the appropriate entry in the table. If not, this routine
  394. returns a pointer to where such an entry would be inserted in the table.
  395. This routine must be called with the NlpActiveLogonLock locked.
  396. Parameters:
  397. LogonId - The LogonId of the logon to find in the table.
  398. ActiveLogon - If the specified logon Id exists, returns a pointer to a
  399. pointer to the appropriate entry in the table. Otherwise,
  400. returns a pointer to where such an entry would be inserted in the
  401. table.
  402. Return Values:
  403. TRUE - The specified LogonId already exists in the table.
  404. FALSE - The specified LogonId does not exist in the table.
  405. --*/
  406. {
  407. PACTIVE_LOGON *Logon;
  408. //
  409. // Loop through the table looking for this particular LogonId.
  410. //
  411. for( Logon = &NlpActiveLogons; *Logon != NULL; Logon = &((*Logon)->Next) ) {
  412. if (RtlCompareMemory( &(*Logon)->LogonId, LogonId, sizeof(*LogonId))
  413. == sizeof(*LogonId) ) {
  414. *ActiveLogon = Logon;
  415. return TRUE;
  416. }
  417. }
  418. //
  419. // By returning a pointer to the NULL at the end of the list, we
  420. // are forcing new entries to be placed at the end. The list is
  421. // thereby maintained in the order that the logon occurred.
  422. // MsV1_0EnumerateUsers relies on this behavior.
  423. //
  424. *ActiveLogon = Logon;
  425. return FALSE;
  426. }
  427. ULONG
  428. NlpCountActiveLogon(
  429. IN PUNICODE_STRING LogonDomainName,
  430. IN PUNICODE_STRING UserName
  431. )
  432. /*++
  433. Routine Description:
  434. This routine counts the number of time a particular user is logged on
  435. in the Active Logon Table.
  436. Parameters:
  437. LogonDomainName - Domain in which this user account is defined.
  438. UserName - The user name to count the active logons for.
  439. Return Values:
  440. The count of active logons for the specified user.
  441. --*/
  442. {
  443. PACTIVE_LOGON Logon;
  444. ULONG LogonCount = 0;
  445. //
  446. // Loop through the table looking for this particular LogonId.
  447. //
  448. NlpLockActiveLogonsRead();
  449. for( Logon = NlpActiveLogons; Logon != NULL; Logon = Logon->Next ) {
  450. if(RtlEqualUnicodeString( UserName, &Logon->UserName, (BOOLEAN) TRUE) &&
  451. RtlEqualDomainName(LogonDomainName,&Logon->LogonDomainName )){
  452. LogonCount ++;
  453. }
  454. }
  455. NlpUnlockActiveLogons();
  456. return LogonCount;
  457. }
  458. NTSTATUS
  459. NlpAllocateInteractiveProfile (
  460. IN PLSA_CLIENT_REQUEST ClientRequest,
  461. OUT PMSV1_0_INTERACTIVE_PROFILE *ProfileBuffer,
  462. OUT PULONG ProfileBufferSize,
  463. IN PNETLOGON_VALIDATION_SAM_INFO4 NlpUser
  464. )
  465. /*++
  466. Routine Description:
  467. This allocates and fills in the clients interactive profile.
  468. Arguments:
  469. ClientRequest - Is a pointer to an opaque data structure
  470. representing the client's request.
  471. ProfileBuffer - Is used to return the address of the profile
  472. buffer in the client process. This routine is
  473. responsible for allocating and returning the profile buffer
  474. within the client process. However, if the caller subsequently
  475. encounters an error which prevents a successful logon, then
  476. then it will take care of deallocating the buffer. This
  477. buffer is allocated with the AllocateClientBuffer() service.
  478. ProfileBufferSize - Receives the Size (in bytes) of the
  479. returned profile buffer.
  480. NlpUser - Contains the validation information which is
  481. to be copied in the ProfileBuffer.
  482. Return Value:
  483. STATUS_SUCCESS - Indicates the service completed successfully.
  484. STATUS_QUOTA_EXCEEDED - This error indicates that the logon
  485. could not be completed because the client does not have
  486. sufficient quota to allocate the return buffer.
  487. --*/
  488. {
  489. NTSTATUS Status;
  490. CLIENT_BUFFER_DESC ClientBufferDesc;
  491. PMSV1_0_INTERACTIVE_PROFILE LocalProfileBuffer;
  492. #if _WIN64
  493. if( ClientRequest != (PLSA_CLIENT_REQUEST)( -1 ) )
  494. {
  495. SECPKG_CALL_INFO CallInfo;
  496. //
  497. // if the call originated outproc, need to check if wow64.
  498. //
  499. if(!LsaFunctions->GetCallInfo(&CallInfo))
  500. {
  501. Status = STATUS_INTERNAL_ERROR;
  502. goto Cleanup;
  503. }
  504. if (CallInfo.Attributes & SECPKG_CALL_WOWCLIENT)
  505. {
  506. return MsvAllocateInteractiveWOWProfile (
  507. ClientRequest,
  508. ProfileBuffer,
  509. ProfileBufferSize,
  510. NlpUser
  511. );
  512. }
  513. }
  514. #endif // _WIN64
  515. //
  516. // Alocate the profile buffer to return to the client
  517. //
  518. NlpInitClientBuffer( &ClientBufferDesc, ClientRequest );
  519. *ProfileBuffer = NULL;
  520. *ProfileBufferSize = sizeof(MSV1_0_INTERACTIVE_PROFILE) +
  521. NlpUser->LogonScript.Length + sizeof(WCHAR) +
  522. NlpUser->HomeDirectory.Length + sizeof(WCHAR) +
  523. NlpUser->HomeDirectoryDrive.Length + sizeof(WCHAR) +
  524. NlpUser->FullName.Length + sizeof(WCHAR) +
  525. NlpUser->ProfilePath.Length + sizeof(WCHAR) +
  526. NlpUser->LogonServer.Length + sizeof(WCHAR);
  527. Status = NlpAllocateClientBuffer( &ClientBufferDesc,
  528. sizeof(MSV1_0_INTERACTIVE_PROFILE),
  529. *ProfileBufferSize );
  530. if ( !NT_SUCCESS( Status ) ) {
  531. goto Cleanup;
  532. }
  533. LocalProfileBuffer = (PMSV1_0_INTERACTIVE_PROFILE) ClientBufferDesc.MsvBuffer;
  534. //
  535. // Copy the scalar fields into the profile buffer.
  536. //
  537. LocalProfileBuffer->MessageType = MsV1_0InteractiveProfile;
  538. LocalProfileBuffer->LogonCount = NlpUser->LogonCount;
  539. LocalProfileBuffer->BadPasswordCount= NlpUser->BadPasswordCount;
  540. OLD_TO_NEW_LARGE_INTEGER( NlpUser->LogonTime,
  541. LocalProfileBuffer->LogonTime );
  542. OLD_TO_NEW_LARGE_INTEGER( NlpUser->LogoffTime,
  543. LocalProfileBuffer->LogoffTime );
  544. OLD_TO_NEW_LARGE_INTEGER( NlpUser->KickOffTime,
  545. LocalProfileBuffer->KickOffTime );
  546. OLD_TO_NEW_LARGE_INTEGER( NlpUser->PasswordLastSet,
  547. LocalProfileBuffer->PasswordLastSet );
  548. OLD_TO_NEW_LARGE_INTEGER( NlpUser->PasswordCanChange,
  549. LocalProfileBuffer->PasswordCanChange );
  550. OLD_TO_NEW_LARGE_INTEGER( NlpUser->PasswordMustChange,
  551. LocalProfileBuffer->PasswordMustChange );
  552. LocalProfileBuffer->UserFlags = NlpUser->UserFlags;
  553. //
  554. // Copy the Unicode strings into the profile buffer.
  555. //
  556. NlpPutClientString( &ClientBufferDesc,
  557. &LocalProfileBuffer->LogonScript,
  558. &NlpUser->LogonScript );
  559. NlpPutClientString( &ClientBufferDesc,
  560. &LocalProfileBuffer->HomeDirectory,
  561. &NlpUser->HomeDirectory );
  562. NlpPutClientString( &ClientBufferDesc,
  563. &LocalProfileBuffer->HomeDirectoryDrive,
  564. &NlpUser->HomeDirectoryDrive );
  565. NlpPutClientString( &ClientBufferDesc,
  566. &LocalProfileBuffer->FullName,
  567. &NlpUser->FullName );
  568. NlpPutClientString( &ClientBufferDesc,
  569. &LocalProfileBuffer->ProfilePath,
  570. &NlpUser->ProfilePath );
  571. NlpPutClientString( &ClientBufferDesc,
  572. &LocalProfileBuffer->LogonServer,
  573. &NlpUser->LogonServer );
  574. //
  575. // Flush the buffer to the client's address space.
  576. //
  577. Status = NlpFlushClientBuffer( &ClientBufferDesc,
  578. (PVOID *) ProfileBuffer );
  579. Cleanup:
  580. //
  581. // If the copy wasn't successful,
  582. // cleanup resources we would have returned to the caller.
  583. //
  584. if ( !NT_SUCCESS(Status) ) {
  585. NlpFreeClientBuffer( &ClientBufferDesc );
  586. }
  587. return Status;
  588. }
  589. NTSTATUS
  590. NlpAllocateNetworkProfile (
  591. IN PLSA_CLIENT_REQUEST ClientRequest,
  592. OUT PMSV1_0_LM20_LOGON_PROFILE *ProfileBuffer,
  593. OUT PULONG ProfileBufferSize,
  594. IN PNETLOGON_VALIDATION_SAM_INFO4 NlpUser,
  595. IN ULONG ParameterControl
  596. )
  597. /*++
  598. Routine Description:
  599. This allocates and fills in the clients network profile.
  600. Arguments:
  601. ClientRequest - Is a pointer to an opaque data structure
  602. representing the client's request.
  603. ProfileBuffer - Is used to return the address of the profile
  604. buffer in the client process. This routine is
  605. responsible for allocating and returning the profile buffer
  606. within the client process. However, if the caller subsequently
  607. encounters an error which prevents a successful logon, then
  608. then it will take care of deallocating the buffer. This
  609. buffer is allocated with the AllocateClientBuffer() service.
  610. ProfileBufferSize - Receives the Size (in bytes) of the
  611. returned profile buffer.
  612. NlpUser - Contains the validation information which is
  613. to be copied in the ProfileBuffer. Will be NULL to indicate a
  614. NULL session.
  615. Return Value:
  616. STATUS_SUCCESS - Indicates the service completed successfully.
  617. STATUS_QUOTA_EXCEEDED - This error indicates that the logon
  618. could not be completed because the client does not have
  619. sufficient quota to allocate the return buffer.
  620. --*/
  621. {
  622. NTSTATUS Status;
  623. NTSTATUS SubAuthStatus = STATUS_SUCCESS;
  624. CLIENT_BUFFER_DESC ClientBufferDesc;
  625. PMSV1_0_LM20_LOGON_PROFILE LocalProfile;
  626. #if _WIN64
  627. if( ClientRequest != (PLSA_CLIENT_REQUEST)( -1 ) )
  628. {
  629. SECPKG_CALL_INFO CallInfo;
  630. //
  631. // if the call originated outproc, need to check if wow64.
  632. //
  633. if(!LsaFunctions->GetCallInfo(&CallInfo))
  634. {
  635. Status = STATUS_INTERNAL_ERROR;
  636. goto Cleanup;
  637. }
  638. if (CallInfo.Attributes & SECPKG_CALL_WOWCLIENT)
  639. {
  640. return MsvAllocateNetworkWOWProfile (
  641. ClientRequest,
  642. ProfileBuffer,
  643. ProfileBufferSize,
  644. NlpUser,
  645. ParameterControl
  646. );
  647. }
  648. }
  649. #endif // _WIN64
  650. //
  651. // Alocate the profile buffer to return to the client
  652. //
  653. NlpInitClientBuffer( &ClientBufferDesc, ClientRequest );
  654. *ProfileBuffer = NULL;
  655. *ProfileBufferSize = sizeof(MSV1_0_LM20_LOGON_PROFILE);
  656. if ( NlpUser != NULL ) {
  657. *ProfileBufferSize += NlpUser->LogonDomainName.Length + sizeof(WCHAR) +
  658. NlpUser->LogonServer.Length + sizeof(WCHAR) +
  659. NlpUser->HomeDirectoryDrive.Length + sizeof(WCHAR);
  660. }
  661. Status = NlpAllocateClientBuffer( &ClientBufferDesc,
  662. sizeof(MSV1_0_LM20_LOGON_PROFILE),
  663. *ProfileBufferSize );
  664. if ( !NT_SUCCESS( Status ) ) {
  665. goto Cleanup;
  666. }
  667. LocalProfile = (PMSV1_0_LM20_LOGON_PROFILE) ClientBufferDesc.MsvBuffer;
  668. LocalProfile->MessageType = MsV1_0Lm20LogonProfile;
  669. //
  670. // For a NULL session, return a constant profile buffer
  671. //
  672. if ( NlpUser == NULL ) {
  673. LocalProfile->KickOffTime.HighPart = 0x7FFFFFFF;
  674. LocalProfile->KickOffTime.LowPart = 0xFFFFFFFF;
  675. LocalProfile->LogoffTime.HighPart = 0x7FFFFFFF;
  676. LocalProfile->LogoffTime.LowPart = 0xFFFFFFFF;
  677. LocalProfile->UserFlags = 0;
  678. RtlZeroMemory( LocalProfile->UserSessionKey,
  679. sizeof(LocalProfile->UserSessionKey));
  680. RtlZeroMemory( LocalProfile->LanmanSessionKey,
  681. sizeof(LocalProfile->LanmanSessionKey));
  682. RtlInitUnicodeString( &LocalProfile->LogonDomainName, NULL );
  683. RtlInitUnicodeString( &LocalProfile->LogonServer, NULL );
  684. RtlInitUnicodeString( &LocalProfile->UserParameters, NULL );
  685. //
  686. // For non-null sessions,
  687. // fill in the profile buffer.
  688. //
  689. } else {
  690. //
  691. // Copy the individual scalar fields into the profile buffer.
  692. //
  693. if ((ParameterControl & MSV1_0_RETURN_PASSWORD_EXPIRY) != 0) {
  694. OLD_TO_NEW_LARGE_INTEGER( NlpUser->PasswordMustChange,
  695. LocalProfile->LogoffTime);
  696. } else {
  697. OLD_TO_NEW_LARGE_INTEGER( NlpUser->LogoffTime,
  698. LocalProfile->LogoffTime);
  699. }
  700. OLD_TO_NEW_LARGE_INTEGER( NlpUser->KickOffTime,
  701. LocalProfile->KickOffTime);
  702. LocalProfile->UserFlags = NlpUser->UserFlags;
  703. RtlCopyMemory( LocalProfile->UserSessionKey,
  704. &NlpUser->UserSessionKey,
  705. sizeof(LocalProfile->UserSessionKey) );
  706. ASSERT( SAMINFO_LM_SESSION_KEY_SIZE ==
  707. sizeof(LocalProfile->LanmanSessionKey) );
  708. RtlCopyMemory(
  709. LocalProfile->LanmanSessionKey,
  710. &NlpUser->ExpansionRoom[SAMINFO_LM_SESSION_KEY],
  711. SAMINFO_LM_SESSION_KEY_SIZE );
  712. // We need to extract the true status sent back for subauth users,
  713. // but not by a sub auth package
  714. SubAuthStatus = NlpUser->ExpansionRoom[SAMINFO_SUBAUTH_STATUS];
  715. //
  716. // Copy the Unicode strings into the profile buffer.
  717. //
  718. NlpPutClientString( &ClientBufferDesc,
  719. &LocalProfile->LogonDomainName,
  720. &NlpUser->LogonDomainName );
  721. NlpPutClientString( &ClientBufferDesc,
  722. &LocalProfile->LogonServer,
  723. &NlpUser->LogonServer );
  724. //
  725. // Kludge: Pass back UserParameters in HomeDirectoryDrive since we
  726. // can't change the NETLOGON_VALIDATION_SAM_INFO structure between
  727. // releases NT 1.0 and NT 1.0A. HomeDirectoryDrive was NULL for release 1.0A
  728. // so we'll use that field.
  729. //
  730. NlpPutClientString( &ClientBufferDesc,
  731. &LocalProfile->UserParameters,
  732. &NlpUser->HomeDirectoryDrive );
  733. }
  734. //
  735. // Flush the buffer to the client's address space.
  736. //
  737. Status = NlpFlushClientBuffer( &ClientBufferDesc,
  738. ProfileBuffer );
  739. Cleanup:
  740. //
  741. // If the copy wasn't successful,
  742. // cleanup resources we would have returned to the caller.
  743. //
  744. if ( !NT_SUCCESS(Status) ) {
  745. NlpFreeClientBuffer( &ClientBufferDesc );
  746. }
  747. // Save the status for subauth logons
  748. if (NT_SUCCESS(Status) && !NT_SUCCESS(SubAuthStatus))
  749. {
  750. Status = SubAuthStatus;
  751. }
  752. return Status;
  753. }
  754. PSID
  755. NlpMakeDomainRelativeSid(
  756. IN PSID DomainId,
  757. IN ULONG RelativeId
  758. )
  759. /*++
  760. Routine Description:
  761. Given a domain Id and a relative ID create the corresponding SID allocated
  762. from the LSA heap.
  763. Arguments:
  764. DomainId - The template SID to use.
  765. RelativeId - The relative Id to append to the DomainId.
  766. Return Value:
  767. Sid - Returns a pointer to a buffer allocated from the LsaHeap
  768. containing the resultant Sid.
  769. --*/
  770. {
  771. UCHAR DomainIdSubAuthorityCount;
  772. ULONG Size;
  773. PSID Sid;
  774. //
  775. // Allocate a Sid which has one more sub-authority than the domain ID.
  776. //
  777. DomainIdSubAuthorityCount = *(RtlSubAuthorityCountSid( DomainId ));
  778. Size = RtlLengthRequiredSid(DomainIdSubAuthorityCount+1);
  779. if ((Sid = (*Lsa.AllocateLsaHeap)( Size )) == NULL ) {
  780. return NULL;
  781. }
  782. //
  783. // Initialize the new SID to have the same inital value as the
  784. // domain ID.
  785. //
  786. if ( !NT_SUCCESS( RtlCopySid( Size, Sid, DomainId ) ) ) {
  787. (*Lsa.FreeLsaHeap)( Sid );
  788. return NULL;
  789. }
  790. //
  791. // Adjust the sub-authority count and
  792. // add the relative Id unique to the newly allocated SID
  793. //
  794. (*(RtlSubAuthorityCountSid( Sid ))) ++;
  795. *RtlSubAuthoritySid( Sid, DomainIdSubAuthorityCount ) = RelativeId;
  796. return Sid;
  797. }
  798. PSID
  799. NlpCopySid(
  800. IN PSID * Sid
  801. )
  802. /*++
  803. Routine Description:
  804. Given a SID allocatees space for a new SID from the LSA heap and copies
  805. the original SID.
  806. Arguments:
  807. Sid - The original SID.
  808. Return Value:
  809. Sid - Returns a pointer to a buffer allocated from the LsaHeap
  810. containing the resultant Sid.
  811. --*/
  812. {
  813. PSID NewSid;
  814. ULONG Size;
  815. Size = RtlLengthSid( Sid );
  816. if ((NewSid = (*Lsa.AllocateLsaHeap)( Size )) == NULL ) {
  817. return NULL;
  818. }
  819. if ( !NT_SUCCESS( RtlCopySid( Size, NewSid, Sid ) ) ) {
  820. (*Lsa.FreeLsaHeap)( NewSid );
  821. return NULL;
  822. }
  823. return NewSid;
  824. }
  825. //+-------------------------------------------------------------------------
  826. //
  827. // Function: NlpMakeTokenInformationV2
  828. //
  829. // Synopsis: This routine makes copies of all the pertinent
  830. // information from the UserInfo and generates a
  831. // LSA_TOKEN_INFORMATION_V2 data structure.
  832. //
  833. // Effects:
  834. //
  835. // Arguments:
  836. //
  837. // UserInfo - Contains the validation information which is
  838. // to be copied into the TokenInformation.
  839. //
  840. // TokenInformation - Returns a pointer to a properly Version 1 token
  841. // information structures. The structure and individual fields are
  842. // allocated properly as described in ntlsa.h.
  843. //
  844. // Requires:
  845. //
  846. // Returns: STATUS_SUCCESS - Indicates the service completed successfully.
  847. //
  848. // STATUS_INSUFFICIENT_RESOURCES - This error indicates that
  849. // the logon could not be completed because the client
  850. // does not have sufficient quota to allocate the return
  851. // buffer.
  852. //
  853. // Notes: stolen back from from kerberos\client2\krbtoken.cxx.c:KerbMakeTokenInformationV1
  854. //
  855. //
  856. //--------------------------------------------------------------------------
  857. NTSTATUS
  858. NlpMakeTokenInformationV2(
  859. IN PNETLOGON_VALIDATION_SAM_INFO4 ValidationInfo,
  860. OUT PLSA_TOKEN_INFORMATION_V2 *TokenInformation
  861. )
  862. {
  863. PNETLOGON_VALIDATION_SAM_INFO3 UserInfo = (PNETLOGON_VALIDATION_SAM_INFO3) ValidationInfo;
  864. NTSTATUS Status;
  865. PLSA_TOKEN_INFORMATION_V2 V2 = NULL;
  866. ULONG Size, i;
  867. DWORD NumGroups = 0;
  868. PBYTE CurrentSid = NULL;
  869. ULONG SidLength = 0;
  870. //
  871. // Allocate the structure itself
  872. //
  873. Size = (ULONG)sizeof(LSA_TOKEN_INFORMATION_V2);
  874. //
  875. // Allocate an array to hold the groups
  876. //
  877. Size += sizeof(TOKEN_GROUPS);
  878. // Add room for groups passed as RIDS
  879. NumGroups = UserInfo->GroupCount;
  880. if(UserInfo->GroupCount)
  881. {
  882. Size += UserInfo->GroupCount * (RtlLengthSid(UserInfo->LogonDomainId) + sizeof(ULONG));
  883. }
  884. //
  885. // If there are extra SIDs, add space for them
  886. //
  887. if (UserInfo->UserFlags & LOGON_EXTRA_SIDS) {
  888. ULONG i = 0;
  889. NumGroups += UserInfo->SidCount;
  890. // Add room for the sid's themselves
  891. for(i=0; i < UserInfo->SidCount; i++)
  892. {
  893. Size += RtlLengthSid(UserInfo->ExtraSids[i].Sid);
  894. }
  895. }
  896. //
  897. // If there are resource groups, add space for them
  898. //
  899. if (UserInfo->UserFlags & LOGON_RESOURCE_GROUPS) {
  900. NumGroups += UserInfo->ResourceGroupCount;
  901. if ((UserInfo->ResourceGroupCount != 0) &&
  902. ((UserInfo->ResourceGroupIds == NULL) ||
  903. (UserInfo->ResourceGroupDomainSid == NULL)))
  904. {
  905. Status = STATUS_INVALID_PARAMETER;
  906. goto Cleanup;
  907. }
  908. // Allocate space for the sids
  909. if(UserInfo->ResourceGroupCount)
  910. {
  911. Size += UserInfo->ResourceGroupCount * (RtlLengthSid(UserInfo->ResourceGroupDomainSid) + sizeof(ULONG));
  912. }
  913. }
  914. if( UserInfo->UserId )
  915. {
  916. // Size of the user sid and the primary group sid.
  917. Size += 2*(RtlLengthSid(UserInfo->LogonDomainId) + sizeof(ULONG));
  918. }
  919. else
  920. {
  921. if ( UserInfo->SidCount <= 0 ) {
  922. Status = STATUS_INSUFFICIENT_LOGON_INFO;
  923. goto Cleanup;
  924. }
  925. // Size of the primary group sid.
  926. Size += (RtlLengthSid(UserInfo->LogonDomainId) + sizeof(ULONG));
  927. }
  928. Size += (NumGroups - ANYSIZE_ARRAY)*sizeof(SID_AND_ATTRIBUTES);
  929. V2 = (PLSA_TOKEN_INFORMATION_V2) (*Lsa.AllocateLsaHeap)( Size );
  930. if ( V2 == NULL ) {
  931. return STATUS_INSUFFICIENT_RESOURCES;
  932. }
  933. RtlZeroMemory(
  934. V2,
  935. Size
  936. );
  937. V2->Groups = (PTOKEN_GROUPS)(V2+1);
  938. V2->Groups->GroupCount = 0;
  939. CurrentSid = (PBYTE)&V2->Groups->Groups[NumGroups];
  940. OLD_TO_NEW_LARGE_INTEGER( UserInfo->KickOffTime, V2->ExpirationTime );
  941. //
  942. // If the UserId is non-zero, then it contians the users RID.
  943. //
  944. if ( UserInfo->UserId ) {
  945. V2->User.User.Sid = (PSID)CurrentSid;
  946. CurrentSid += NlpCopyDomainRelativeSid((PSID)CurrentSid, UserInfo->LogonDomainId, UserInfo->UserId);
  947. }
  948. //
  949. // Make a copy of the primary group (a required field).
  950. //
  951. V2->PrimaryGroup.PrimaryGroup = (PSID)CurrentSid;
  952. CurrentSid += NlpCopyDomainRelativeSid((PSID)CurrentSid, UserInfo->LogonDomainId, UserInfo->PrimaryGroupId );
  953. //
  954. // Copy over all the groups passed as RIDs
  955. //
  956. for ( i=0; i < UserInfo->GroupCount; i++ ) {
  957. V2->Groups->Groups[V2->Groups->GroupCount].Attributes = UserInfo->GroupIds[i].Attributes;
  958. V2->Groups->Groups[V2->Groups->GroupCount].Sid = (PSID)CurrentSid;
  959. CurrentSid += NlpCopyDomainRelativeSid((PSID)CurrentSid, UserInfo->LogonDomainId, UserInfo->GroupIds[i].RelativeId);
  960. V2->Groups->GroupCount++;
  961. }
  962. //
  963. // Add in the extra SIDs
  964. //
  965. if (UserInfo->UserFlags & LOGON_EXTRA_SIDS) {
  966. ULONG index = 0;
  967. //
  968. // If the user SID wasn't passed as a RID, it is the first
  969. // SID.
  970. //
  971. if ( !V2->User.User.Sid ) {
  972. V2->User.User.Sid = (PSID)CurrentSid;
  973. SidLength = RtlLengthSid(UserInfo->ExtraSids[index].Sid);
  974. RtlCopySid(SidLength, (PSID)CurrentSid, UserInfo->ExtraSids[index].Sid);
  975. CurrentSid += SidLength;
  976. index++;
  977. }
  978. //
  979. // Copy over all additional SIDs as groups.
  980. //
  981. for ( ; index < UserInfo->SidCount; index++ ) {
  982. V2->Groups->Groups[V2->Groups->GroupCount].Attributes =
  983. UserInfo->ExtraSids[index].Attributes;
  984. V2->Groups->Groups[V2->Groups->GroupCount].Sid= (PSID)CurrentSid;
  985. SidLength = RtlLengthSid(UserInfo->ExtraSids[index].Sid);
  986. RtlCopySid(SidLength, (PSID)CurrentSid, UserInfo->ExtraSids[index].Sid);
  987. CurrentSid += SidLength;
  988. V2->Groups->GroupCount++;
  989. }
  990. }
  991. //
  992. // Check to see if any resouce groups exist
  993. //
  994. if (UserInfo->UserFlags & LOGON_RESOURCE_GROUPS) {
  995. for ( i=0; i < UserInfo->ResourceGroupCount; i++ ) {
  996. V2->Groups->Groups[V2->Groups->GroupCount].Attributes = UserInfo->ResourceGroupIds[i].Attributes;
  997. V2->Groups->Groups[V2->Groups->GroupCount].Sid= (PSID)CurrentSid;
  998. CurrentSid += NlpCopyDomainRelativeSid((PSID)CurrentSid, UserInfo->ResourceGroupDomainSid, UserInfo->ResourceGroupIds[i].RelativeId);
  999. V2->Groups->GroupCount++;
  1000. }
  1001. }
  1002. ASSERT( ((PBYTE)V2 + Size) == CurrentSid );
  1003. if (!V2->User.User.Sid) {
  1004. Status = STATUS_INSUFFICIENT_LOGON_INFO;
  1005. goto Cleanup;
  1006. }
  1007. //
  1008. // There are no default privileges supplied.
  1009. // We don't have an explicit owner SID.
  1010. // There is no default DACL.
  1011. //
  1012. V2->Privileges = NULL;
  1013. V2->Owner.Owner = NULL;
  1014. V2->DefaultDacl.DefaultDacl = NULL;
  1015. //
  1016. // Return the Validation Information to the caller.
  1017. //
  1018. *TokenInformation = V2;
  1019. return STATUS_SUCCESS;
  1020. //
  1021. // Deallocate any memory we've allocated
  1022. //
  1023. Cleanup:
  1024. (*Lsa.FreeLsaHeap)( V2 );
  1025. return Status;
  1026. }
  1027. VOID
  1028. NlpPutOwfsInPrimaryCredential(
  1029. IN PUNICODE_STRING CleartextPassword,
  1030. OUT PMSV1_0_PRIMARY_CREDENTIAL Credential
  1031. )
  1032. /*++
  1033. Routine Description:
  1034. This routine puts the OWFs for the specified clear password into
  1035. the passed in Credential structure.
  1036. Arguments:
  1037. CleartextPassword - Is a string containing the user's cleartext password.
  1038. The password may be up to 255 characters long and contain any
  1039. UNICODE value.
  1040. Credential - A pointer to the credential to update.
  1041. Return Value:
  1042. STATUS_SUCCESS - Indicates the service completed successfully.
  1043. STATUS_QUOTA_EXCEEDED - This error indicates that the logon
  1044. could not be completed because the client does not have
  1045. sufficient quota to allocate the return buffer.
  1046. --*/
  1047. {
  1048. NTSTATUS Status;
  1049. //
  1050. // Compute the Ansi version to the Cleartext password.
  1051. //
  1052. // The Ansi version of the Cleartext password is at most 14 bytes long,
  1053. // exists in a trailing zero filled 15 byte buffer,
  1054. // is uppercased.
  1055. //
  1056. Credential->LmPasswordPresent = FALSE;
  1057. if( CleartextPassword->Length <= (LM20_PWLEN*sizeof(WCHAR)) )
  1058. {
  1059. CHAR LmPassword[LM20_PWLEN+1];
  1060. STRING AnsiCleartextPassword;
  1061. AnsiCleartextPassword.Buffer = LmPassword;
  1062. AnsiCleartextPassword.Length = sizeof(LmPassword);
  1063. AnsiCleartextPassword.MaximumLength = AnsiCleartextPassword.Length;
  1064. Status = RtlUpcaseUnicodeStringToOemString(
  1065. &AnsiCleartextPassword,
  1066. CleartextPassword,
  1067. (BOOLEAN) FALSE );
  1068. if( NT_SUCCESS( Status ) )
  1069. {
  1070. //
  1071. // Save the OWF encrypted versions of the passwords.
  1072. //
  1073. Status = RtlCalculateLmOwfPassword( LmPassword,
  1074. &Credential->LmOwfPassword );
  1075. ASSERT( NT_SUCCESS(Status) );
  1076. Credential->LmPasswordPresent = TRUE;
  1077. }
  1078. //
  1079. // Don't leave passwords around in the pagefile
  1080. //
  1081. RtlZeroMemory( LmPassword, sizeof(LmPassword) );
  1082. }
  1083. Status = RtlCalculateNtOwfPassword( CleartextPassword,
  1084. &Credential->NtOwfPassword );
  1085. ASSERT( NT_SUCCESS(Status) );
  1086. Credential->NtPasswordPresent = TRUE;
  1087. Status = RtlCalculateShaOwfPassword( CleartextPassword,
  1088. &Credential->ShaOwfPassword );
  1089. ASSERT( NT_SUCCESS(Status) );
  1090. Credential->ShaPasswordPresent = TRUE;
  1091. return;
  1092. }
  1093. NTSTATUS
  1094. NlpMakePrimaryCredential(
  1095. IN PUNICODE_STRING LogonDomainName,
  1096. IN PUNICODE_STRING UserName,
  1097. IN PUNICODE_STRING CleartextPassword,
  1098. OUT PMSV1_0_PRIMARY_CREDENTIAL *CredentialBuffer,
  1099. OUT PULONG CredentialSize
  1100. )
  1101. /*++
  1102. Routine Description:
  1103. This routine makes a primary credential for the given user nam and
  1104. password.
  1105. Arguments:
  1106. LogonDomainName - Is a string representing the domain in which the user's
  1107. account is defined.
  1108. UserName - Is a string representing the user's account name. The
  1109. name may be up to 255 characters long. The name is treated case
  1110. insensitive.
  1111. CleartextPassword - Is a string containing the user's cleartext password.
  1112. The password may be up to 255 characters long and contain any
  1113. UNICODE value.
  1114. CredentialBuffer - Returns a pointer to the specified credential allocated
  1115. on the LsaHeap. It is the callers responsibility to deallocate
  1116. this credential.
  1117. CredentialSize - the size of the allocated credential buffer (in bytes).
  1118. Return Value:
  1119. STATUS_SUCCESS - Indicates the service completed successfully.
  1120. STATUS_QUOTA_EXCEEDED - This error indicates that the logon
  1121. could not be completed because the client does not have
  1122. sufficient quota to allocate the return buffer.
  1123. --*/
  1124. {
  1125. PMSV1_0_PRIMARY_CREDENTIAL Credential;
  1126. NTSTATUS Status;
  1127. PUCHAR Where;
  1128. ULONG PaddingLength;
  1129. //
  1130. // Build the credential
  1131. //
  1132. *CredentialSize = sizeof(MSV1_0_PRIMARY_CREDENTIAL) +
  1133. LogonDomainName->Length + sizeof(WCHAR) +
  1134. UserName->Length + sizeof(WCHAR);
  1135. //
  1136. // add padding for memory encryption interface.
  1137. //
  1138. PaddingLength = DESX_BLOCKLEN - (*CredentialSize % DESX_BLOCKLEN);
  1139. if( PaddingLength == DESX_BLOCKLEN )
  1140. {
  1141. PaddingLength = 0;
  1142. }
  1143. *CredentialSize += PaddingLength;
  1144. Credential = (*Lsa.AllocateLsaHeap)( *CredentialSize );
  1145. if ( Credential == NULL ) {
  1146. KdPrint(("MSV1_0: NlpMakePrimaryCredential: No memory %ld\n",
  1147. *CredentialSize ));
  1148. return STATUS_QUOTA_EXCEEDED;
  1149. }
  1150. //
  1151. // Put the LogonDomainName into the Credential Buffer.
  1152. //
  1153. Where = (PUCHAR)(Credential + 1);
  1154. NlpPutString( &Credential->LogonDomainName, LogonDomainName, &Where );
  1155. //
  1156. // Put the UserName into the Credential Buffer.
  1157. //
  1158. NlpPutString( &Credential->UserName, UserName, &Where );
  1159. //
  1160. // Put the OWF passwords into the newly allocated credential.
  1161. //
  1162. NlpPutOwfsInPrimaryCredential( CleartextPassword, Credential );
  1163. //
  1164. // Return the credential to the caller.
  1165. //
  1166. *CredentialBuffer = Credential;
  1167. return STATUS_SUCCESS;
  1168. }
  1169. NTSTATUS
  1170. NlpMakePrimaryCredentialFromMsvCredential(
  1171. IN PUNICODE_STRING LogonDomainName,
  1172. IN PUNICODE_STRING UserName,
  1173. IN PMSV1_0_SUPPLEMENTAL_CREDENTIAL MsvCredential,
  1174. OUT PMSV1_0_PRIMARY_CREDENTIAL *CredentialBuffer,
  1175. OUT PULONG CredentialSize
  1176. )
  1177. /*++
  1178. Routine Description:
  1179. This routine makes a primary credential for the given user nam and
  1180. password.
  1181. Arguments:
  1182. LogonDomainName - Is a string representing the domain in which the user's
  1183. account is defined.
  1184. UserName - Is a string representing the user's account name. The
  1185. name may be up to 255 characters long. The name is treated case
  1186. insensitive.
  1187. SupplementalCred - The credentials retrieved from the user's account on
  1188. the domain controller.
  1189. CredentialBuffer - Returns a pointer to the specified credential allocated
  1190. on the LsaHeap. It is the callers responsibility to deallocate
  1191. this credential.
  1192. CredentialSize - the size of the allocated credential buffer (in bytes).
  1193. Return Value:
  1194. STATUS_SUCCESS - Indicates the service completed successfully.
  1195. STATUS_QUOTA_EXCEEDED - This error indicates that the logon
  1196. could not be completed because the client does not have
  1197. sufficient quota to allocate the return buffer.
  1198. --*/
  1199. {
  1200. PMSV1_0_PRIMARY_CREDENTIAL Credential;
  1201. NTSTATUS Status;
  1202. PUCHAR Where;
  1203. ULONG PaddingLength;
  1204. //
  1205. // Build the credential
  1206. //
  1207. *CredentialSize = sizeof(MSV1_0_PRIMARY_CREDENTIAL) +
  1208. LogonDomainName->Length + sizeof(WCHAR) +
  1209. UserName->Length + sizeof(WCHAR);
  1210. //
  1211. // add padding for memory encryption interface.
  1212. //
  1213. PaddingLength = DESX_BLOCKLEN - (*CredentialSize % DESX_BLOCKLEN);
  1214. if( PaddingLength == DESX_BLOCKLEN )
  1215. {
  1216. PaddingLength = 0;
  1217. }
  1218. *CredentialSize += PaddingLength;
  1219. Credential = (*Lsa.AllocateLsaHeap)( *CredentialSize );
  1220. if ( Credential == NULL ) {
  1221. KdPrint(("MSV1_0: NlpMakePrimaryCredential: No memory %ld\n",
  1222. *CredentialSize ));
  1223. return STATUS_QUOTA_EXCEEDED;
  1224. }
  1225. RtlZeroMemory(
  1226. Credential,
  1227. *CredentialSize
  1228. );
  1229. //
  1230. // Put the LogonDomainName into the Credential Buffer.
  1231. //
  1232. Where = (PUCHAR)(Credential + 1);
  1233. NlpPutString( &Credential->LogonDomainName, LogonDomainName, &Where );
  1234. //
  1235. // Put the UserName into the Credential Buffer.
  1236. //
  1237. NlpPutString( &Credential->UserName, UserName, &Where );
  1238. //
  1239. // Save the OWF encrypted versions of the passwords.
  1240. //
  1241. if (MsvCredential->Flags & MSV1_0_CRED_NT_PRESENT) {
  1242. RtlCopyMemory(
  1243. &Credential->NtOwfPassword,
  1244. MsvCredential->NtPassword,
  1245. MSV1_0_OWF_PASSWORD_LENGTH
  1246. );
  1247. Credential->NtPasswordPresent = TRUE;
  1248. } else {
  1249. #if 0
  1250. RtlCopyMemory(
  1251. &Credential->NtOwfPassword,
  1252. &NlpNullNtOwfPassword,
  1253. MSV1_0_OWF_PASSWORD_LENGTH
  1254. );
  1255. Credential->NtPasswordPresent = TRUE;
  1256. #endif
  1257. Credential->NtPasswordPresent = FALSE;
  1258. }
  1259. if (MsvCredential->Flags & MSV1_0_CRED_LM_PRESENT) {
  1260. RtlCopyMemory(
  1261. &Credential->LmOwfPassword,
  1262. MsvCredential->LmPassword,
  1263. MSV1_0_OWF_PASSWORD_LENGTH
  1264. );
  1265. Credential->LmPasswordPresent = TRUE;
  1266. } else {
  1267. #if 0
  1268. RtlCopyMemory(
  1269. &Credential->LmOwfPassword,
  1270. &NlpNullLmOwfPassword,
  1271. MSV1_0_OWF_PASSWORD_LENGTH
  1272. );
  1273. Credential->LmPasswordPresent = TRUE;
  1274. #endif
  1275. Credential->LmPasswordPresent = FALSE;
  1276. }
  1277. //
  1278. // Return the credential to the caller.
  1279. //
  1280. *CredentialBuffer = Credential;
  1281. return STATUS_SUCCESS;
  1282. }
  1283. NTSTATUS
  1284. NlpAddPrimaryCredential(
  1285. IN PLUID LogonId,
  1286. IN PMSV1_0_PRIMARY_CREDENTIAL Credential,
  1287. IN ULONG CredentialSize
  1288. )
  1289. /*++
  1290. Routine Description:
  1291. This routine sets a primary credential for the given LogonId.
  1292. Arguments:
  1293. LogonId - The LogonId of the LogonSession to set the Credentials
  1294. for.
  1295. Credential - Specifies a pointer to the credential.
  1296. Return Value:
  1297. STATUS_SUCCESS - Indicates the service completed successfully.
  1298. STATUS_QUOTA_EXCEEDED - This error indicates that the logon
  1299. could not be completed because the client does not have
  1300. sufficient quota to allocate the return buffer.
  1301. --*/
  1302. {
  1303. NTSTATUS Status;
  1304. STRING CredentialString;
  1305. STRING PrimaryKeyValue;
  1306. //
  1307. // Make all pointers in the credential relative.
  1308. //
  1309. NlpMakeRelativeString( (PUCHAR)Credential, &Credential->UserName );
  1310. NlpMakeRelativeString( (PUCHAR)Credential, &Credential->LogonDomainName );
  1311. //
  1312. // Add the credential to the logon session.
  1313. //
  1314. RtlInitString( &PrimaryKeyValue, MSV1_0_PRIMARY_KEY );
  1315. CredentialString.Buffer = (PCHAR) Credential;
  1316. CredentialString.Length = (USHORT) CredentialSize;
  1317. CredentialString.MaximumLength = CredentialString.Length;
  1318. //
  1319. // encrypt input credential.
  1320. //
  1321. (*Lsa.LsaProtectMemory)( CredentialString.Buffer, (ULONG)CredentialString.Length );
  1322. Status = (*Lsa.AddCredential)(
  1323. LogonId,
  1324. MspAuthenticationPackageId,
  1325. &PrimaryKeyValue,
  1326. &CredentialString );
  1327. if ( !NT_SUCCESS( Status ) ) {
  1328. KdPrint(( "NlpAddPrimaryCredential: error from AddCredential %lX\n",
  1329. Status));
  1330. }
  1331. return Status;
  1332. }
  1333. NTSTATUS
  1334. NlpGetPrimaryCredentialByUserDomain(
  1335. IN PUNICODE_STRING LogonDomainName,
  1336. IN PUNICODE_STRING UserName,
  1337. OUT PMSV1_0_PRIMARY_CREDENTIAL *CredentialBuffer,
  1338. OUT PULONG CredentialSize OPTIONAL
  1339. )
  1340. {
  1341. PACTIVE_LOGON Logon;
  1342. LUID LogonId;
  1343. BOOLEAN Match = FALSE;
  1344. //
  1345. // Loop through the table looking for this particular LogonId.
  1346. //
  1347. NlpLockActiveLogonsRead();
  1348. for( Logon = NlpActiveLogons; Logon != NULL; Logon = Logon->Next ) {
  1349. if(RtlEqualUnicodeString( UserName, &Logon->UserName, (BOOLEAN) TRUE) &&
  1350. RtlEqualDomainName(LogonDomainName,&Logon->LogonDomainName ))
  1351. {
  1352. Match = TRUE;
  1353. CopyMemory( &LogonId, &Logon->LogonId, sizeof(LogonId) );
  1354. break;
  1355. }
  1356. }
  1357. NlpUnlockActiveLogons();
  1358. if( !Match )
  1359. return STATUS_NO_SUCH_LOGON_SESSION;
  1360. return NlpGetPrimaryCredential( &LogonId, CredentialBuffer, CredentialSize );
  1361. }
  1362. NTSTATUS
  1363. NlpGetPrimaryCredential(
  1364. IN PLUID LogonId,
  1365. OUT PMSV1_0_PRIMARY_CREDENTIAL *CredentialBuffer,
  1366. OUT PULONG CredentialSize OPTIONAL
  1367. )
  1368. /*++
  1369. Routine Description:
  1370. This routine gets a primary credential for the given LogonId.
  1371. Arguments:
  1372. LogonId - The LogonId of the LogonSession to retrieve the Credentials
  1373. for.
  1374. CredentialBuffer - Returns a pointer to the specified credential allocated
  1375. on the LsaHeap. It is the callers responsibility to deallocate
  1376. this credential.
  1377. CredentialSize - Optionally returns the size of the credential buffer.
  1378. Return Value:
  1379. STATUS_SUCCESS - Indicates the service completed successfully.
  1380. STATUS_QUOTA_EXCEEDED - This error indicates that the logon
  1381. could not be completed because the client does not have
  1382. sufficient quota to allocate the return buffer.
  1383. --*/
  1384. {
  1385. NTSTATUS Status;
  1386. ULONG QueryContext = 0;
  1387. ULONG PrimaryKeyLength;
  1388. STRING PrimaryKeyValue;
  1389. STRING CredentialString;
  1390. PMSV1_0_PRIMARY_CREDENTIAL Credential = NULL;
  1391. RtlInitString( &PrimaryKeyValue, MSV1_0_PRIMARY_KEY );
  1392. Status = (*Lsa.GetCredentials)( LogonId,
  1393. MspAuthenticationPackageId,
  1394. &QueryContext,
  1395. (BOOLEAN) FALSE, // Just retrieve primary
  1396. &PrimaryKeyValue,
  1397. &PrimaryKeyLength,
  1398. &CredentialString );
  1399. if ( !NT_SUCCESS( Status ) ) {
  1400. return Status;
  1401. }
  1402. //
  1403. // Make all pointers in the credential absolute.
  1404. //
  1405. Credential = (PMSV1_0_PRIMARY_CREDENTIAL) CredentialString.Buffer;
  1406. //
  1407. // decrypt credential.
  1408. //
  1409. (*Lsa.LsaUnprotectMemory)( CredentialString.Buffer, (ULONG)CredentialString.Length );
  1410. NlpRelativeToAbsolute( Credential,
  1411. (PULONG_PTR)&Credential->UserName.Buffer );
  1412. NlpRelativeToAbsolute( Credential,
  1413. (PULONG_PTR)&Credential->LogonDomainName.Buffer );
  1414. *CredentialBuffer = Credential;
  1415. if ( CredentialSize != NULL ) {
  1416. *CredentialSize = CredentialString.Length;
  1417. }
  1418. return STATUS_SUCCESS;
  1419. }
  1420. NTSTATUS
  1421. NlpDeletePrimaryCredential(
  1422. IN PLUID LogonId
  1423. )
  1424. /*++
  1425. Routine Description:
  1426. This routine deletes the credential for the given LogonId.
  1427. Arguments:
  1428. LogonId - The LogonId of the LogonSession to delete the Credentials for.
  1429. Return Value:
  1430. STATUS_SUCCESS - Indicates the service completed successfully.
  1431. STATUS_QUOTA_EXCEEDED - This error indicates that the logon
  1432. could not be completed because the client does not have
  1433. sufficient quota to allocate the return buffer.
  1434. --*/
  1435. {
  1436. NTSTATUS Status;
  1437. STRING PrimaryKeyValue;
  1438. RtlInitString( &PrimaryKeyValue, MSV1_0_PRIMARY_KEY );
  1439. Status = (*Lsa.DeleteCredential)( LogonId,
  1440. MspAuthenticationPackageId,
  1441. &PrimaryKeyValue );
  1442. return Status;
  1443. }
  1444. NTSTATUS
  1445. NlpChangePassword(
  1446. IN PUNICODE_STRING DomainName,
  1447. IN PUNICODE_STRING UserName,
  1448. IN PUNICODE_STRING Password
  1449. )
  1450. /*++
  1451. Routine Description:
  1452. Change the password for the specified user in all currently stored
  1453. credentials.
  1454. Arguments:
  1455. DomainName - The Netbios name of the domain in which the account exists.
  1456. UserName - The name of the account whose password is to be changed.
  1457. Password - The new password.
  1458. Return Value:
  1459. STATUS_SUCCESS - If the operation was successful.
  1460. --*/
  1461. {
  1462. NTSTATUS Status = STATUS_NOT_FOUND;
  1463. PACTIVE_LOGON Logon;
  1464. MSV1_0_PRIMARY_CREDENTIAL TempCredential;
  1465. LUID FastLogonIds[ 32 ];
  1466. PLUID SlowLogonIds = NULL;
  1467. ULONG AllocatedLogonIds;
  1468. PLUID LogonIds;
  1469. ULONG cLogonIds;
  1470. UNICODE_STRING NetBiosLogonDomainName = {0};
  1471. UNICODE_STRING DnsDomainName = {0};
  1472. UNICODE_STRING* pNetBiosLogonDomainName = NULL;
  1473. cLogonIds = 0;
  1474. LogonIds = FastLogonIds;
  1475. AllocatedLogonIds = sizeof(FastLogonIds) / sizeof(LUID);
  1476. //
  1477. // Compute the OWFs of the password.
  1478. //
  1479. NlpPutOwfsInPrimaryCredential( Password, &TempCredential );
  1480. Status = LsaIGetNbAndDnsDomainNames(DomainName, &DnsDomainName, &NetBiosLogonDomainName);
  1481. if (NT_SUCCESS(Status) && NetBiosLogonDomainName.Length != 0)
  1482. {
  1483. pNetBiosLogonDomainName = &NetBiosLogonDomainName;
  1484. }
  1485. else
  1486. {
  1487. pNetBiosLogonDomainName = DomainName;
  1488. }
  1489. //
  1490. // Loop through the table looking for this particular UserName/DomainName.
  1491. //
  1492. NlpLockActiveLogonsRead();
  1493. for (Logon = NlpActiveLogons; Logon != NULL; Logon = Logon->Next ) {
  1494. if (!RtlEqualUnicodeString( UserName, &Logon->UserName, (BOOLEAN) TRUE ))
  1495. {
  1496. continue;
  1497. }
  1498. if (!RtlEqualDomainName( pNetBiosLogonDomainName, &Logon->LogonDomainName ))
  1499. {
  1500. continue;
  1501. }
  1502. SspPrint((SSP_UPDATES, "NlpChangePassword matched LogonId=%lx.%lx\n",
  1503. Logon->LogonId.LowPart, Logon->LogonId.HighPart ));
  1504. //
  1505. // if we don't have space to store the new entry, allocate a new
  1506. // buffer, copy the existing buffer, and keep going.
  1507. //
  1508. if( AllocatedLogonIds < (cLogonIds+1))
  1509. {
  1510. PLUID OldLogonIds = SlowLogonIds;
  1511. AllocatedLogonIds *= 2;
  1512. SlowLogonIds = I_NtLmAllocate( AllocatedLogonIds * sizeof(LUID) );
  1513. if( SlowLogonIds == NULL )
  1514. {
  1515. break;
  1516. }
  1517. CopyMemory( SlowLogonIds, LogonIds, cLogonIds*sizeof(LUID) );
  1518. LogonIds = SlowLogonIds;
  1519. if( OldLogonIds != NULL )
  1520. {
  1521. I_NtLmFree( OldLogonIds );
  1522. }
  1523. }
  1524. LogonIds[ cLogonIds ] = Logon->LogonId;
  1525. cLogonIds++;
  1526. }
  1527. NlpUnlockActiveLogons();
  1528. //
  1529. // Pass the change back to the LSA. Note - this only changes it for the
  1530. // last element in the list.
  1531. //
  1532. if (cLogonIds != 0)
  1533. {
  1534. SECPKG_PRIMARY_CRED PrimaryCredentials;
  1535. ULONG Index;
  1536. RtlZeroMemory(
  1537. &PrimaryCredentials,
  1538. sizeof(SECPKG_PRIMARY_CRED)
  1539. );
  1540. PrimaryCredentials.Password = *Password;
  1541. PrimaryCredentials.Flags = PRIMARY_CRED_UPDATE | PRIMARY_CRED_CLEAR_PASSWORD;
  1542. //
  1543. // update each instance of the credential that matches.
  1544. // Multiple logon session can legally reference the same creds,
  1545. // eg: Terminal Services, RunAs, etc.
  1546. //
  1547. for ( Index = 0 ; Index < cLogonIds ; Index++ )
  1548. {
  1549. PrimaryCredentials.LogonId = LogonIds[ Index ];
  1550. (VOID) LsaFunctions->UpdateCredentials(
  1551. &PrimaryCredentials,
  1552. NULL // no supplemental credentials
  1553. );
  1554. }
  1555. Status = STATUS_SUCCESS;
  1556. }
  1557. else
  1558. {
  1559. Status = STATUS_NOT_FOUND;
  1560. }
  1561. //
  1562. // Pass the new password on to the logon cache
  1563. //
  1564. NlpChangeCachePassword(
  1565. DomainName,
  1566. UserName,
  1567. &TempCredential.LmOwfPassword,
  1568. &TempCredential.NtOwfPassword
  1569. );
  1570. ZeroMemory( &TempCredential, sizeof(TempCredential) );
  1571. if ( SlowLogonIds )
  1572. {
  1573. I_NtLmFree( SlowLogonIds );
  1574. }
  1575. if (NetBiosLogonDomainName.MaximumLength && NetBiosLogonDomainName.Buffer)
  1576. {
  1577. LsaIFreeHeap(NetBiosLogonDomainName.Buffer);
  1578. }
  1579. if (DnsDomainName.MaximumLength && DnsDomainName.Buffer)
  1580. {
  1581. LsaIFreeHeap(DnsDomainName.Buffer);
  1582. }
  1583. return Status;
  1584. }
  1585. NTSTATUS
  1586. NlpChangePasswordByLogonId(
  1587. IN PLUID LogonId,
  1588. IN PUNICODE_STRING Password
  1589. )
  1590. /*++
  1591. Routine Description:
  1592. Change the password for the specified user in all currently stored
  1593. credentials.
  1594. Arguments:
  1595. LogonId - Logon ID of user whose password changed.
  1596. Password - New password.
  1597. Return Value:
  1598. STATUS_SUCCESS - If the operation was successful.
  1599. --*/
  1600. {
  1601. NTSTATUS Status = STATUS_SUCCESS;
  1602. PACTIVE_LOGON Logon;
  1603. ULONG LogonCount = 0;
  1604. PMSV1_0_PRIMARY_CREDENTIAL Credential = NULL;
  1605. ULONG CredentialSize;
  1606. MSV1_0_PRIMARY_CREDENTIAL TempCredential;
  1607. //
  1608. // Compute the OWFs of the password.
  1609. //
  1610. NlpPutOwfsInPrimaryCredential( Password, &TempCredential );
  1611. //
  1612. // Loop through the table looking for this particular UserName/DomainName.
  1613. //
  1614. // conservative: take the full write lock up front.
  1615. NlpLockActiveLogonsWrite();
  1616. for( Logon = NlpActiveLogons; Logon != NULL; Logon = Logon->Next )
  1617. {
  1618. if(!RtlEqualLuid( LogonId, &Logon->LogonId) )
  1619. {
  1620. continue;
  1621. }
  1622. SspPrint((SSP_UPDATES, "NlpChangePasswordByLogonId LogonId=%lx.%lx\n",
  1623. LogonId->LowPart, LogonId->HighPart ));
  1624. //
  1625. // Get the current credential for this logonid.
  1626. //
  1627. Status = NlpGetPrimaryCredential( &Logon->LogonId,
  1628. &Credential,
  1629. &CredentialSize );
  1630. if ( !NT_SUCCESS(Status) ) {
  1631. break;
  1632. }
  1633. //
  1634. // Delete it from the LSA.
  1635. //
  1636. Status = NlpDeletePrimaryCredential( &Logon->LogonId );
  1637. if ( !NT_SUCCESS(Status) ) {
  1638. (*Lsa.FreeLsaHeap)( Credential );
  1639. break;
  1640. }
  1641. //
  1642. // Change the passwords in it
  1643. //
  1644. Credential->LmOwfPassword = TempCredential.LmOwfPassword;
  1645. Credential->NtOwfPassword = TempCredential.NtOwfPassword;
  1646. Credential->ShaOwfPassword = TempCredential.ShaOwfPassword;
  1647. Credential->LmPasswordPresent = TempCredential.LmPasswordPresent;
  1648. Credential->NtPasswordPresent = TempCredential.NtPasswordPresent;
  1649. Credential->ShaPasswordPresent = TempCredential.ShaPasswordPresent;
  1650. //
  1651. // Add it back to the LSA.
  1652. //
  1653. Status = NlpAddPrimaryCredential( &Logon->LogonId,
  1654. Credential,
  1655. CredentialSize );
  1656. (*Lsa.FreeLsaHeap)( Credential );
  1657. if ( !NT_SUCCESS(Status) ) {
  1658. break;
  1659. }
  1660. //
  1661. // Pass the new password on to the logon cache
  1662. //
  1663. NlpChangeCachePassword(
  1664. &Logon->LogonDomainName,
  1665. &Logon->UserName,
  1666. &TempCredential.LmOwfPassword,
  1667. &TempCredential.NtOwfPassword );
  1668. break;
  1669. }
  1670. NlpUnlockActiveLogons();
  1671. ZeroMemory( &TempCredential, sizeof(TempCredential) );
  1672. return Status;
  1673. }
  1674. VOID
  1675. NlpGetAccountNames(
  1676. IN PNETLOGON_LOGON_IDENTITY_INFO LogonInfo,
  1677. IN PNETLOGON_VALIDATION_SAM_INFO4 NlpUser,
  1678. OUT PUNICODE_STRING SamAccountName,
  1679. OUT PUNICODE_STRING NetbiosDomainName,
  1680. OUT PUNICODE_STRING DnsDomainName,
  1681. OUT PUNICODE_STRING Upn
  1682. )
  1683. /*++
  1684. Routine Description:
  1685. Get the sundry account names from the LogonInfo and NlpUser
  1686. Arguments:
  1687. LogonInfo - pointer to NETLOGON_INTERACTIVE_INFO structure which contains
  1688. the domain name, user name and password for this user. These
  1689. are what the user typed to WinLogon
  1690. NlpUser - pointer to NETLOGON_VALIDATION_SAM_INFO4 structure which
  1691. contains this user's specific interactive logon information
  1692. SamAccountName - Returns the SamAccountName of the logged on user.
  1693. The returned buffer is within the LogonInfo or NlpUser.
  1694. NetbiosDomainName - Returns the NetbiosDomainName of the logged on user.
  1695. The returned buffer is within the LogonInfo or NlpUser.
  1696. DnsDomainName - Returns the DnsDomainName of the logged on user.
  1697. The returned buffer is within the LogonInfo or NlpUser.
  1698. The returned length will be zero if DnsDomainName is not known.
  1699. UPN - Returns the UPN of the logged on user.
  1700. The returned buffer is within the LogonInfo or NlpUser.
  1701. The returned length will be zero if UPN is not known.
  1702. Return Value:
  1703. None.
  1704. --*/
  1705. {
  1706. //
  1707. // Return the SamAccountName and Netbios Domain Name
  1708. //
  1709. *SamAccountName = NlpUser->EffectiveName;
  1710. *NetbiosDomainName = NlpUser->LogonDomainName;
  1711. //
  1712. // Return the DNS domain name.
  1713. //
  1714. *DnsDomainName = NlpUser->DnsLogonDomainName;
  1715. //
  1716. // Determine the UPN of the account
  1717. //
  1718. // If the UPN was returned from the DC,
  1719. // use it.
  1720. // else
  1721. // use the UPN the caller passed in
  1722. //
  1723. // The caller passed in a UPN if all of the following are true:
  1724. // There is no domain name.
  1725. // The passed in user name isn't the one returned from the DC.
  1726. // The passed in user name has an @ in it.
  1727. //
  1728. //
  1729. *Upn = NlpUser->Upn;
  1730. if ( Upn->Length == 0 ) {
  1731. if ( LogonInfo->LogonDomainName.Length == 0 &&
  1732. !RtlEqualUnicodeString( &LogonInfo->UserName, &NlpUser->EffectiveName, (BOOLEAN) TRUE ) ) {
  1733. ULONG i;
  1734. for ( i=0; i<LogonInfo->UserName.Length/sizeof(WCHAR); i++) {
  1735. if ( LogonInfo->UserName.Buffer[i] == L'@') {
  1736. *Upn = LogonInfo->UserName;
  1737. break;
  1738. }
  1739. }
  1740. }
  1741. }
  1742. }
  1743. //+-------------------------------------------------------------------------
  1744. //
  1745. // Function: NlpCopyDomainRelativeSid
  1746. //
  1747. // Synopsis: Given a domain Id and a relative ID create the corresponding
  1748. // SID at the location indicated by TargetSid
  1749. //
  1750. // Effects:
  1751. //
  1752. // Arguments: TargetSid - target memory location
  1753. // DomainId - The template SID to use.
  1754. //
  1755. // RelativeId - The relative Id to append to the DomainId.
  1756. //
  1757. // Requires:
  1758. //
  1759. // Returns: Size - Size of the sid copied
  1760. //
  1761. // Notes:
  1762. //
  1763. //
  1764. //--------------------------------------------------------------------------
  1765. DWORD
  1766. NlpCopyDomainRelativeSid(
  1767. OUT PSID TargetSid,
  1768. IN PSID DomainId,
  1769. IN ULONG RelativeId
  1770. )
  1771. {
  1772. UCHAR DomainIdSubAuthorityCount;
  1773. ULONG Size;
  1774. //
  1775. // Allocate a Sid which has one more sub-authority than the domain ID.
  1776. //
  1777. DomainIdSubAuthorityCount = *(RtlSubAuthorityCountSid( DomainId ));
  1778. Size = RtlLengthRequiredSid(DomainIdSubAuthorityCount+1);
  1779. //
  1780. // Initialize the new SID to have the same inital value as the
  1781. // domain ID.
  1782. //
  1783. if ( !NT_SUCCESS( RtlCopySid( Size, TargetSid, DomainId ) ) ) {
  1784. return 0;
  1785. }
  1786. //
  1787. // Adjust the sub-authority count and
  1788. // add the relative Id unique to the newly allocated SID
  1789. //
  1790. (*(RtlSubAuthorityCountSid( TargetSid ))) ++;
  1791. *RtlSubAuthoritySid( TargetSid, DomainIdSubAuthorityCount ) = RelativeId;
  1792. return Size;
  1793. }
  1794. //
  1795. // temporary home for this function.
  1796. //
  1797. NTSTATUS
  1798. RtlCalculateShaOwfPassword(
  1799. IN PSHA_PASSWORD ShaPassword,
  1800. OUT PSHA_OWF_PASSWORD ShaOwfPassword
  1801. )
  1802. /*++
  1803. Routine Description:
  1804. Takes the passed ShaPassword and performs a one-way-function on it.
  1805. Uses the FIPS approved SHA-1 function
  1806. Arguments:
  1807. ShaPassword - The password to perform the one-way-function on.
  1808. ShaOwfPassword - The hashed password is returned here
  1809. Return Values:
  1810. STATUS_SUCCESS - The function was completed successfully. The hashed
  1811. password is in ShaOwfPassword.
  1812. --*/
  1813. {
  1814. A_SHA_CTX SHA_Context;
  1815. A_SHAInit(&SHA_Context);
  1816. A_SHAUpdate(&SHA_Context, (PCHAR)ShaPassword->Buffer, ShaPassword->Length);
  1817. A_SHAFinal(&SHA_Context, (PCHAR)ShaOwfPassword);
  1818. return(STATUS_SUCCESS);
  1819. }