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.

487 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: mapsam.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 10-17-96 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. extern "C" {
  18. #include "sslp.h"
  19. #include <crypt.h>
  20. #include <lmcons.h>
  21. #include <ntsam.h>
  22. #include <samrpc.h>
  23. #include <samisrv.h>
  24. #include <lsarpc.h>
  25. #include <lsaisrv.h>
  26. #include <ntmsv1_0.h>
  27. #include <certmap.h>
  28. #include "mapsam.h"
  29. }
  30. #include <pac.hxx>
  31. //+---------------------------------------------------------------------------
  32. //
  33. // Function: SslDuplicateString
  34. //
  35. // Synopsis: Duplicate a unicode string
  36. //
  37. // Arguments: [Dest] --
  38. // [Source] --
  39. //
  40. // History: 10-18-96 RichardW Created
  41. //
  42. // Notes:
  43. //
  44. //----------------------------------------------------------------------------
  45. NTSTATUS
  46. SslDuplicateString(
  47. PUNICODE_STRING Dest,
  48. PUNICODE_STRING Source
  49. )
  50. {
  51. Dest->Buffer = (PWSTR) LocalAlloc( LMEM_FIXED, Source->Length + sizeof(WCHAR) );
  52. if ( Dest->Buffer )
  53. {
  54. Dest->Length = Source->Length ;
  55. Dest->MaximumLength = Source->Length + sizeof(WCHAR) ;
  56. CopyMemory( Dest->Buffer, Source->Buffer, Source->Length );
  57. Dest->Buffer[ Dest->Length / 2 ] = L'\0';
  58. return( STATUS_SUCCESS );
  59. }
  60. return( STATUS_NO_MEMORY );
  61. }
  62. //+-------------------------------------------------------------------------
  63. //
  64. // Function: SslMakeDomainRelativeSid
  65. //
  66. // Synopsis: Given a domain Id and a relative ID create the corresponding
  67. // SID allocated from the LSA heap.
  68. //
  69. // Effects:
  70. //
  71. // Arguments:
  72. //
  73. // DomainId - The template SID to use.
  74. //
  75. // RelativeId - The relative Id to append to the DomainId.
  76. //
  77. // Requires:
  78. //
  79. // Returns: Sid - Returns a pointer to a buffer allocated from the LsaHeap
  80. // containing the resultant Sid.
  81. //
  82. // Notes:
  83. //
  84. //
  85. //--------------------------------------------------------------------------
  86. PSID
  87. SslMakeDomainRelativeSid(
  88. IN PSID DomainId,
  89. IN ULONG RelativeId
  90. )
  91. {
  92. UCHAR DomainIdSubAuthorityCount;
  93. ULONG Size;
  94. PSID Sid;
  95. //
  96. // Allocate a Sid which has one more sub-authority than the domain ID.
  97. //
  98. DomainIdSubAuthorityCount = *(RtlSubAuthorityCountSid( DomainId ));
  99. Size = RtlLengthRequiredSid(DomainIdSubAuthorityCount+1);
  100. if ((Sid = LocalAlloc( LMEM_FIXED, Size )) == NULL ) {
  101. return NULL;
  102. }
  103. //
  104. // Initialize the new SID to have the same inital value as the
  105. // domain ID.
  106. //
  107. if ( !NT_SUCCESS( RtlCopySid( Size, Sid, DomainId ) ) ) {
  108. LocalFree( Sid );
  109. return NULL;
  110. }
  111. //
  112. // Adjust the sub-authority count and
  113. // add the relative Id unique to the newly allocated SID
  114. //
  115. (*(RtlSubAuthorityCountSid( Sid ))) ++;
  116. *RtlSubAuthoritySid( Sid, DomainIdSubAuthorityCount ) = RelativeId;
  117. return Sid;
  118. }
  119. //+-------------------------------------------------------------------------
  120. //
  121. // Function: SslDuplicateSid
  122. //
  123. // Synopsis: Duplicates a SID
  124. //
  125. // Effects: allocates memory with LsaFunctions.AllocateLsaHeap
  126. //
  127. // Arguments: DestinationSid - Receives a copy of the SourceSid
  128. // SourceSid - SID to copy
  129. //
  130. // Requires:
  131. //
  132. // Returns: STATUS_SUCCESS - the copy succeeded
  133. // STATUS_INSUFFICIENT_RESOURCES - the call to allocate memory
  134. // failed
  135. //
  136. // Notes:
  137. //
  138. //
  139. //--------------------------------------------------------------------------
  140. NTSTATUS
  141. SslDuplicateSid(
  142. OUT PSID * DestinationSid,
  143. IN PSID SourceSid
  144. )
  145. {
  146. ULONG SidSize;
  147. DsysAssert(RtlValidSid(SourceSid));
  148. SidSize = RtlLengthSid(SourceSid);
  149. *DestinationSid = (PSID) LocalAlloc( LMEM_FIXED, SidSize );
  150. if (*DestinationSid == NULL)
  151. {
  152. return(STATUS_INSUFFICIENT_RESOURCES);
  153. }
  154. RtlCopyMemory(
  155. *DestinationSid,
  156. SourceSid,
  157. SidSize
  158. );
  159. return(STATUS_SUCCESS);
  160. }
  161. NTSTATUS
  162. SslpGetPacForUser(
  163. IN SAMPR_HANDLE UserHandle,
  164. OUT PPACTYPE * ppPac
  165. )
  166. {
  167. PSAMPR_USER_ALL_INFORMATION UserAll = NULL ;
  168. PSAMPR_USER_INFO_BUFFER UserAllInfo = NULL ;
  169. NTSTATUS Status ;
  170. PPACTYPE pNewPac = NULL ;
  171. PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL ;
  172. *ppPac = NULL ;
  173. Status = pSamrQueryInformationUser(
  174. UserHandle,
  175. UserAllInformation,
  176. &UserAllInfo );
  177. if ( !NT_SUCCESS( Status ) )
  178. {
  179. return( Status );
  180. }
  181. UserAll = &UserAllInfo->All ;
  182. if ( UserAll->UserAccountControl & USER_ACCOUNT_DISABLED )
  183. {
  184. Status = STATUS_ACCOUNT_DISABLED ;
  185. goto GetPac_Cleanup;
  186. }
  187. Status = pSamrGetGroupsForUser(
  188. UserHandle,
  189. &GroupsBuffer );
  190. if ( !NT_SUCCESS( Status ) )
  191. {
  192. goto GetPac_Cleanup ;
  193. }
  194. Status = PAC_Init( UserAll,
  195. GroupsBuffer,
  196. GlobalDomainSid,
  197. &GlobalDomainName,
  198. &GlobalMachineName,
  199. NULL,
  200. ppPac );
  201. GetPac_Cleanup:
  202. if ( UserAllInfo )
  203. {
  204. pSamIFree_SAMPR_USER_INFO_BUFFER( UserAllInfo, UserAllInformation );
  205. }
  206. if ( GroupsBuffer )
  207. {
  208. pSamIFree_SAMPR_GET_GROUPS_BUFFER( GroupsBuffer );
  209. }
  210. return( Status );
  211. }
  212. NTSTATUS
  213. SslGetPacForUser(
  214. IN PUNICODE_STRING AlternateName,
  215. IN BOOL AllowGuest,
  216. OUT PUCHAR * pPacData,
  217. OUT PULONG pPacDataSize
  218. )
  219. {
  220. NTSTATUS Status ;
  221. PVOID UserHandle ;
  222. *pPacData = NULL ;
  223. *pPacDataSize = 0 ;
  224. Status = LsaTable->OpenSamUser( AlternateName,
  225. SecNameAlternateId,
  226. &SslNamePrefix,
  227. AllowGuest,
  228. 0,
  229. &UserHandle );
  230. if ( NT_SUCCESS( Status ) )
  231. {
  232. Status = LsaTable->GetUserAuthData( UserHandle,
  233. pPacData,
  234. pPacDataSize );
  235. (VOID) LsaTable->CloseSamUser( UserHandle );
  236. }
  237. return Status ;
  238. }
  239. NTSTATUS
  240. SslCreateTokenFromPac(
  241. IN PUCHAR MarshalledPac,
  242. IN ULONG MarshalledPacSize,
  243. OUT PLUID NewLogonId,
  244. OUT PHANDLE Token
  245. )
  246. {
  247. PLSA_TOKEN_INFORMATION_V1 TokenInformation = NULL ;
  248. PLSA_TOKEN_INFORMATION_NULL TokenNull = NULL ;
  249. PVOID LsaTokenInformation = NULL ;
  250. LUID LogonId ;
  251. UNICODE_STRING UserName ;
  252. UNICODE_STRING DomainName ;
  253. UNICODE_STRING Workstation ;
  254. NTSTATUS Status ;
  255. NTSTATUS SubStatus ;
  256. HANDLE TokenHandle = NULL ;
  257. RtlInitUnicodeString(
  258. &UserName,
  259. L"Certificate User"
  260. );
  261. RtlInitUnicodeString(
  262. &DomainName,
  263. GlobalDomainName.Buffer
  264. );
  265. //
  266. // Now create the token.
  267. //
  268. LsaTokenInformation = TokenInformation;
  269. //
  270. // Create a logon session.
  271. //
  272. NtAllocateLocallyUniqueId(&LogonId);
  273. Status = LsaTable->CreateLogonSession( &LogonId );
  274. if (!NT_SUCCESS(Status))
  275. {
  276. DebugOut((DEB_ERROR,"Failed to create logon session: 0x%x\n",Status));
  277. goto CreateToken_Cleanup;
  278. }
  279. //
  280. // We would normally pass in the client workstation name when creating
  281. // the token, but this information is not available since the client is
  282. // sitting on the other side of an SSL connection.
  283. //
  284. RtlInitUnicodeString(
  285. &Workstation,
  286. NULL
  287. );
  288. Status = LsaTable->CreateToken(
  289. &LogonId,
  290. &SslSource,
  291. Network,
  292. LsaTokenInformationV1,
  293. LsaTokenInformation,
  294. NULL, // no token groups
  295. &UserName,
  296. &DomainName,
  297. &Workstation,
  298. &TokenHandle,
  299. &SubStatus
  300. );
  301. if (!NT_SUCCESS(Status))
  302. {
  303. DebugOut((DEB_ERROR,"Failed to create token: 0x%x\n",Status));
  304. goto CreateToken_Cleanup;
  305. }
  306. TokenInformation = NULL;
  307. TokenNull = NULL;
  308. if (!NT_SUCCESS(SubStatus))
  309. {
  310. DebugOut((DEB_ERROR,"Failed to create token, substatus = 0x%x\n",SubStatus));
  311. Status = SubStatus;
  312. goto CreateToken_Cleanup;
  313. }
  314. //
  315. // If the caller wanted an identify level token, duplicate the token
  316. // now.
  317. //
  318. #if 0
  319. if ((ContextFlags & ISC_RET_IDENTIFY) != 0)
  320. {
  321. if (!DuplicateTokenEx(
  322. TokenHandle,
  323. TOKEN_ALL_ACCESS,
  324. NULL, // no security attributes
  325. SecurityIdentification,
  326. TokenImpersonation,
  327. &TempTokenHandle
  328. ))
  329. {
  330. DebugOut((DEB_ERROR,"Failed to duplicate token\n"));
  331. DsysAssert(GetLastError() == ERROR_NO_SYSTEM_RESOURCES);
  332. Status = STATUS_INSUFFICIENT_RESOURCES;
  333. goto CreateToken_Cleanup;
  334. }
  335. Status = NtClose(TokenHandle);
  336. DsysAssert(NT_SUCCESS(Status));
  337. TokenHandle = TempTokenHandle;
  338. TempTokenHandle = NULL;
  339. }
  340. #endif
  341. //
  342. // Check the delegation information to see if we need to create
  343. // a logon session for this.
  344. //
  345. *NewLogonId = LogonId;
  346. *Token = TokenHandle;
  347. CreateToken_Cleanup:
  348. if (TokenInformation != NULL)
  349. {
  350. if ( TokenInformation->User.User.Sid != NULL ) {
  351. LocalFree( TokenInformation->User.User.Sid );
  352. }
  353. if ( TokenInformation->Groups != NULL ) {
  354. ULONG i;
  355. for ( i=0; i < TokenInformation->Groups->GroupCount; i++ ) {
  356. LocalFree( TokenInformation->Groups->Groups[i].Sid );
  357. }
  358. LocalFree( TokenInformation->Groups );
  359. }
  360. if ( TokenInformation->PrimaryGroup.PrimaryGroup != NULL ) {
  361. LocalFree( TokenInformation->PrimaryGroup.PrimaryGroup );
  362. }
  363. LocalFree( TokenInformation );
  364. }
  365. if (TokenNull != NULL)
  366. {
  367. LocalFree(TokenNull);
  368. }
  369. if (!NT_SUCCESS(Status))
  370. {
  371. //
  372. // Note: if we have created a token, we don't want to delete
  373. // the logon session here because we will end up dereferencing
  374. // the logon session twice.
  375. //
  376. if (TokenHandle != NULL)
  377. {
  378. NtClose(TokenHandle);
  379. }
  380. else if ((LogonId.LowPart != 0) || (LogonId.HighPart != 0))
  381. {
  382. LsaTable->DeleteLogonSession(&LogonId);
  383. }
  384. }
  385. return(Status);
  386. }