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

718 lines
18 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: ctxtapi.c
  7. //
  8. // Contents: LSA Mode Context API
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 2-24-97 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "xtcbpkg.h"
  18. #include "md5.h"
  19. typedef struct _XTCB_ATTR_MAP {
  20. ULONG Request ;
  21. ULONG Return ;
  22. } XTCB_ATTR_MAP ;
  23. XTCB_ATTR_MAP AcceptMap[] = {
  24. { ASC_REQ_DELEGATE, ASC_RET_DELEGATE },
  25. { ASC_REQ_MUTUAL_AUTH, ASC_RET_MUTUAL_AUTH },
  26. { ASC_REQ_REPLAY_DETECT, ASC_RET_REPLAY_DETECT },
  27. { ASC_REQ_SEQUENCE_DETECT, ASC_RET_SEQUENCE_DETECT },
  28. { ASC_REQ_CONFIDENTIALITY, ASC_RET_CONFIDENTIALITY },
  29. { ASC_REQ_ALLOCATE_MEMORY, ASC_RET_ALLOCATED_MEMORY },
  30. { ASC_REQ_CONNECTION, ASC_RET_CONNECTION },
  31. { ASC_REQ_INTEGRITY, ASC_RET_INTEGRITY }
  32. };
  33. XTCB_ATTR_MAP InitMap[] = {
  34. { ISC_REQ_DELEGATE, ISC_RET_DELEGATE },
  35. { ISC_REQ_MUTUAL_AUTH, ISC_RET_MUTUAL_AUTH },
  36. { ISC_REQ_SEQUENCE_DETECT, ISC_RET_MUTUAL_AUTH },
  37. { ISC_REQ_REPLAY_DETECT, ISC_RET_REPLAY_DETECT },
  38. { ISC_REQ_CONFIDENTIALITY, ISC_RET_CONFIDENTIALITY },
  39. { ISC_REQ_ALLOCATE_MEMORY, ISC_RET_ALLOCATED_MEMORY },
  40. { ISC_REQ_INTEGRITY, ISC_RET_INTEGRITY }
  41. };
  42. ULONG
  43. XtcbMapAttributes(
  44. ULONG Input,
  45. BOOL Init
  46. )
  47. {
  48. int i;
  49. ULONG Result = 0 ;
  50. if ( Init )
  51. {
  52. for ( i = 0 ; i < sizeof( InitMap ) / sizeof( XTCB_ATTR_MAP ) ; i++ )
  53. {
  54. if ( InitMap[i].Request & Input )
  55. {
  56. Result |= InitMap[i].Return ;
  57. }
  58. }
  59. }
  60. else
  61. {
  62. for ( i = 0 ; i < sizeof( AcceptMap ) / sizeof( XTCB_ATTR_MAP ) ; i++ )
  63. {
  64. if ( AcceptMap[i].Request & Input )
  65. {
  66. Result |= AcceptMap[i].Return ;
  67. }
  68. }
  69. }
  70. return Result ;
  71. }
  72. //+---------------------------------------------------------------------------
  73. //
  74. // Function: XtcbGetState
  75. //
  76. // Synopsis: Translates handles to their structures, and pulls out the
  77. // interesting bits of the input and output buffers
  78. //
  79. // Arguments: [dwCredHandle] --
  80. // [dwCtxtHandle] --
  81. // [pInput] --
  82. // [pOutput] --
  83. // [Client] --
  84. // [pContext] --
  85. // [pCredHandle] --
  86. // [pInToken] --
  87. // [pOutToken] --
  88. //
  89. // History: 3-05-97 RichardW Created
  90. //
  91. // Notes:
  92. //
  93. //----------------------------------------------------------------------------
  94. SECURITY_STATUS
  95. XtcbGetState(
  96. LSA_SEC_HANDLE dwCredHandle,
  97. LSA_SEC_HANDLE dwCtxtHandle,
  98. PSecBufferDesc pInput,
  99. PSecBufferDesc pOutput,
  100. BOOL Client,
  101. PXTCB_CONTEXT * pContext,
  102. PXTCB_CRED_HANDLE * pCredHandle,
  103. PSecBuffer * pInToken,
  104. PSecBuffer * pOutToken)
  105. {
  106. SECURITY_STATUS scRet;
  107. PXTCB_CONTEXT Context ;
  108. PXTCB_CRED_HANDLE CredHandle ;
  109. PSecBuffer OutToken ;
  110. PSecBuffer InToken ;
  111. ULONG i;
  112. if ( dwCtxtHandle )
  113. {
  114. Context = (PXTCB_CONTEXT) dwCtxtHandle ;
  115. if ( !XtcbRefContextRecord( Context ) )
  116. {
  117. return SEC_E_INVALID_HANDLE ;
  118. }
  119. CredHandle = (PXTCB_CRED_HANDLE) Context->CredHandle ;
  120. }
  121. else
  122. {
  123. CredHandle = (PXTCB_CRED_HANDLE) dwCredHandle ;
  124. if ( !CredHandle )
  125. {
  126. return SEC_E_INVALID_HANDLE ;
  127. }
  128. Context = XtcbCreateContextRecord( (Client ?
  129. XtcbContextClient :
  130. XtcbContextServer),
  131. CredHandle );
  132. if ( !Context )
  133. {
  134. return SEC_E_INSUFFICIENT_MEMORY ;
  135. }
  136. }
  137. //
  138. // Find the output token buffer:
  139. //
  140. OutToken = NULL ;
  141. for ( i = 0 ; i < pOutput->cBuffers ; i++ )
  142. {
  143. if ( (pOutput->pBuffers[i].BufferType & (~SECBUFFER_ATTRMASK)) ==
  144. SECBUFFER_TOKEN )
  145. {
  146. OutToken = &pOutput->pBuffers[i] ;
  147. LsaTable->MapBuffer( OutToken, OutToken );
  148. break;
  149. }
  150. }
  151. //
  152. // Find the input token buffer:
  153. //
  154. InToken = NULL ;
  155. for ( i = 0 ; i < pInput->cBuffers ; i++ )
  156. {
  157. if ( (pInput->pBuffers[i].BufferType & (~SECBUFFER_ATTRMASK)) ==
  158. SECBUFFER_TOKEN )
  159. {
  160. InToken = &pInput->pBuffers[i] ;
  161. LsaTable->MapBuffer( InToken, InToken );
  162. break;
  163. }
  164. }
  165. *pContext = Context ;
  166. *pCredHandle = CredHandle ;
  167. *pInToken = InToken ;
  168. *pOutToken = OutToken ;
  169. return SEC_E_OK ;
  170. }
  171. //+---------------------------------------------------------------------------
  172. //
  173. // Function: XtcbInitLsaModeContext
  174. //
  175. // Synopsis: Creates a client side context and blob
  176. //
  177. // Arguments: [dwCredHandle] --
  178. // [dwCtxtHandle] --
  179. // [pszTargetName] --
  180. // [fContextReq] --
  181. // [TargetDataRep] --
  182. // [pInput] --
  183. // [pdwNewContext] --
  184. // [pOutput] --
  185. // [pfContextAttr] --
  186. // [ptsExpiry] --
  187. // [pfMapContext] --
  188. // [pContextData] --
  189. //
  190. // History: 8-15-98 RichardW Created
  191. //
  192. // Notes:
  193. //
  194. //----------------------------------------------------------------------------
  195. SECURITY_STATUS
  196. SEC_ENTRY
  197. XtcbInitLsaModeContext(
  198. LSA_SEC_HANDLE dwCredHandle,
  199. LSA_SEC_HANDLE dwCtxtHandle,
  200. PSECURITY_STRING TargetName,
  201. ULONG fContextReq,
  202. ULONG TargetDataRep,
  203. PSecBufferDesc pInput,
  204. PLSA_SEC_HANDLE pdwNewContext,
  205. PSecBufferDesc pOutput,
  206. PULONG pfContextAttr,
  207. PTimeStamp ptsExpiry,
  208. PBYTE pfMapContext,
  209. PSecBuffer pContextData)
  210. {
  211. SECURITY_STATUS scRet;
  212. PXTCB_CONTEXT Context ;
  213. PXTCB_CRED_HANDLE CredHandle ;
  214. PSecBuffer OutToken ;
  215. PSecBuffer InToken ;
  216. UCHAR GroupKey[ SEED_KEY_SIZE ];
  217. UCHAR UniqueKey[ SEED_KEY_SIZE ];
  218. UCHAR MyKey[ SEED_KEY_SIZE ];
  219. PWSTR Target ;
  220. BOOL RealTarget = FALSE ;
  221. PUCHAR Buffer;
  222. ULONG BufferLen ;
  223. PUNICODE_STRING Group ;
  224. DebugLog(( DEB_TRACE_CALLS, "InitLsaModeContext( %p, %p, %ws, ... )\n",
  225. dwCredHandle, dwCtxtHandle,
  226. (TargetName->Buffer ? TargetName->Buffer : L"<none>") ));
  227. if ( fContextReq &
  228. ( ISC_REQ_PROMPT_FOR_CREDS |
  229. ISC_REQ_USE_SUPPLIED_CREDS |
  230. ISC_REQ_DATAGRAM |
  231. ISC_REQ_STREAM |
  232. ISC_REQ_NULL_SESSION |
  233. ISC_REQ_MANUAL_CRED_VALIDATION ) )
  234. {
  235. return STATUS_INVALID_PARAMETER ;
  236. }
  237. //
  238. // Determine what kind of call this is (first or second)
  239. //
  240. scRet = XtcbGetState( dwCredHandle,
  241. dwCtxtHandle,
  242. pInput,
  243. pOutput,
  244. TRUE,
  245. &Context,
  246. &CredHandle,
  247. &InToken,
  248. &OutToken );
  249. if ( FAILED( scRet ) )
  250. {
  251. return scRet ;
  252. }
  253. //
  254. // Decide what to do:
  255. //
  256. if ( Context->Core.State == ContextFirstCall )
  257. {
  258. if ( InToken )
  259. {
  260. //
  261. // Something there
  262. //
  263. scRet = SEC_E_INVALID_TOKEN ;
  264. }
  265. else
  266. {
  267. if ( !OutToken )
  268. {
  269. scRet = SEC_E_INVALID_TOKEN ;
  270. }
  271. else
  272. {
  273. //
  274. // Examine the target name. See if we can handle it:
  275. //
  276. if ( MGroupParseTarget( TargetName->Buffer,
  277. &Target ) )
  278. {
  279. //
  280. // See if we have a group with that machine as a member:
  281. //
  282. if ( MGroupLocateKeys( Target,
  283. &Group,
  284. UniqueKey,
  285. GroupKey,
  286. MyKey ) )
  287. {
  288. //
  289. // We do have one! Calooh! Calay!
  290. //
  291. RealTarget = TRUE ;
  292. }
  293. }
  294. if ( !RealTarget )
  295. {
  296. //
  297. // Not one of ours. Delete the context,
  298. // clean up
  299. //
  300. scRet = SEC_E_TARGET_UNKNOWN ;
  301. }
  302. }
  303. if ( RealTarget )
  304. {
  305. //
  306. // We've got a live target. Fill in the context, and construct
  307. // the blob
  308. //
  309. scRet = XtcbBuildInitialToken(
  310. CredHandle->Creds,
  311. Context,
  312. TargetName,
  313. Group,
  314. UniqueKey,
  315. GroupKey,
  316. MyKey,
  317. &Buffer,
  318. &BufferLen );
  319. }
  320. if ( NT_SUCCESS( scRet ) )
  321. {
  322. if ( fContextReq & ISC_REQ_ALLOCATE_MEMORY )
  323. {
  324. OutToken->pvBuffer = Buffer ;
  325. OutToken->cbBuffer = BufferLen ;
  326. }
  327. else
  328. {
  329. if ( BufferLen <= OutToken->cbBuffer )
  330. {
  331. RtlCopyMemory(
  332. OutToken->pvBuffer,
  333. Buffer,
  334. BufferLen );
  335. OutToken->cbBuffer = BufferLen ;
  336. }
  337. else
  338. {
  339. scRet = SEC_E_INSUFFICIENT_MEMORY ;
  340. }
  341. }
  342. }
  343. if ( NT_SUCCESS( scRet ) )
  344. {
  345. Context->Core.State = ContextSecondCall ;
  346. Context->Core.Attributes = fContextReq ;
  347. *pdwNewContext = (LSA_SEC_HANDLE) Context ;
  348. }
  349. else
  350. {
  351. XtcbDerefContextRecord( Context );
  352. }
  353. return scRet ;
  354. }
  355. }
  356. else
  357. {
  358. //
  359. // Second round
  360. //
  361. }
  362. return( scRet );
  363. }
  364. //+---------------------------------------------------------------------------
  365. //
  366. // Function: XtcbDeleteContext
  367. //
  368. // Synopsis: Deletes the LSA side of a context
  369. //
  370. // Arguments: [dwCtxtHandle] --
  371. //
  372. // History: 8-15-98 RichardW Created
  373. //
  374. // Notes:
  375. //
  376. //----------------------------------------------------------------------------
  377. SECURITY_STATUS
  378. SEC_ENTRY
  379. XtcbDeleteContext(
  380. LSA_SEC_HANDLE dwCtxtHandle
  381. )
  382. {
  383. PXTCB_CONTEXT Context ;
  384. DebugLog(( DEB_TRACE_CALLS, "DeleteContext( %x )\n", dwCtxtHandle ));
  385. Context = (PXTCB_CONTEXT) dwCtxtHandle ;
  386. if ( XtcbRefContextRecord( Context ) )
  387. {
  388. XtcbDerefContextRecord( Context );
  389. XtcbDerefContextRecord( Context );
  390. return SEC_E_OK ;
  391. }
  392. return( SEC_E_INVALID_HANDLE );
  393. }
  394. //+---------------------------------------------------------------------------
  395. //
  396. // Function: XtcbApplyControlToken
  397. //
  398. // Synopsis: Apply a control token to a context
  399. //
  400. // Effects: not supported
  401. //
  402. // Arguments: [dwCtxtHandle] --
  403. // [pInput] --
  404. //
  405. // History: 8-15-98 RichardW Created
  406. //
  407. // Notes:
  408. //
  409. //----------------------------------------------------------------------------
  410. SECURITY_STATUS
  411. SEC_ENTRY
  412. XtcbApplyControlToken(
  413. LSA_SEC_HANDLE dwCtxtHandle,
  414. PSecBufferDesc pInput)
  415. {
  416. DebugLog(( DEB_TRACE_CALLS, "ApplyControlToken( %x )\n", dwCtxtHandle ));
  417. return(SEC_E_UNSUPPORTED_FUNCTION);
  418. }
  419. //+---------------------------------------------------------------------------
  420. //
  421. // Function: XtcbAcceptLsaModeContext
  422. //
  423. // Synopsis: Creates a server side context representing the user connecting
  424. //
  425. // Arguments: [dwCredHandle] --
  426. // [dwCtxtHandle] --
  427. // [pInput] --
  428. // [fContextReq] --
  429. // [TargetDataRep] --
  430. // [pdwNewContext] --
  431. // [pOutput] --
  432. // [pfContextAttr] --
  433. // [ptsExpiry] --
  434. // [pfMapContext] --
  435. // [pContextData] --
  436. //
  437. // History: 8-15-98 RichardW Created
  438. //
  439. // Notes:
  440. //
  441. //----------------------------------------------------------------------------
  442. SECURITY_STATUS
  443. SEC_ENTRY
  444. XtcbAcceptLsaModeContext(
  445. LSA_SEC_HANDLE dwCredHandle,
  446. LSA_SEC_HANDLE dwCtxtHandle,
  447. PSecBufferDesc pInput,
  448. ULONG fContextReq,
  449. ULONG TargetDataRep,
  450. PLSA_SEC_HANDLE pdwNewContext,
  451. PSecBufferDesc pOutput,
  452. PULONG pfContextAttr,
  453. PTimeStamp ptsExpiry,
  454. PBYTE pfMapContext,
  455. PSecBuffer pContextData)
  456. {
  457. SECURITY_STATUS scRet;
  458. PXTCB_CONTEXT Context ;
  459. PXTCB_CRED_HANDLE CredHandle ;
  460. PSecBuffer OutToken ;
  461. PSecBuffer InToken ;
  462. HANDLE Token ;
  463. UNICODE_STRING Client;
  464. UNICODE_STRING Group ;
  465. UCHAR GroupKey[ SEED_KEY_SIZE ];
  466. UCHAR UniqueKey[ SEED_KEY_SIZE ];
  467. UCHAR MyKey[ SEED_KEY_SIZE ];
  468. BOOL Success = FALSE ;
  469. DebugLog(( DEB_TRACE_CALLS, "AcceptLsaModeContext( %x, %x, ... )\n",
  470. dwCredHandle, dwCtxtHandle ));
  471. //
  472. // Determine what kind of call this is (first or second)
  473. //
  474. *pfMapContext = FALSE ;
  475. scRet = XtcbGetState( dwCredHandle,
  476. dwCtxtHandle,
  477. pInput,
  478. pOutput,
  479. FALSE,
  480. &Context,
  481. &CredHandle,
  482. &InToken,
  483. &OutToken );
  484. if ( FAILED( scRet ) )
  485. {
  486. return scRet ;
  487. }
  488. //
  489. // Decide what to do:
  490. //
  491. if ( Context->Core.State == ContextFirstCall )
  492. {
  493. if ( !InToken )
  494. {
  495. return SEC_E_INVALID_TOKEN ;
  496. }
  497. if ( !XtcbParseInputToken(
  498. InToken->pvBuffer,
  499. InToken->cbBuffer,
  500. &Client,
  501. &Group ) )
  502. {
  503. DebugLog((DEB_TRACE, "Unable to parse input token\n" ));
  504. return SEC_E_INVALID_TOKEN ;
  505. }
  506. Success = MGroupLocateInboundKey(
  507. &Group,
  508. &Client,
  509. UniqueKey,
  510. GroupKey,
  511. MyKey );
  512. LocalFree( Client.Buffer );
  513. LocalFree( Group.Buffer );
  514. if ( Success )
  515. {
  516. scRet = XtcbAuthenticateClient(
  517. Context,
  518. InToken->pvBuffer,
  519. InToken->cbBuffer,
  520. UniqueKey,
  521. GroupKey,
  522. MyKey
  523. );
  524. }
  525. else
  526. {
  527. DebugLog(( DEB_TRACE, "Unable to find group entry for Group %ws, Client %ws\n",
  528. Group.Buffer, Client.Buffer ));
  529. scRet = SEC_E_INVALID_TOKEN ;
  530. }
  531. if ( NT_SUCCESS( scRet ) )
  532. {
  533. scRet = XtcbBuildReplyToken(
  534. Context,
  535. fContextReq,
  536. OutToken );
  537. }
  538. if ( NT_SUCCESS( scRet ) )
  539. {
  540. Context->Core.State = ContextSecondCall ;
  541. //
  542. // Ok, we've done the authentication. Now, we need to map
  543. // the security context back to the client process
  544. //
  545. scRet = LsaTable->DuplicateHandle(
  546. Context->Token,
  547. &Token );
  548. if ( NT_SUCCESS( scRet ) )
  549. {
  550. Context->Core.CoreTokenHandle = HandleToUlong( Token );
  551. *pfMapContext = TRUE ;
  552. pContextData->BufferType = SECBUFFER_TOKEN ;
  553. pContextData->cbBuffer = sizeof( XTCB_CONTEXT_CORE );
  554. pContextData->pvBuffer = &Context->Core ;
  555. *pfContextAttr = ASC_RET_DELEGATE |
  556. ASC_RET_MUTUAL_AUTH |
  557. ASC_RET_REPLAY_DETECT |
  558. ASC_RET_SEQUENCE_DETECT |
  559. ASC_RET_CONFIDENTIALITY |
  560. ASC_
  561. }
  562. }
  563. }
  564. return( scRet );
  565. }
  566. //+---------------------------------------------------------------------------
  567. //
  568. // Function: XtcbQueryLsaModeContext
  569. //
  570. // Synopsis: Lifespan is thunked to LSA mode for demonstration purposes
  571. //
  572. // Arguments: [ContextHandle] --
  573. // [ContextAttribute] --
  574. // [pBuffer] --
  575. //
  576. // History: 3-30-97 RichardW Created
  577. //
  578. // Notes:
  579. //
  580. //----------------------------------------------------------------------------
  581. NTSTATUS
  582. NTAPI
  583. XtcbQueryLsaModeContext(
  584. IN LSA_SEC_HANDLE ContextHandle,
  585. IN ULONG ContextAttribute,
  586. IN OUT PVOID pBuffer
  587. )
  588. {
  589. PXTCB_CONTEXT Context ;
  590. NTSTATUS Status ;
  591. Context = (PXTCB_CONTEXT) ContextHandle ;
  592. if ( !XtcbRefContextRecord( Context ))
  593. {
  594. return SEC_E_INVALID_HANDLE ;
  595. }
  596. Status = SEC_E_UNSUPPORTED_FUNCTION ;
  597. XtcbDerefContextRecord( Context );
  598. return( Status );
  599. }