Windows NT 4.0 source code leak
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.

1565 lines
35 KiB

4 years ago
  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1992 - 1994
  6. //
  7. // File: stubs.cxx
  8. //
  9. // Contents: user-mode stubs for security API
  10. //
  11. //
  12. // History: 3/5/94 MikeSw Created
  13. //
  14. //------------------------------------------------------------------------
  15. #include <sspdrv.h>
  16. #pragma alloc_text(PAGE, AcquireCredentialsHandleW)
  17. #pragma alloc_text(PAGE, FreeCredentialsHandle)
  18. #pragma alloc_text(PAGE, InitializeSecurityContextW)
  19. #pragma alloc_text(PAGE, AcceptSecurityContext)
  20. #pragma alloc_text(PAGE, DeleteSecurityContext)
  21. #pragma alloc_text(PAGE, ApplyControlToken)
  22. #pragma alloc_text(PAGE, EnumerateSecurityPackagesW)
  23. #pragma alloc_text(PAGE, QuerySecurityPackageInfoW)
  24. #pragma alloc_text(PAGE, FreeContextBuffer)
  25. static CtxtHandle NullContext = {0,0};
  26. static CredHandle NullCredential = {0,0};
  27. static LUID lFake = {0, 0};
  28. static SECURITY_STRING sFake = {0, 0, NULL};
  29. static TOKEN_SOURCE KsecTokenSource = {"KSecDD", {0, 0} };
  30. #define NTLMSSP_REQUIRED_NEGOTIATE_FLAGS ( NTLMSSP_NEGOTIATE_UNICODE | \
  31. NTLMSSP_REQUEST_INIT_RESPONSE )
  32. //+-------------------------------------------------------------------------
  33. //
  34. // Function: AcquireCredentialsHandleW
  35. //
  36. // Synopsis:
  37. //
  38. // Effects:
  39. //
  40. // Arguments:
  41. //
  42. // Requires:
  43. //
  44. // Returns:
  45. //
  46. // Notes:
  47. //
  48. //
  49. //--------------------------------------------------------------------------
  50. SECURITY_STATUS SEC_ENTRY
  51. AcquireCredentialsHandleW(
  52. PSECURITY_STRING pssPrincipal, // Name of principal
  53. PSECURITY_STRING pssPackageName, // Name of package
  54. unsigned long fCredentialUse, // Flags indicating use
  55. void SEC_FAR * pvLogonId, // Pointer to logon ID
  56. void SEC_FAR * pAuthData, // Package specific data
  57. SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func
  58. void SEC_FAR * pvGetKeyArgument, // Value to pass to GetKey()
  59. PCredHandle phCredential, // (out) Cred Handle
  60. PTimeStamp ptsExpiry // (out) Lifetime (optional)
  61. )
  62. {
  63. SECURITY_STATUS scRet;
  64. SECURITY_STRING Principal;
  65. TimeStamp OptionalTimeStamp;
  66. UNICODE_STRING PackageName;
  67. PAGED_CODE();
  68. if (!pssPackageName)
  69. {
  70. return(SEC_E_SECPKG_NOT_FOUND);
  71. }
  72. //
  73. // We don't accept principal names either.
  74. //
  75. if (pssPrincipal)
  76. {
  77. return(SEC_E_UNKNOWN_CREDENTIALS);
  78. }
  79. //
  80. // Make sure they want the NTLM security package
  81. //
  82. RtlInitUnicodeString(
  83. &PackageName,
  84. NTLMSP_NAME
  85. );
  86. if (!RtlEqualUnicodeString(
  87. pssPackageName,
  88. &PackageName,
  89. TRUE))
  90. {
  91. return(SEC_E_SECPKG_NOT_FOUND);
  92. }
  93. //
  94. // The credential handle is the logon id
  95. //
  96. if (fCredentialUse & SECPKG_CRED_OUTBOUND)
  97. {
  98. if (pvLogonId != NULL)
  99. {
  100. *phCredential = *(PCredHandle) pvLogonId;
  101. }
  102. else
  103. {
  104. return(SEC_E_UNKNOWN_CREDENTIALS);
  105. }
  106. }
  107. else if (fCredentialUse & SECPKG_CRED_INBOUND)
  108. {
  109. //
  110. // For inbound credentials, we will accept a logon id but
  111. // we don't require it.
  112. //
  113. if (pvLogonId != NULL)
  114. {
  115. *phCredential = *(PCredHandle) pvLogonId;
  116. }
  117. else
  118. {
  119. *phCredential = NullCredential;
  120. }
  121. }
  122. else
  123. {
  124. return(SEC_E_UNSUPPORTED_FUNCTION);
  125. }
  126. return(SEC_E_OK);
  127. }
  128. //+-------------------------------------------------------------------------
  129. //
  130. // Function: FreeCredentialsHandle
  131. //
  132. // Synopsis:
  133. //
  134. // Effects:
  135. //
  136. // Arguments:
  137. //
  138. // Requires:
  139. //
  140. // Returns:
  141. //
  142. // Notes:
  143. //
  144. //
  145. //--------------------------------------------------------------------------
  146. SECURITY_STATUS SEC_ENTRY
  147. FreeCredentialsHandle(
  148. PCredHandle phCredential // Handle to free
  149. )
  150. {
  151. PAGED_CODE();
  152. //
  153. // Since the credential handle is just the LogonId, do nothing.
  154. //
  155. return(SEC_E_OK);
  156. }
  157. VOID
  158. PutString(
  159. OUT PSTRING Destination,
  160. IN PSTRING Source,
  161. IN PVOID Base,
  162. IN OUT PUCHAR * Where
  163. )
  164. {
  165. Destination->Buffer = (PCHAR) *Where - (ULONG) Base;
  166. Destination->Length =
  167. Source->Length;
  168. Destination->MaximumLength =
  169. Source->Length;
  170. RtlCopyMemory(
  171. *Where,
  172. Source->Buffer,
  173. Source->Length
  174. );
  175. *Where += Source->Length;
  176. }
  177. //+-------------------------------------------------------------------------
  178. //
  179. // Function: InitializeSecurityContextW
  180. //
  181. // Synopsis:
  182. //
  183. // Effects:
  184. //
  185. // Arguments:
  186. //
  187. // Requires:
  188. //
  189. // Returns:
  190. //
  191. // Notes:
  192. //
  193. //
  194. //--------------------------------------------------------------------------
  195. SECURITY_STATUS SEC_ENTRY
  196. InitializeSecurityContextW(
  197. PCredHandle phCredential, // Cred to base context
  198. PCtxtHandle phContext, // Existing context (OPT)
  199. PSECURITY_STRING pssTargetName, // Name of target
  200. unsigned long fContextReq, // Context Requirements
  201. unsigned long Reserved1, // Reserved, MBZ
  202. unsigned long TargetDataRep, // Data rep of target
  203. PSecBufferDesc pInput, // Input Buffers
  204. unsigned long Reserved2, // Reserved, MBZ
  205. PCtxtHandle phNewContext, // (out) New Context handle
  206. PSecBufferDesc pOutput, // (inout) Output Buffers
  207. unsigned long SEC_FAR * pfContextAttr, // (out) Context attrs
  208. PTimeStamp ptsExpiry // (out) Life span (OPT)
  209. )
  210. {
  211. SECURITY_STATUS scRet;
  212. PMSV1_0_GETCHALLENRESP_REQUEST ChallengeRequest = NULL;
  213. ULONG ChallengeRequestSize;
  214. PMSV1_0_GETCHALLENRESP_RESPONSE ChallengeResponse = NULL;
  215. ULONG ChallengeResponseSize;
  216. PCHALLENGE_MESSAGE ChallengeMessage = NULL;
  217. ULONG ChallengeMessageSize;
  218. PNTLM_CHALLENGE_MESSAGE NtlmChallengeMessage = NULL;
  219. ULONG NtlmChallengeMessageSize;
  220. PAUTHENTICATE_MESSAGE AuthenticateMessage = NULL;
  221. ULONG AuthenticateMessageSize;
  222. PNTLM_INITIALIZE_RESPONSE NtlmInitializeResponse = NULL;
  223. PClient Client = NULL;
  224. UNICODE_STRING PasswordToUse;
  225. UNICODE_STRING UserNameToUse;
  226. UNICODE_STRING DomainNameToUse;
  227. ULONG ParameterControl = USE_PRIMARY_PASSWORD |
  228. RETURN_PRIMARY_USERNAME |
  229. RETURN_PRIMARY_LOGON_DOMAINNAME;
  230. NTSTATUS FinalStatus = STATUS_SUCCESS;
  231. PUCHAR Where;
  232. PSecBuffer AuthenticationToken = NULL;
  233. PSecBuffer InitializeResponseToken = NULL;
  234. BOOLEAN UseSuppliedCreds = FALSE;
  235. PAGED_CODE();
  236. RtlInitUnicodeString(
  237. &PasswordToUse,
  238. NULL
  239. );
  240. RtlInitUnicodeString(
  241. &UserNameToUse,
  242. NULL
  243. );
  244. RtlInitUnicodeString(
  245. &DomainNameToUse,
  246. NULL
  247. );
  248. //
  249. // Check for valid sizes, pointers, etc.:
  250. //
  251. if (!phCredential)
  252. {
  253. return(SEC_E_INVALID_HANDLE);
  254. }
  255. //
  256. // Check that we can indeed call the LSA and get the client
  257. // handle to it.
  258. //
  259. scRet = IsOkayToExec(&Client);
  260. if (!NT_SUCCESS(scRet))
  261. {
  262. return(scRet);
  263. }
  264. //
  265. // Locate the buffers with the input data
  266. //
  267. if (!GetTokenBuffer(
  268. pInput,
  269. 0, // get the first security token
  270. (PVOID *) &ChallengeMessage,
  271. &ChallengeMessageSize,
  272. TRUE // may be readonly
  273. ))
  274. {
  275. scRet = SEC_E_INVALID_TOKEN;
  276. goto Cleanup;
  277. }
  278. //
  279. // If we are using supplied creds, get them now too.
  280. //
  281. if (fContextReq & ISC_REQ_USE_SUPPLIED_CREDS)
  282. {
  283. if (!GetTokenBuffer(
  284. pInput,
  285. 1, // get the second security token
  286. (PVOID *) &NtlmChallengeMessage,
  287. &NtlmChallengeMessageSize,
  288. TRUE // may be readonly
  289. ))
  290. {
  291. scRet = SEC_E_INVALID_TOKEN;
  292. goto Cleanup;
  293. }
  294. else
  295. {
  296. UseSuppliedCreds = TRUE;
  297. }
  298. }
  299. //
  300. // Get the output tokens
  301. //
  302. if (!GetSecurityToken(
  303. pOutput,
  304. 0,
  305. &AuthenticationToken) ||
  306. !GetSecurityToken(
  307. pOutput,
  308. 1,
  309. &InitializeResponseToken ) )
  310. {
  311. scRet = SEC_E_INVALID_TOKEN;
  312. goto Cleanup;
  313. }
  314. //
  315. // Make sure the sizes are o.k.
  316. //
  317. if ((ChallengeMessageSize < sizeof(CHALLENGE_MESSAGE)) ||
  318. (UseSuppliedCreds &&
  319. !(NtlmChallengeMessageSize < sizeof(NTLM_CHALLENGE_MESSAGE))))
  320. {
  321. scRet = SEC_E_INVALID_TOKEN;
  322. }
  323. //
  324. // Make sure the caller wants us to allocate memory:
  325. //
  326. if (!(fContextReq & ISC_REQ_ALLOCATE_MEMORY))
  327. {
  328. scRet = SEC_E_UNSUPPORTED_FUNCTION;
  329. goto Cleanup;
  330. }
  331. //
  332. // BUGBUG: allow calls requesting PROMPT_FOR_CREDS to go through.
  333. // We won't prompt, but we will setup a context properly.
  334. //
  335. // if ((fContextReq & ISC_REQ_PROMPT_FOR_CREDS) != 0)
  336. // {
  337. // scRet = SEC_E_UNSUPPORTED_FUNCTION;
  338. // goto Cleanup;
  339. // }
  340. //
  341. // Verify the validity of the challenge message.
  342. //
  343. if (strncmp(
  344. ChallengeMessage->Signature,
  345. NTLMSSP_SIGNATURE,
  346. sizeof(NTLMSSP_SIGNATURE)))
  347. {
  348. scRet = SEC_E_INVALID_TOKEN;
  349. goto Cleanup;
  350. }
  351. if (ChallengeMessage->MessageType != NtLmChallenge)
  352. {
  353. scRet = SEC_E_INVALID_TOKEN;
  354. goto Cleanup;
  355. }
  356. if (ChallengeMessage->NegotiateFlags & NTLMSSP_REQUIRED_NEGOTIATE_FLAGS !=
  357. NTLMSSP_REQUIRED_NEGOTIATE_FLAGS)
  358. {
  359. scRet = SEC_E_UNSUPPORTED_FUNCTION;
  360. goto Cleanup;
  361. }
  362. if ((ChallengeMessage->NegotiateFlags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY) != 0)
  363. {
  364. ParameterControl |= RETURN_NON_NT_USER_SESSION_KEY;
  365. }
  366. if ((fContextReq & ISC_REQ_USE_SUPPLIED_CREDS) != 0)
  367. {
  368. if ( NtlmChallengeMessage->Password.Buffer != NULL)
  369. {
  370. ParameterControl &= ~USE_PRIMARY_PASSWORD;
  371. PasswordToUse = NtlmChallengeMessage->Password;
  372. PasswordToUse.Buffer = (LPWSTR) ((PCHAR) PasswordToUse.Buffer +
  373. (ULONG) NtlmChallengeMessage);
  374. }
  375. if (NtlmChallengeMessage->UserName.Length != 0)
  376. {
  377. UserNameToUse = NtlmChallengeMessage->UserName;
  378. UserNameToUse.Buffer = (LPWSTR) ((PCHAR) UserNameToUse.Buffer +
  379. (ULONG) NtlmChallengeMessage);
  380. ParameterControl &= ~RETURN_PRIMARY_USERNAME;
  381. }
  382. if (NtlmChallengeMessage->DomainName.Length != 0)
  383. {
  384. DomainNameToUse = NtlmChallengeMessage->DomainName;
  385. DomainNameToUse.Buffer = (LPWSTR) ((PCHAR) DomainNameToUse.Buffer +
  386. (ULONG) NtlmChallengeMessage);
  387. ParameterControl &= ~RETURN_PRIMARY_LOGON_DOMAINNAME;
  388. }
  389. }
  390. //
  391. // Package up the parameter for a call to the LSA.
  392. //
  393. ChallengeRequestSize = sizeof(MSV1_0_GETCHALLENRESP_REQUEST) +
  394. PasswordToUse.Length;
  395. scRet = ZwAllocateVirtualMemory(
  396. NtCurrentProcess(),
  397. &ChallengeRequest,
  398. 0L,
  399. &ChallengeRequestSize,
  400. MEM_COMMIT,
  401. PAGE_READWRITE
  402. );
  403. if (!NT_SUCCESS(scRet))
  404. {
  405. goto Cleanup;
  406. }
  407. //
  408. // Build the challenge request message.
  409. //
  410. ChallengeRequest->MessageType = MsV1_0Lm20GetChallengeResponse;
  411. ChallengeRequest->ParameterControl = ParameterControl;
  412. ChallengeRequest->LogonId = * (PLUID) phCredential;
  413. RtlCopyMemory(
  414. ChallengeRequest->ChallengeToClient,
  415. ChallengeMessage->Challenge,
  416. MSV1_0_CHALLENGE_LENGTH
  417. );
  418. if ((ParameterControl & USE_PRIMARY_PASSWORD) == 0)
  419. {
  420. ChallengeRequest->Password.Buffer = (LPWSTR) (ChallengeRequest+1);
  421. RtlCopyMemory(
  422. ChallengeRequest->Password.Buffer,
  423. PasswordToUse.Buffer,
  424. PasswordToUse.Length
  425. );
  426. ChallengeRequest->Password.Length = PasswordToUse.Length;
  427. ChallengeRequest->Password.MaximumLength = PasswordToUse.Length;
  428. }
  429. //
  430. // Call the LSA to get the challenge response.
  431. //
  432. scRet = LsaCallAuthenticationPackage(
  433. Client->hPort,
  434. PackageId,
  435. ChallengeRequest,
  436. ChallengeRequestSize,
  437. &ChallengeResponse,
  438. &ChallengeResponseSize,
  439. &FinalStatus
  440. );
  441. if (!NT_SUCCESS(scRet))
  442. {
  443. goto Cleanup;
  444. }
  445. if (!NT_SUCCESS(FinalStatus))
  446. {
  447. scRet = FinalStatus;
  448. goto Cleanup;
  449. }
  450. ASSERT(ChallengeResponse->MessageType == MsV1_0Lm20GetChallengeResponse);
  451. //
  452. // Now prepare the output message.
  453. //
  454. if (UserNameToUse.Buffer == NULL)
  455. {
  456. UserNameToUse = ChallengeResponse->UserName;
  457. }
  458. if (DomainNameToUse.Buffer == NULL)
  459. {
  460. DomainNameToUse = ChallengeResponse->LogonDomainName;
  461. }
  462. AuthenticateMessageSize = sizeof(AUTHENTICATE_MESSAGE) +
  463. UserNameToUse.Length +
  464. DomainNameToUse.Length +
  465. ChallengeResponse->CaseSensitiveChallengeResponse.Length +
  466. ChallengeResponse->CaseInsensitiveChallengeResponse.Length;
  467. //
  468. // BUGBUG: where do I get the workstation name from?
  469. //
  470. AuthenticateMessage = (PAUTHENTICATE_MESSAGE) SecAllocate(AuthenticateMessageSize);
  471. if (AuthenticateMessage == NULL)
  472. {
  473. scRet = SEC_E_INSUFFICIENT_MEMORY;
  474. goto Cleanup;
  475. }
  476. Where = (PUCHAR) (AuthenticateMessage + 1);
  477. RtlCopyMemory(
  478. AuthenticateMessage->Signature,
  479. NTLMSSP_SIGNATURE,
  480. sizeof(NTLMSSP_SIGNATURE)
  481. );
  482. AuthenticateMessage->MessageType = NtLmAuthenticate;
  483. PutString(
  484. &AuthenticateMessage->LmChallengeResponse,
  485. &ChallengeResponse->CaseInsensitiveChallengeResponse,
  486. AuthenticateMessage,
  487. &Where
  488. );
  489. PutString(
  490. &AuthenticateMessage->NtChallengeResponse,
  491. &ChallengeResponse->CaseSensitiveChallengeResponse,
  492. AuthenticateMessage,
  493. &Where
  494. );
  495. PutString(
  496. &AuthenticateMessage->DomainName,
  497. (PSTRING) &DomainNameToUse,
  498. AuthenticateMessage,
  499. &Where
  500. );
  501. PutString(
  502. &AuthenticateMessage->UserName,
  503. (PSTRING) &UserNameToUse,
  504. AuthenticateMessage,
  505. &Where
  506. );
  507. //
  508. // BUGBUG: no workstation name to fill in.
  509. //
  510. AuthenticateMessage->Workstation.Length = 0;
  511. AuthenticateMessage->Workstation.MaximumLength = 0;
  512. AuthenticateMessage->Workstation.Buffer = NULL;
  513. //
  514. // Build the initialize response.
  515. //
  516. NtlmInitializeResponse = (PNTLM_INITIALIZE_RESPONSE) SecAllocate(sizeof(NTLM_INITIALIZE_RESPONSE));
  517. if (NtlmInitializeResponse == NULL)
  518. {
  519. scRet = SEC_E_INSUFFICIENT_MEMORY;
  520. goto Cleanup;
  521. }
  522. RtlCopyMemory(
  523. NtlmInitializeResponse->UserSessionKey,
  524. ChallengeResponse->UserSessionKey,
  525. MSV1_0_USER_SESSION_KEY_LENGTH
  526. );
  527. RtlCopyMemory(
  528. NtlmInitializeResponse->LanmanSessionKey,
  529. ChallengeResponse->LanmanSessionKey,
  530. MSV1_0_LANMAN_SESSION_KEY_LENGTH
  531. );
  532. //
  533. // Fill in the output buffers now.
  534. //
  535. AuthenticationToken->pvBuffer = AuthenticateMessage;
  536. AuthenticationToken->cbBuffer = AuthenticateMessageSize;
  537. InitializeResponseToken->pvBuffer = NtlmInitializeResponse;
  538. InitializeResponseToken->cbBuffer = sizeof(NTLM_INITIALIZE_RESPONSE);
  539. //
  540. // Make a local context for this
  541. //
  542. scRet = NtlmInitKernelContext(
  543. NtlmInitializeResponse->UserSessionKey,
  544. NtlmInitializeResponse->LanmanSessionKey,
  545. NULL, // no token,
  546. phNewContext
  547. );
  548. if (!NT_SUCCESS(scRet))
  549. {
  550. goto Cleanup;
  551. }
  552. scRet = SEC_E_OK;
  553. Cleanup:
  554. if (ChallengeRequest != NULL)
  555. {
  556. ZwFreeVirtualMemory(
  557. NtCurrentProcess(),
  558. &ChallengeRequest,
  559. &ChallengeRequestSize,
  560. MEM_RELEASE
  561. );
  562. }
  563. if (ChallengeResponse != NULL)
  564. {
  565. LsaFreeReturnBuffer( ChallengeResponse );
  566. }
  567. if (!NT_SUCCESS(scRet))
  568. {
  569. if (AuthenticateMessage != NULL)
  570. {
  571. SecFree(AuthenticateMessage);
  572. }
  573. if (NtlmInitializeResponse != NULL)
  574. {
  575. SecFree(NtlmInitializeResponse);
  576. }
  577. }
  578. return(scRet);
  579. }
  580. //+-------------------------------------------------------------------------
  581. //
  582. // Function: AcceptSecurityContext
  583. //
  584. // Synopsis:
  585. //
  586. // Effects:
  587. //
  588. // Arguments:
  589. //
  590. // Requires:
  591. //
  592. // Returns:
  593. //
  594. // Notes:
  595. //
  596. //
  597. //--------------------------------------------------------------------------
  598. SECURITY_STATUS SEC_ENTRY
  599. AcceptSecurityContext(
  600. PCredHandle phCredential, // Cred to base context
  601. PCtxtHandle phContext, // Existing context (OPT)
  602. PSecBufferDesc pInput, // Input buffer
  603. unsigned long fContextReq, // Context Requirements
  604. unsigned long TargetDataRep, // Target Data Rep
  605. PCtxtHandle phNewContext, // (out) New context handle
  606. PSecBufferDesc pOutput, // (inout) Output buffers
  607. unsigned long SEC_FAR * pfContextAttr, // (out) Context attributes
  608. PTimeStamp ptsExpiry // (out) Life span (OPT)
  609. )
  610. {
  611. SECURITY_STATUS scRet;
  612. NTSTATUS SubStatus;
  613. PAUTHENTICATE_MESSAGE AuthenticateMessage;
  614. ULONG AuthenticateMessageSize;
  615. PNTLM_AUTHENTICATE_MESSAGE NtlmAuthenticateMessage;
  616. ULONG NtlmAuthenticateMessageSize;
  617. PNTLM_ACCEPT_RESPONSE NtlmAcceptResponse = NULL;
  618. PMSV1_0_LM20_LOGON LogonBuffer = NULL;
  619. ULONG LogonBufferSize;
  620. PMSV1_0_LM20_LOGON_PROFILE LogonProfile = NULL;
  621. ULONG LogonProfileSize;
  622. PSecBuffer AcceptResponseToken = NULL;
  623. PClient Client = NULL;
  624. ANSI_STRING SourceName;
  625. LUID LogonId;
  626. LUID UNALIGNED * TempLogonId;
  627. LARGE_INTEGER UNALIGNED * TempKickoffTime;
  628. HANDLE TokenHandle = NULL;
  629. QUOTA_LIMITS Quotas;
  630. PUCHAR Where;
  631. STRING DomainName;
  632. STRING UserName;
  633. STRING Workstation;
  634. STRING NtChallengeResponse;
  635. STRING LmChallengeResponse;
  636. ULONG EffectivePackageId;
  637. RtlInitString(
  638. &SourceName,
  639. NULL
  640. );
  641. PAGED_CODE();
  642. //
  643. // Check for valid sizes, pointers, etc.:
  644. //
  645. if (!phCredential)
  646. {
  647. return(SEC_E_INVALID_HANDLE);
  648. }
  649. //
  650. // Check that we can indeed call the LSA and get the client
  651. // handle to it.
  652. //
  653. scRet = IsOkayToExec(&Client);
  654. if (!NT_SUCCESS(scRet))
  655. {
  656. return(scRet);
  657. }
  658. //
  659. // Locate the buffers with the input data
  660. //
  661. if (!GetTokenBuffer(
  662. pInput,
  663. 0, // get the first security token
  664. (PVOID *) &AuthenticateMessage,
  665. &AuthenticateMessageSize,
  666. TRUE // may be readonly
  667. ) ||
  668. (!GetTokenBuffer(
  669. pInput,
  670. 1, // get the second security token
  671. (PVOID *) &NtlmAuthenticateMessage,
  672. &NtlmAuthenticateMessageSize,
  673. TRUE // may be readonly
  674. )))
  675. {
  676. scRet = SEC_E_INVALID_TOKEN;
  677. goto Cleanup;
  678. }
  679. //
  680. // Get the output tokens
  681. //
  682. if (!GetSecurityToken(
  683. pOutput,
  684. 0,
  685. &AcceptResponseToken ) )
  686. {
  687. scRet = SEC_E_INVALID_TOKEN;
  688. goto Cleanup;
  689. }
  690. //
  691. // Make sure the sizes are o.k.
  692. //
  693. if ((AuthenticateMessageSize < sizeof(AUTHENTICATE_MESSAGE)) ||
  694. (NtlmAuthenticateMessageSize < sizeof(NTLM_AUTHENTICATE_MESSAGE)))
  695. {
  696. scRet = SEC_E_INVALID_TOKEN;
  697. }
  698. //
  699. // Make sure the caller does not want us to allocate memory:
  700. //
  701. if (fContextReq & ISC_REQ_ALLOCATE_MEMORY)
  702. {
  703. scRet = SEC_E_UNSUPPORTED_FUNCTION;
  704. goto Cleanup;
  705. }
  706. if (AcceptResponseToken->cbBuffer < sizeof(NTLM_ACCEPT_RESPONSE))
  707. {
  708. scRet = SEC_E_INVALID_TOKEN;
  709. goto Cleanup;
  710. }
  711. //
  712. // Verify the validity of the Authenticate message.
  713. //
  714. if (strncmp(
  715. AuthenticateMessage->Signature,
  716. NTLMSSP_SIGNATURE,
  717. sizeof(NTLMSSP_SIGNATURE)))
  718. {
  719. scRet = SEC_E_INVALID_TOKEN;
  720. goto Cleanup;
  721. }
  722. if (AuthenticateMessage->MessageType != NtLmAuthenticate)
  723. {
  724. scRet = SEC_E_INVALID_TOKEN;
  725. goto Cleanup;
  726. }
  727. //
  728. // Fixup the buffer pointers
  729. //
  730. UserName = AuthenticateMessage->UserName;
  731. UserName.Buffer = UserName.Buffer + (ULONG) AuthenticateMessage;
  732. DomainName = AuthenticateMessage->DomainName;
  733. DomainName.Buffer = DomainName.Buffer + (ULONG) AuthenticateMessage;
  734. Workstation = AuthenticateMessage->Workstation;
  735. Workstation.Buffer = Workstation.Buffer + (ULONG) AuthenticateMessage;
  736. NtChallengeResponse = AuthenticateMessage->NtChallengeResponse;
  737. NtChallengeResponse.Buffer = NtChallengeResponse.Buffer + (ULONG) AuthenticateMessage;
  738. LmChallengeResponse = AuthenticateMessage->LmChallengeResponse;
  739. LmChallengeResponse.Buffer = LmChallengeResponse.Buffer + (ULONG) AuthenticateMessage;
  740. //
  741. // Allocate a buffer to pass into LsaLogonUser
  742. //
  743. LogonBufferSize = sizeof(MSV1_0_LM20_LOGON) +
  744. UserName.Length +
  745. DomainName.Length +
  746. Workstation.Length +
  747. LmChallengeResponse.Length +
  748. NtChallengeResponse.Length;
  749. scRet = ZwAllocateVirtualMemory(
  750. NtCurrentProcess(),
  751. &LogonBuffer,
  752. 0L,
  753. &LogonBufferSize,
  754. MEM_COMMIT,
  755. PAGE_READWRITE
  756. );
  757. if (!NT_SUCCESS(scRet))
  758. {
  759. goto Cleanup;
  760. }
  761. //
  762. // Fill in the fixed-length portions
  763. //
  764. LogonBuffer->MessageType = MsV1_0NetworkLogon;
  765. RtlCopyMemory(
  766. LogonBuffer->ChallengeToClient,
  767. NtlmAuthenticateMessage->ChallengeToClient,
  768. MSV1_0_CHALLENGE_LENGTH
  769. );
  770. //
  771. // Fill in the variable length pieces
  772. //
  773. Where = (PUCHAR) (LogonBuffer + 1);
  774. PutString(
  775. (PSTRING) &LogonBuffer->LogonDomainName,
  776. &DomainName,
  777. 0,
  778. &Where
  779. );
  780. PutString(
  781. (PSTRING) &LogonBuffer->UserName,
  782. &UserName,
  783. 0,
  784. &Where
  785. );
  786. PutString(
  787. (PSTRING) &LogonBuffer->Workstation,
  788. &Workstation,
  789. 0,
  790. &Where
  791. );
  792. PutString(
  793. (PSTRING) &LogonBuffer->CaseSensitiveChallengeResponse,
  794. &NtChallengeResponse,
  795. 0,
  796. &Where
  797. );
  798. PutString(
  799. (PSTRING) &LogonBuffer->CaseInsensitiveChallengeResponse,
  800. &LmChallengeResponse,
  801. 0,
  802. &Where
  803. );
  804. LogonBuffer->ParameterControl = MSV1_0_CLEARTEXT_PASSWORD_ALLOWED |
  805. NtlmAuthenticateMessage->ParameterControl;
  806. scRet = RtlUnicodeStringToAnsiString(
  807. &SourceName,
  808. (PUNICODE_STRING) &Workstation,
  809. TRUE
  810. );
  811. if (!NT_SUCCESS(scRet))
  812. {
  813. goto Cleanup;
  814. }
  815. if ( fContextReq & ASC_REQ_LICENSING )
  816. {
  817. EffectivePackageId = PackageId | LSA_CALL_LICENSE_SERVER ;
  818. }
  819. else
  820. {
  821. EffectivePackageId = PackageId ;
  822. }
  823. scRet = LsaLogonUser(
  824. Client->hPort,
  825. &SourceName,
  826. Network,
  827. EffectivePackageId,
  828. LogonBuffer,
  829. LogonBufferSize,
  830. NULL, // token groups
  831. &KsecTokenSource,
  832. (PVOID *) &LogonProfile,
  833. &LogonProfileSize,
  834. &LogonId,
  835. &TokenHandle,
  836. &Quotas,
  837. &SubStatus
  838. );
  839. if (scRet == STATUS_ACCOUNT_RESTRICTION)
  840. {
  841. scRet = SubStatus;
  842. }
  843. if (!NT_SUCCESS(scRet))
  844. {
  845. //
  846. // LsaLogonUser returns garbage for the token if it fails,
  847. // so zero it now so we don't try to close it later.
  848. //
  849. TokenHandle = NULL;
  850. goto Cleanup;
  851. }
  852. //
  853. // Create the kernel context
  854. //
  855. scRet = NtlmInitKernelContext(
  856. LogonProfile->UserSessionKey,
  857. LogonProfile->LanmanSessionKey,
  858. TokenHandle,
  859. phNewContext
  860. );
  861. if (!NT_SUCCESS(scRet))
  862. {
  863. goto Cleanup;
  864. }
  865. TokenHandle = NULL;
  866. //
  867. // Allocate the return buffer.
  868. //
  869. NtlmAcceptResponse = (PNTLM_ACCEPT_RESPONSE) AcceptResponseToken->pvBuffer;
  870. if (NtlmAcceptResponse == NULL)
  871. {
  872. scRet = SEC_E_INSUFFICIENT_MEMORY;
  873. goto Cleanup;
  874. }
  875. TempLogonId = (LUID UNALIGNED *) &NtlmAcceptResponse->LogonId;
  876. *TempLogonId = LogonId;
  877. NtlmAcceptResponse->UserFlags = LogonProfile->UserFlags;
  878. RtlCopyMemory(
  879. NtlmAcceptResponse->UserSessionKey,
  880. LogonProfile->UserSessionKey,
  881. MSV1_0_USER_SESSION_KEY_LENGTH
  882. );
  883. RtlCopyMemory(
  884. NtlmAcceptResponse->LanmanSessionKey,
  885. LogonProfile->LanmanSessionKey,
  886. MSV1_0_LANMAN_SESSION_KEY_LENGTH
  887. );
  888. TempKickoffTime = (LARGE_INTEGER UNALIGNED *) &NtlmAcceptResponse->KickoffTime;
  889. *TempKickoffTime = LogonProfile->KickOffTime;
  890. AcceptResponseToken->cbBuffer = sizeof(NTLM_ACCEPT_RESPONSE);
  891. if ( fContextReq & ASC_REQ_LICENSING )
  892. {
  893. *pfContextAttr = ASC_RET_ALLOCATED_MEMORY | ASC_RET_LICENSING ;
  894. }
  895. else
  896. {
  897. *pfContextAttr = ASC_RET_ALLOCATED_MEMORY;
  898. }
  899. *ptsExpiry = LogonProfile->LogoffTime;
  900. scRet = SEC_E_OK;
  901. Cleanup:
  902. if (SourceName.Buffer != NULL)
  903. {
  904. RtlFreeAnsiString(&SourceName);
  905. }
  906. if (LogonBuffer != NULL)
  907. {
  908. ZwFreeVirtualMemory(
  909. NtCurrentProcess(),
  910. &LogonBuffer,
  911. &LogonBufferSize,
  912. MEM_RELEASE
  913. );
  914. }
  915. if (LogonProfile != NULL)
  916. {
  917. LsaFreeReturnBuffer(LogonProfile);
  918. }
  919. if (TokenHandle != NULL)
  920. {
  921. NtClose(TokenHandle);
  922. }
  923. return(scRet);
  924. }
  925. //+-------------------------------------------------------------------------
  926. //
  927. // Function: DeleteSecurityContext
  928. //
  929. // Synopsis:
  930. //
  931. // Effects:
  932. //
  933. // Arguments:
  934. //
  935. // Requires:
  936. //
  937. // Returns:
  938. //
  939. // Notes:
  940. //
  941. //
  942. //--------------------------------------------------------------------------
  943. SECURITY_STATUS SEC_ENTRY
  944. DeleteSecurityContext(
  945. PCtxtHandle phContext // Context to delete
  946. )
  947. {
  948. SECURITY_STATUS scRet;
  949. PAGED_CODE();
  950. // For now, just delete the LSA context:
  951. if (!phContext)
  952. {
  953. return(SEC_E_INVALID_HANDLE);
  954. }
  955. scRet = NtlmDeleteKernelContext(phContext);
  956. return(scRet);
  957. }
  958. //+-------------------------------------------------------------------------
  959. //
  960. // Function: ApplyControlToken
  961. //
  962. // Synopsis:
  963. //
  964. // Effects:
  965. //
  966. // Arguments:
  967. //
  968. // Requires:
  969. //
  970. // Returns:
  971. //
  972. // Notes:
  973. //
  974. //
  975. //--------------------------------------------------------------------------
  976. SECURITY_STATUS SEC_ENTRY
  977. ApplyControlToken(
  978. PCtxtHandle phContext, // Context to modify
  979. PSecBufferDesc pInput // Input token to apply
  980. )
  981. {
  982. PAGED_CODE();
  983. return(SEC_E_UNSUPPORTED_FUNCTION);
  984. }
  985. //+-------------------------------------------------------------------------
  986. //
  987. // Function: EnumerateSecurityPackagesW
  988. //
  989. // Synopsis:
  990. //
  991. // Effects:
  992. //
  993. // Arguments:
  994. //
  995. // Requires:
  996. //
  997. // Returns:
  998. //
  999. // Notes:
  1000. //
  1001. //
  1002. //--------------------------------------------------------------------------
  1003. SECURITY_STATUS SEC_ENTRY
  1004. EnumerateSecurityPackagesW(
  1005. unsigned long SEC_FAR * pcPackages, // Receives num. packages
  1006. PSecPkgInfo SEC_FAR * ppPackageInfo // Receives array of info
  1007. )
  1008. {
  1009. ULONG PackageInfoSize;
  1010. PSecPkgInfoW PackageInfo = NULL;
  1011. PUCHAR Where;
  1012. PAGED_CODE();
  1013. //
  1014. // Figure out the size of the returned data
  1015. //
  1016. PackageInfoSize = sizeof(SecPkgInfoW) +
  1017. sizeof(NTLMSP_NAME) +
  1018. sizeof(NTLMSP_COMMENT);
  1019. PackageInfo = (PSecPkgInfoW) SecAllocate(PackageInfoSize);
  1020. if (PackageInfo == NULL)
  1021. {
  1022. return(SEC_E_INSUFFICIENT_MEMORY);
  1023. }
  1024. //
  1025. // Fill in the fixed length fields
  1026. //
  1027. PackageInfo->fCapabilities = SECPKG_FLAG_CONNECTION |
  1028. SECPKG_FLAG_TOKEN_ONLY;
  1029. PackageInfo->wVersion = NTLMSP_VERSION;
  1030. PackageInfo->wRPCID = NTLMSP_RPCID;
  1031. PackageInfo->cbMaxToken = NTLMSSP_MAX_MESSAGE_SIZE;
  1032. //
  1033. // Fill in the fields
  1034. //
  1035. Where = (PUCHAR) (PackageInfo+1);
  1036. PackageInfo->Name = (LPWSTR) Where;
  1037. RtlCopyMemory(
  1038. PackageInfo->Name,
  1039. NTLMSP_NAME,
  1040. sizeof(NTLMSP_NAME)
  1041. );
  1042. Where += sizeof(NTLMSP_NAME);
  1043. PackageInfo->Comment = (LPWSTR) Where;
  1044. RtlCopyMemory(
  1045. PackageInfo->Comment,
  1046. NTLMSP_COMMENT,
  1047. sizeof(NTLMSP_COMMENT)
  1048. );
  1049. Where += sizeof(NTLMSP_COMMENT);
  1050. *pcPackages = 1;
  1051. *ppPackageInfo = PackageInfo;
  1052. return(SEC_E_OK);
  1053. }
  1054. //+-------------------------------------------------------------------------
  1055. //
  1056. // Function: QuerySecurityPackageInfoW
  1057. //
  1058. // Synopsis:
  1059. //
  1060. // Effects:
  1061. //
  1062. // Arguments:
  1063. //
  1064. // Requires:
  1065. //
  1066. // Returns:
  1067. //
  1068. // Notes:
  1069. //
  1070. //
  1071. //--------------------------------------------------------------------------
  1072. SECURITY_STATUS SEC_ENTRY
  1073. QuerySecurityPackageInfoW(
  1074. PSECURITY_STRING pssPackageName, // Name of package
  1075. PSecPkgInfo * ppPackageInfo // Receives package info
  1076. )
  1077. {
  1078. UNICODE_STRING PackageName;
  1079. ULONG PackageCount;
  1080. PAGED_CODE();
  1081. RtlInitUnicodeString(
  1082. &PackageName,
  1083. NTLMSP_NAME
  1084. );
  1085. if (!RtlEqualUnicodeString(
  1086. pssPackageName,
  1087. &PackageName,
  1088. TRUE // case insensitive
  1089. ))
  1090. {
  1091. return(SEC_E_SECPKG_NOT_FOUND);
  1092. }
  1093. return(EnumerateSecurityPackages(&PackageCount,ppPackageInfo));
  1094. }
  1095. //+-------------------------------------------------------------------------
  1096. //
  1097. // Function: FreeContextBuffer
  1098. //
  1099. // Synopsis:
  1100. //
  1101. // Effects:
  1102. //
  1103. // Arguments:
  1104. //
  1105. // Requires:
  1106. //
  1107. // Returns:
  1108. //
  1109. // Notes:
  1110. //
  1111. //
  1112. //--------------------------------------------------------------------------
  1113. SECURITY_STATUS SEC_ENTRY
  1114. FreeContextBuffer(
  1115. void SEC_FAR * pvContextBuffer
  1116. )
  1117. {
  1118. PAGED_CODE();
  1119. SecFree(pvContextBuffer);
  1120. return(SEC_E_OK);
  1121. }
  1122. //+-------------------------------------------------------------------------
  1123. //
  1124. // Function: GetSecurityUserData
  1125. //
  1126. // Synopsis: retrieves information about a logged on user.
  1127. //
  1128. // Effects: allocates memory to be freed with FreeContextBuffer
  1129. //
  1130. // Arguments: pLogonId - Logon id of the user in question
  1131. // fFlags - Indicates whether the caller want Cairo style names
  1132. // or NT styles names. For NT, this is ignored.
  1133. // ppUserInfo - Recieves information about user
  1134. //
  1135. // Requires:
  1136. //
  1137. // Returns:
  1138. //
  1139. // Notes:
  1140. //
  1141. //
  1142. //--------------------------------------------------------------------------
  1143. SECURITY_STATUS SEC_ENTRY
  1144. GetSecurityUserInfo(
  1145. IN PLUID pLogonId,
  1146. IN ULONG fFlags,
  1147. OUT PSecurityUserData * ppUserInfo)
  1148. {
  1149. NTSTATUS Status, FinalStatus;
  1150. PVOID GetInfoBuffer = NULL;
  1151. PVOID GetInfoResponseBuffer = NULL;
  1152. PMSV1_0_GETUSERINFO_REQUEST GetInfoRequest;
  1153. PMSV1_0_GETUSERINFO_RESPONSE GetInfoResponse;
  1154. ULONG ResponseSize;
  1155. ULONG RegionSize = sizeof(MSV1_0_GETUSERINFO_REQUEST);
  1156. PSecurityUserData UserInfo = NULL;
  1157. ULONG UserInfoSize;
  1158. PUCHAR Where;
  1159. SECURITY_STATUS scRet;
  1160. PClient Client = NULL;
  1161. scRet = IsOkayToExec(&Client);
  1162. if (!NT_SUCCESS(scRet))
  1163. {
  1164. return(scRet);
  1165. }
  1166. //
  1167. // Allocate virtual memory for the response buffer.
  1168. //
  1169. Status = ZwAllocateVirtualMemory(
  1170. NtCurrentProcess(),
  1171. &GetInfoBuffer, 0L,
  1172. &RegionSize,
  1173. MEM_COMMIT,
  1174. PAGE_READWRITE
  1175. );
  1176. GetInfoRequest = GetInfoBuffer;
  1177. if (!NT_SUCCESS(Status)) {
  1178. scRet = Status;
  1179. goto Cleanup;
  1180. }
  1181. GetInfoRequest->MessageType = MsV1_0GetUserInfo;
  1182. RtlCopyLuid(&GetInfoRequest->LogonId, pLogonId);
  1183. Status = LsaCallAuthenticationPackage(
  1184. Client->hPort,
  1185. PackageId,
  1186. GetInfoRequest,
  1187. RegionSize,
  1188. &GetInfoResponseBuffer,
  1189. &ResponseSize,
  1190. &FinalStatus);
  1191. GetInfoResponse = GetInfoResponseBuffer;
  1192. if (!NT_SUCCESS(Status)) {
  1193. GetInfoResponseBuffer = NULL;
  1194. scRet = Status;
  1195. goto Cleanup;
  1196. }
  1197. if (!NT_SUCCESS(FinalStatus)) {
  1198. scRet = FinalStatus;
  1199. goto Cleanup;
  1200. }
  1201. ASSERT(GetInfoResponse->MessageType == MsV1_0GetUserInfo);
  1202. //
  1203. // Build a SecurityUserData
  1204. //
  1205. UserInfoSize = sizeof(SecurityUserData) +
  1206. GetInfoResponse->UserName.MaximumLength +
  1207. GetInfoResponse->LogonDomainName.MaximumLength +
  1208. GetInfoResponse->LogonServer.MaximumLength +
  1209. RtlLengthSid(GetInfoResponse->UserSid);
  1210. scRet = ZwAllocateVirtualMemory(
  1211. NtCurrentProcess(),
  1212. &UserInfo,
  1213. 0L,
  1214. &UserInfoSize,
  1215. MEM_COMMIT,
  1216. PAGE_READWRITE
  1217. );
  1218. if (!NT_SUCCESS(scRet))
  1219. {
  1220. goto Cleanup;
  1221. }
  1222. //
  1223. // Pack in the SID first, to respectalignment boundaries.
  1224. //
  1225. Where = (PUCHAR) (UserInfo + 1);
  1226. UserInfo->pSid = (PSID) (Where);
  1227. RtlCopySid(
  1228. UserInfoSize,
  1229. Where,
  1230. GetInfoResponse->UserSid
  1231. );
  1232. Where += RtlLengthSid(Where);
  1233. //
  1234. // Pack in the strings
  1235. //
  1236. PutString(
  1237. (PSTRING) &UserInfo->UserName,
  1238. (PSTRING) &GetInfoResponse->UserName,
  1239. 0,
  1240. &Where
  1241. );
  1242. PutString(
  1243. (PSTRING) &UserInfo->LogonDomainName,
  1244. (PSTRING) &GetInfoResponse->LogonDomainName,
  1245. 0,
  1246. &Where
  1247. );
  1248. PutString(
  1249. (PSTRING) &UserInfo->LogonServer,
  1250. (PSTRING) &GetInfoResponse->LogonServer,
  1251. 0,
  1252. &Where
  1253. );
  1254. *ppUserInfo = UserInfo;
  1255. UserInfo = NULL;
  1256. scRet = STATUS_SUCCESS;
  1257. Cleanup:
  1258. if (GetInfoRequest != NULL)
  1259. {
  1260. ZwFreeVirtualMemory(
  1261. NtCurrentProcess(),
  1262. &GetInfoRequest,
  1263. &RegionSize,
  1264. MEM_RELEASE
  1265. );
  1266. }
  1267. if (UserInfo != NULL)
  1268. {
  1269. FreeContextBuffer(UserInfo);
  1270. }
  1271. if (GetInfoResponseBuffer != NULL)
  1272. {
  1273. LsaFreeReturnBuffer(GetInfoResponseBuffer);
  1274. }
  1275. return(scRet);
  1276. }