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.

1800 lines
45 KiB

  1. /*++
  2. Copyright (c) 1996, 1997 Microsoft Corporation
  3. Module Name:
  4. crypt32.cpp
  5. Abstract:
  6. This module contains routines associated with server side Crypt32
  7. operations.
  8. Author:
  9. Scott Field (sfield) 14-Aug-97
  10. --*/
  11. #include <pch.cpp>
  12. #pragma hdrstop
  13. #include <msaudite.h>
  14. #define SECURITY_WIN32
  15. #include <security.h>
  16. #define CRYPTPROTECT_SVR_VERSION_1 0x01
  17. DWORD
  18. CPSCreateServerContext(
  19. PCRYPT_SERVER_CONTEXT pServerContext,
  20. handle_t hBinding
  21. );
  22. DWORD
  23. CPSDeleteServerContext(
  24. PCRYPT_SERVER_CONTEXT pServerContext
  25. );
  26. GUID g_guidDefaultProvider = CRYPTPROTECT_DEFAULT_PROVIDER;
  27. //
  28. // routines to initialize and destroy server state associated with
  29. // server callbacks and performance improvements.
  30. //
  31. DWORD
  32. CPSCreateServerContext(
  33. PCRYPT_SERVER_CONTEXT pServerContext,
  34. handle_t hBinding
  35. )
  36. {
  37. DWORD dwLastError = ERROR_SUCCESS;
  38. ZeroMemory( pServerContext, sizeof(CRYPT_SERVER_CONTEXT) );
  39. pServerContext->cbSize = sizeof(CRYPT_SERVER_CONTEXT);
  40. pServerContext->hBinding = hBinding;
  41. pServerContext->fImpersonating = FALSE;
  42. if(NULL != hBinding)
  43. {
  44. dwLastError = RpcImpersonateClient( hBinding );
  45. if(ERROR_SUCCESS != dwLastError)
  46. {
  47. return dwLastError;
  48. }
  49. }
  50. //
  51. // Grab the thread token.
  52. //
  53. if(OpenThreadToken(
  54. GetCurrentThread(),
  55. TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
  56. TRUE,
  57. &pServerContext->hToken
  58. ))
  59. {
  60. pServerContext->fImpersonating = (NULL == hBinding);
  61. }
  62. else
  63. {
  64. HANDLE hProcessToken = NULL;
  65. if(OpenProcessToken(GetCurrentProcess(),
  66. TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
  67. &hProcessToken))
  68. {
  69. if(!DuplicateTokenEx(hProcessToken,
  70. 0,
  71. NULL,
  72. SecurityImpersonation,
  73. TokenImpersonation,
  74. &pServerContext->hToken))
  75. {
  76. dwLastError = GetLastError();
  77. }
  78. CloseHandle(hProcessToken);
  79. }
  80. else
  81. {
  82. dwLastError = GetLastError();
  83. }
  84. }
  85. if(hBinding)
  86. {
  87. DWORD rc;
  88. rc = RpcRevertToSelfEx( hBinding );
  89. if (rc != RPC_S_OK)
  90. {
  91. if (ERROR_SUCCESS == dwLastError)
  92. {
  93. dwLastError = rc;
  94. }
  95. }
  96. }
  97. //
  98. // Is this call from one of the well-known accounts?
  99. //
  100. {
  101. WCHAR szUserName[MAX_PATH + 1];
  102. DWORD cchUserName = MAX_PATH;
  103. if(GetUserTextualSid(
  104. pServerContext->hToken,
  105. szUserName,
  106. &cchUserName))
  107. {
  108. if(lstrcmpW(szUserName, TEXTUAL_SID_LOCAL_SYSTEM) == 0)
  109. {
  110. pServerContext->WellKnownAccount = DP_ACCOUNT_LOCAL_SYSTEM;
  111. }
  112. else if(lstrcmpW(szUserName, TEXTUAL_SID_LOCAL_SERVICE) == 0)
  113. {
  114. pServerContext->WellKnownAccount = DP_ACCOUNT_LOCAL_SERVICE;
  115. }
  116. else if(lstrcmpW(szUserName, TEXTUAL_SID_NETWORK_SERVICE) == 0)
  117. {
  118. pServerContext->WellKnownAccount = DP_ACCOUNT_NETWORK_SERVICE;
  119. }
  120. }
  121. }
  122. return dwLastError;
  123. }
  124. DWORD
  125. CPSDeleteServerContext(
  126. PCRYPT_SERVER_CONTEXT pServerContext
  127. )
  128. {
  129. if(pServerContext->szUserStorageArea)
  130. {
  131. SSFree(pServerContext->szUserStorageArea);
  132. pServerContext->szUserStorageArea = NULL;
  133. }
  134. if(pServerContext->hToken)
  135. {
  136. CloseHandle(pServerContext->hToken);
  137. }
  138. if(pServerContext->cbSize == sizeof(CRYPT_SERVER_CONTEXT))
  139. ZeroMemory( pServerContext, sizeof(CRYPT_SERVER_CONTEXT) );
  140. return ERROR_SUCCESS;
  141. }
  142. DWORD
  143. WINAPI
  144. CPSDuplicateContext(
  145. IN PVOID pvContext,
  146. IN OUT PVOID *ppvDuplicateContext
  147. )
  148. /*++
  149. Duplicate an outstanding server context so that a provider may defer
  150. processing associated with the outstanding context until a later time.
  151. This is used to support asynchronous operations on behalf of the caller
  152. to the Data Protection API.
  153. The caller MUST be impersonating the security context of the client user
  154. prior to making this call.
  155. --*/
  156. {
  157. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvContext;
  158. PCRYPT_SERVER_CONTEXT pNewContext = NULL;
  159. HANDLE hToken = NULL;
  160. HANDLE hDuplicateToken;
  161. BOOL fSuccess = FALSE;
  162. DWORD dwLastError = ERROR_SUCCESS;
  163. if( pServerContext == NULL ||
  164. pServerContext->cbSize != sizeof(CRYPT_SERVER_CONTEXT) ||
  165. ppvDuplicateContext == NULL
  166. ) {
  167. return ERROR_INVALID_PARAMETER;
  168. }
  169. pNewContext = (PCRYPT_SERVER_CONTEXT)SSAlloc( sizeof( CRYPT_SERVER_CONTEXT ) );
  170. if( pNewContext == NULL )
  171. return ERROR_NOT_ENOUGH_SERVER_MEMORY;
  172. CopyMemory( pNewContext, pServerContext, sizeof(CRYPT_SERVER_CONTEXT) );
  173. pNewContext->hBinding = NULL;
  174. if(pServerContext->szUserStorageArea)
  175. {
  176. pNewContext->szUserStorageArea = (LPWSTR)SSAlloc((wcslen(pServerContext->szUserStorageArea)+1)*
  177. sizeof(WCHAR));
  178. if(NULL != pNewContext->szUserStorageArea)
  179. {
  180. wcscpy(pNewContext->szUserStorageArea, pServerContext->szUserStorageArea);
  181. }
  182. }
  183. fSuccess = DuplicateTokenEx(pServerContext->hToken,
  184. 0,
  185. NULL,
  186. SecurityImpersonation,
  187. TokenImpersonation,
  188. &pNewContext->hToken);
  189. if( !fSuccess )
  190. {
  191. dwLastError = GetLastError();
  192. pNewContext->hToken = NULL;
  193. CPSFreeContext( pNewContext );
  194. } else {
  195. *ppvDuplicateContext = pNewContext;
  196. }
  197. return dwLastError;
  198. }
  199. DWORD
  200. WINAPI
  201. CPSFreeContext(
  202. IN PVOID pvDuplicateContext
  203. )
  204. {
  205. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvDuplicateContext;
  206. if( pServerContext == NULL ||
  207. pServerContext->cbSize != sizeof(CRYPT_SERVER_CONTEXT)
  208. ) {
  209. return ERROR_INVALID_PARAMETER;
  210. }
  211. if( pServerContext->hToken )
  212. CloseHandle( pServerContext->hToken );
  213. if(pServerContext->szUserStorageArea)
  214. {
  215. SSFree(pServerContext->szUserStorageArea);
  216. pServerContext->szUserStorageArea = NULL;
  217. }
  218. ZeroMemory( pServerContext, sizeof(CRYPT_SERVER_CONTEXT) );
  219. SSFree( pServerContext );
  220. return ERROR_SUCCESS;
  221. }
  222. DWORD
  223. WINAPI
  224. CPSImpersonateClient(
  225. IN PVOID pvContext
  226. )
  227. {
  228. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvContext;
  229. DWORD dwLastError = ERROR_INVALID_PARAMETER;
  230. if( pvContext == NULL )
  231. return ERROR_SUCCESS;
  232. if( pServerContext->cbSize == sizeof(CRYPT_SERVER_CONTEXT) )
  233. {
  234. if( pServerContext->fOverrideToLocalSystem ||
  235. (pServerContext->WellKnownAccount != 0))
  236. {
  237. if(ImpersonateSelf(SecurityImpersonation))
  238. {
  239. dwLastError = ERROR_SUCCESS;
  240. }
  241. else
  242. {
  243. dwLastError = GetLastError();
  244. D_DebugLog((DEB_WARN, "Failed ImpersonateSelf call: 0x%x\n", dwLastError));
  245. }
  246. }
  247. else
  248. {
  249. //
  250. // duplicated server context has access token included; use it directly
  251. //
  252. if( pServerContext->hToken )
  253. {
  254. if(!SetThreadToken( NULL, pServerContext->hToken ))
  255. {
  256. dwLastError = GetLastError();
  257. D_DebugLog((DEB_WARN, "Failed SetThreadToken call: 0x%x\n", dwLastError));
  258. goto cleanup;
  259. }
  260. dwLastError = ERROR_SUCCESS;
  261. goto cleanup;
  262. }
  263. if(pServerContext->hBinding)
  264. {
  265. dwLastError = RpcImpersonateClient( pServerContext->hBinding );
  266. }
  267. else
  268. {
  269. dwLastError = ERROR_INVALID_PARAMETER;
  270. }
  271. }
  272. }
  273. cleanup:
  274. #if DBG
  275. if(NT_SUCCESS(dwLastError) && (DPAPIInfoLevel & DEB_TRACE))
  276. {
  277. BYTE rgbTemp[256];
  278. PTOKEN_USER pUser = (PTOKEN_USER)rgbTemp;
  279. DWORD cbRetInfo;
  280. UNICODE_STRING ucsSid;
  281. HANDLE hToken;
  282. NTSTATUS Status;
  283. Status = NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, TRUE, &hToken);
  284. if(NT_SUCCESS(Status))
  285. {
  286. Status = NtQueryInformationToken(hToken,
  287. TokenUser,
  288. pUser,
  289. 256,
  290. &cbRetInfo);
  291. if(NT_SUCCESS(Status))
  292. {
  293. if(NT_SUCCESS(RtlConvertSidToUnicodeString(&ucsSid, pUser->User.Sid, TRUE)))
  294. {
  295. D_DebugLog((DEB_TRACE, "Impersonating user:%ls\n", ucsSid.Buffer));
  296. RtlFreeUnicodeString(&ucsSid);
  297. }
  298. }
  299. else
  300. {
  301. D_DebugLog((DEB_ERROR, "Unable read user info: 0x%x\n", Status));
  302. }
  303. CloseHandle(hToken);
  304. }
  305. else
  306. {
  307. D_DebugLog((DEB_ERROR, "Unable to open thread token: 0x%x\n", Status));
  308. }
  309. }
  310. #endif
  311. if(!NT_SUCCESS(dwLastError))
  312. {
  313. D_DebugLog((DEB_WARN, "CPSImpersonateClient returned 0x%x\n", dwLastError));
  314. }
  315. return dwLastError;
  316. }
  317. DWORD
  318. WINAPI
  319. CPSRevertToSelf(
  320. IN PVOID pvContext
  321. )
  322. {
  323. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvContext;
  324. DWORD dwLastError = ERROR_INVALID_PARAMETER;
  325. if( pvContext == NULL )
  326. return ERROR_SUCCESS;
  327. if( pServerContext->cbSize == sizeof(CRYPT_SERVER_CONTEXT) ) {
  328. if( pServerContext->fOverrideToLocalSystem || pServerContext->hToken ) {
  329. if(RevertToSelf()) {
  330. dwLastError = ERROR_SUCCESS;
  331. } else {
  332. dwLastError = GetLastError();
  333. }
  334. } else {
  335. if(pServerContext->hBinding)
  336. {
  337. dwLastError = RpcRevertToSelfEx( pServerContext->hBinding );
  338. }
  339. else
  340. {
  341. dwLastError = ERROR_INVALID_PARAMETER;
  342. }
  343. }
  344. }
  345. return dwLastError;
  346. }
  347. DWORD
  348. WINAPI
  349. CPSOverrideToLocalSystem(
  350. IN PVOID pvContext,
  351. IN BOOL *pfLocalSystem, // if non-null, new over ride BOOL
  352. IN OUT BOOL *pfCurrentlyLocalSystem // if non-null, prior over ride BOOL
  353. )
  354. {
  355. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvContext;
  356. if( pServerContext == NULL ||
  357. pServerContext->cbSize != sizeof(CRYPT_SERVER_CONTEXT)
  358. ) {
  359. return ERROR_INVALID_PARAMETER;
  360. }
  361. if( pfCurrentlyLocalSystem )
  362. *pfCurrentlyLocalSystem = pServerContext->fOverrideToLocalSystem;
  363. if( pfLocalSystem )
  364. pServerContext->fOverrideToLocalSystem = *pfLocalSystem;
  365. return ERROR_SUCCESS;
  366. }
  367. DWORD
  368. WINAPI
  369. CPSSetWellKnownAccount(
  370. IN PVOID pvContext,
  371. IN DWORD dwAccount)
  372. {
  373. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvContext;
  374. if( pServerContext == NULL ||
  375. pServerContext->cbSize != sizeof(CRYPT_SERVER_CONTEXT))
  376. {
  377. return ERROR_INVALID_PARAMETER;
  378. }
  379. if(dwAccount != pServerContext->WellKnownAccount)
  380. {
  381. // We're setting the context account to a new value,
  382. // so NULL out the cached path string. A new one will be
  383. // created automatically, as necessary.
  384. if(pServerContext->szUserStorageArea)
  385. {
  386. SSFree(pServerContext->szUserStorageArea);
  387. pServerContext->szUserStorageArea = NULL;
  388. }
  389. pServerContext->WellKnownAccount = dwAccount;
  390. }
  391. return ERROR_SUCCESS;
  392. }
  393. DWORD
  394. WINAPI
  395. CPSQueryWellKnownAccount(
  396. IN PVOID pvContext,
  397. OUT DWORD *pdwAccount)
  398. {
  399. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvContext;
  400. if( pServerContext == NULL ||
  401. pServerContext->cbSize != sizeof(CRYPT_SERVER_CONTEXT))
  402. {
  403. return ERROR_INVALID_PARAMETER;
  404. }
  405. *pdwAccount = pServerContext->WellKnownAccount;
  406. return ERROR_SUCCESS;
  407. }
  408. DWORD
  409. CPSDuplicateClientAccessToken(
  410. IN PVOID pvContext, // server context
  411. IN OUT HANDLE *phToken
  412. )
  413. {
  414. HANDLE hToken = NULL;
  415. HANDLE hDuplicateToken;
  416. DWORD dwLastError = ERROR_SUCCESS;
  417. BOOL fSuccess;
  418. *phToken = NULL;
  419. //
  420. // make a duplicate of the client access token.
  421. //
  422. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvContext;
  423. if(!DuplicateTokenEx(pServerContext->hToken,
  424. 0,
  425. NULL,
  426. SecurityImpersonation,
  427. TokenImpersonation,
  428. &hDuplicateToken ))
  429. {
  430. dwLastError = GetLastError();
  431. }
  432. else
  433. *phToken = hDuplicateToken;
  434. return dwLastError;
  435. }
  436. DWORD
  437. WINAPI
  438. CPSGetUserName(
  439. IN PVOID pvContext,
  440. OUT LPWSTR *ppszUserName,
  441. OUT DWORD *pcchUserName
  442. )
  443. {
  444. WCHAR szBuf[MAX_PATH+1];
  445. DWORD cchBuf = MAX_PATH;
  446. DWORD dwLastError = ERROR_INVALID_PARAMETER;
  447. BOOL fLocalMachine = FALSE;
  448. BOOL fSuccess = FALSE;
  449. DWORD dwAccount = 0;
  450. //
  451. // if we are currently over-riding to Local System, we know the values
  452. // that need to be returned.
  453. //
  454. CPSOverrideToLocalSystem(
  455. pvContext,
  456. NULL, // don't change current over-ride BOOL
  457. &fLocalMachine
  458. );
  459. CPSQueryWellKnownAccount(pvContext,
  460. &dwAccount);
  461. if( fLocalMachine || dwAccount == DP_ACCOUNT_LOCAL_SYSTEM)
  462. {
  463. static const WCHAR szName1[] = TEXTUAL_SID_LOCAL_SYSTEM;
  464. CopyMemory( szBuf, szName1, sizeof(szName1) );
  465. cchBuf = sizeof(szName1) / sizeof(WCHAR);
  466. fSuccess = TRUE;
  467. }
  468. else if(dwAccount == DP_ACCOUNT_LOCAL_SERVICE)
  469. {
  470. static const WCHAR szName2[] = TEXTUAL_SID_LOCAL_SERVICE;
  471. CopyMemory( szBuf, szName2, sizeof(szName2) );
  472. cchBuf = sizeof(szName2) / sizeof(WCHAR);
  473. fSuccess = TRUE;
  474. }
  475. else if(dwAccount == DP_ACCOUNT_NETWORK_SERVICE)
  476. {
  477. static const WCHAR szName3[] = TEXTUAL_SID_NETWORK_SERVICE;
  478. CopyMemory( szBuf, szName3, sizeof(szName3) );
  479. cchBuf = sizeof(szName3) / sizeof(WCHAR);
  480. fSuccess = TRUE;
  481. }
  482. else
  483. {
  484. dwLastError = CPSImpersonateClient( pvContext );
  485. if(dwLastError != ERROR_SUCCESS)
  486. return dwLastError;
  487. fSuccess = GetUserTextualSid(
  488. NULL,
  489. szBuf,
  490. &cchBuf
  491. );
  492. CPSRevertToSelf( pvContext );
  493. }
  494. dwLastError = ERROR_NOT_ENOUGH_MEMORY;
  495. if( fSuccess )
  496. {
  497. *ppszUserName = (LPWSTR)SSAlloc( cchBuf * sizeof(WCHAR));
  498. if(*ppszUserName)
  499. {
  500. CopyMemory( *ppszUserName, szBuf, cchBuf * sizeof(WCHAR));
  501. if(pcchUserName)
  502. *pcchUserName = cchBuf;
  503. dwLastError = ERROR_SUCCESS;
  504. }
  505. }
  506. return dwLastError;
  507. }
  508. DWORD
  509. WINAPI
  510. CPSGetDerivedCredential(
  511. IN PVOID pvContext,
  512. OUT GUID *pCredentialID,
  513. IN DWORD dwFlags,
  514. IN PBYTE pbMixingBytes,
  515. IN DWORD cbMixingBytes,
  516. IN OUT BYTE rgbDerivedCredential[A_SHA_DIGEST_LEN]
  517. )
  518. {
  519. LUID LogonId;
  520. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvContext;
  521. DWORD dwLastError = ERROR_SUCCESS;
  522. if( pServerContext != NULL && pServerContext->cbSize != sizeof(CRYPT_SERVER_CONTEXT) )
  523. return ERROR_INVALID_PARAMETER;
  524. if( cbMixingBytes == 0 || pbMixingBytes == NULL )
  525. return ERROR_INVALID_PARAMETER;
  526. //
  527. // impersonate the client and get the LogonId associated with the client.
  528. //
  529. dwLastError = CPSImpersonateClient( pvContext );
  530. if( dwLastError != ERROR_SUCCESS )
  531. return dwLastError;
  532. if(!GetThreadAuthenticationId( GetCurrentThread(), &LogonId ))
  533. {
  534. dwLastError = GetLastError();
  535. CPSRevertToSelf( pvContext ); // don't check error return since we're already failing
  536. return dwLastError;
  537. }
  538. dwLastError = QueryDerivedCredential( pCredentialID,
  539. &LogonId,
  540. dwFlags,
  541. pbMixingBytes,
  542. cbMixingBytes,
  543. rgbDerivedCredential );
  544. CPSRevertToSelf( pvContext );
  545. return dwLastError;
  546. }
  547. DWORD
  548. WINAPI
  549. CPSGetSystemCredential(
  550. IN PVOID pvContext,
  551. IN BOOL fLocalMachine,
  552. IN OUT BYTE rgbSystemCredential[A_SHA_DIGEST_LEN]
  553. )
  554. {
  555. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvContext;
  556. if( pServerContext != NULL && pServerContext->cbSize != sizeof(CRYPT_SERVER_CONTEXT) )
  557. return ERROR_INVALID_PARAMETER;
  558. return GetSystemCredential( fLocalMachine, rgbSystemCredential);
  559. }
  560. DWORD
  561. WINAPI
  562. CPSCreateWorkerThread(
  563. IN PVOID pThreadFunc,
  564. IN PVOID pThreadArg
  565. )
  566. {
  567. if( !QueueUserWorkItem(
  568. (PTHREAD_START_ROUTINE)pThreadFunc,
  569. pThreadArg,
  570. WT_EXECUTELONGFUNCTION
  571. )) {
  572. return GetLastError();
  573. }
  574. return ERROR_SUCCESS;
  575. }
  576. DWORD CPSAudit(
  577. IN HANDLE hToken,
  578. IN DWORD dwAuditID,
  579. IN LPCWSTR wszMasterKeyID,
  580. IN LPCWSTR wszRecoveryServer,
  581. IN DWORD dwReason,
  582. IN LPCWSTR wszRecoveryKeyID,
  583. IN DWORD dwFailure)
  584. {
  585. NTSTATUS Status = STATUS_SUCCESS;
  586. UNICODE_STRING MasterKeyID;
  587. UNICODE_STRING RecoveryServer;
  588. UNICODE_STRING RecoveryKeyID;
  589. BOOL fReasonField = FALSE;
  590. PSID UserSid = NULL;
  591. fReasonField = ((SE_AUDITID_DPAPI_PROTECT == dwAuditID) ||
  592. (SE_AUDITID_DPAPI_UNPROTECT == dwAuditID) ||
  593. (SE_AUDITID_DPAPI_RECOVERY == dwAuditID));
  594. GetTokenUserSid(hToken, &UserSid);
  595. if(wszMasterKeyID)
  596. {
  597. RtlInitUnicodeString(&MasterKeyID, wszMasterKeyID);
  598. }
  599. else
  600. {
  601. RtlInitUnicodeString(&MasterKeyID, L"");
  602. }
  603. if(wszRecoveryServer)
  604. {
  605. RtlInitUnicodeString(&RecoveryServer, wszRecoveryServer);
  606. }
  607. else
  608. {
  609. RtlInitUnicodeString(&RecoveryServer, L"");
  610. }
  611. if(wszRecoveryKeyID)
  612. {
  613. RtlInitUnicodeString(&RecoveryKeyID, wszRecoveryKeyID);
  614. }
  615. else
  616. {
  617. RtlInitUnicodeString(&RecoveryKeyID, L"");
  618. }
  619. Status = LsaIAuditDPAPIEvent(
  620. dwAuditID,
  621. UserSid,
  622. &MasterKeyID,
  623. &RecoveryServer,
  624. fReasonField ? &dwReason : NULL,
  625. &RecoveryKeyID,
  626. &dwFailure
  627. );
  628. if(UserSid)
  629. {
  630. SSFree(UserSid);
  631. }
  632. return (DWORD)Status;
  633. }
  634. DWORD
  635. CPSGetUserStorageArea(
  636. IN PVOID pvContext,
  637. IN PSID pSid, // optional
  638. IN BOOL fCreate, // Create the storage area if it doesn't exist
  639. IN OUT LPWSTR *ppszUserStorageArea
  640. )
  641. {
  642. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvContext;
  643. WCHAR szUserStorageRoot[MAX_PATH+1];
  644. DWORD cbUserStorageRoot;
  645. const WCHAR szProductString[] = L"\\Microsoft\\Protect\\";
  646. DWORD cbProductString = sizeof(szProductString) - sizeof(WCHAR);
  647. const WCHAR szUserStorageForSystem[] = L"\\User";
  648. LPWSTR pszUser = NULL;
  649. DWORD cbUser;
  650. DWORD cchUser;
  651. LPCWSTR szOptionalTrailing;
  652. DWORD cbOptionalTrailing = 0;
  653. BOOL fLocalMachine = FALSE;
  654. DWORD dwAccount = 0;
  655. HANDLE hFile = INVALID_HANDLE_VALUE;
  656. PBYTE pbCurrent;
  657. BOOL fImpersonated = FALSE;
  658. DWORD dwLastError = ERROR_CANTOPEN;
  659. *ppszUserStorageArea = NULL;
  660. if(NULL == pServerContext)
  661. {
  662. return ERROR_INVALID_PARAMETER;
  663. }
  664. if(NULL == pSid)
  665. {
  666. //
  667. // If this is the current users sid, check to see if we've already
  668. // calculated this string.
  669. if(NULL != pServerContext->szUserStorageArea)
  670. {
  671. *ppszUserStorageArea = (LPWSTR)SSAlloc((wcslen(pServerContext->szUserStorageArea)+1)*sizeof(WCHAR));
  672. if(NULL == *ppszUserStorageArea)
  673. {
  674. return ERROR_NOT_ENOUGH_MEMORY;
  675. }
  676. wcscpy(*ppszUserStorageArea, pServerContext->szUserStorageArea);
  677. return ERROR_SUCCESS;
  678. }
  679. //
  680. // get the user name associated with the call.
  681. // Note: this is the textual Sid on NT, and the user name on Win95.
  682. //
  683. dwLastError = CPSGetUserName( pvContext, &pszUser, &cchUser );
  684. if(dwLastError != ERROR_SUCCESS)
  685. goto cleanup;
  686. cbUser = (cchUser-1) * sizeof(WCHAR);
  687. }
  688. else
  689. {
  690. WCHAR wszTextualSid[MAX_PATH+1];
  691. cchUser = MAX_PATH;
  692. // Note that the number of characters returned from
  693. // GetTextualSid includes the zero-terminator.
  694. if(!GetTextualSid(pSid, wszTextualSid, &cchUser))
  695. {
  696. dwLastError = ERROR_INVALID_PARAMETER;
  697. goto cleanup;
  698. }
  699. cbUser = (cchUser-1) * sizeof(WCHAR);
  700. pszUser = (LPWSTR)SSAlloc(cchUser*sizeof(WCHAR));
  701. if(NULL == pszUser)
  702. {
  703. dwLastError = ERROR_NOT_ENOUGH_MEMORY;
  704. goto cleanup;
  705. }
  706. wcscpy(pszUser, wszTextualSid);
  707. }
  708. //
  709. // impersonate the client user to test and create storage area if necessary
  710. //
  711. dwLastError = CPSImpersonateClient( pvContext );
  712. if( dwLastError != ERROR_SUCCESS )
  713. goto cleanup;
  714. fImpersonated = TRUE;
  715. //
  716. // see if the call is for shared, CRYPT_PROTECT_LOCAL_MACHINE
  717. // disposition.
  718. //
  719. CPSOverrideToLocalSystem(
  720. pvContext,
  721. NULL, // don't change current over-ride BOOL
  722. &fLocalMachine
  723. );
  724. CPSQueryWellKnownAccount(
  725. pvContext,
  726. &dwAccount);
  727. //
  728. // determine path to per-user storage area, based on whether this
  729. // is a local machine disposition call or a per-user disposition call.
  730. //
  731. if(fLocalMachine || (dwAccount != 0))
  732. {
  733. cbUserStorageRoot = GetSystemDirectoryW(
  734. szUserStorageRoot,
  735. sizeof(szUserStorageRoot) / sizeof(WCHAR)
  736. );
  737. cbUserStorageRoot *= sizeof(WCHAR);
  738. //
  739. // when the Sid is the SYSTEM sid, and this isn't a Local Machine
  740. // disposition call, add a trailing component to the storage path.
  741. //
  742. if((dwAccount == DP_ACCOUNT_LOCAL_SYSTEM) && !fLocalMachine)
  743. {
  744. cbOptionalTrailing = sizeof(szUserStorageForSystem) - sizeof(WCHAR);
  745. szOptionalTrailing = szUserStorageForSystem;
  746. }
  747. }
  748. else
  749. {
  750. dwLastError = PRGetProfilePath(NULL,
  751. szUserStorageRoot );
  752. if( dwLastError != ERROR_SUCCESS )
  753. {
  754. goto cleanup;
  755. }
  756. cbUserStorageRoot = lstrlenW( szUserStorageRoot ) * sizeof(WCHAR);
  757. }
  758. //
  759. // an empty string is not legal as the root component of the per-user
  760. // storage area.
  761. //
  762. if( cbUserStorageRoot == 0 )
  763. {
  764. dwLastError = ERROR_CANTOPEN;
  765. goto cleanup;
  766. }
  767. //
  768. // ensure returned string does not have trailing \
  769. //
  770. if( szUserStorageRoot[ (cbUserStorageRoot / sizeof(WCHAR)) - 1 ] == L'\\' )
  771. {
  772. szUserStorageRoot[ (cbUserStorageRoot / sizeof(WCHAR)) - 1 ] = L'\0';
  773. cbUserStorageRoot -= sizeof(WCHAR);
  774. }
  775. *ppszUserStorageArea = (LPWSTR)SSAlloc(
  776. cbUserStorageRoot +
  777. cbProductString +
  778. cbUser +
  779. cbOptionalTrailing +
  780. (2 * sizeof(WCHAR)) // trailing slash and NULL
  781. );
  782. if( *ppszUserStorageArea == NULL )
  783. {
  784. dwLastError = ERROR_NOT_ENOUGH_SERVER_MEMORY;
  785. goto cleanup;
  786. }
  787. pbCurrent = (PBYTE)*ppszUserStorageArea;
  788. CopyMemory(pbCurrent, szUserStorageRoot, cbUserStorageRoot);
  789. pbCurrent += cbUserStorageRoot;
  790. CopyMemory(pbCurrent, szProductString, cbProductString);
  791. pbCurrent += cbProductString;
  792. CopyMemory(pbCurrent, pszUser, cbUser);
  793. pbCurrent += cbUser; // note: cbUser does not include terminal NULL
  794. if(cbOptionalTrailing)
  795. {
  796. CopyMemory(pbCurrent, szOptionalTrailing, cbOptionalTrailing);
  797. pbCurrent += cbOptionalTrailing;
  798. }
  799. if( *((LPWSTR)pbCurrent - 1) != L'\\' )
  800. {
  801. *(LPWSTR)pbCurrent = L'\\';
  802. pbCurrent += sizeof(WCHAR);
  803. }
  804. *(LPWSTR)pbCurrent = L'\0';
  805. //
  806. // test for well-known file in the storage area. if it exists,
  807. // don't bother trying to create directory structure.
  808. //
  809. dwLastError = OpenFileInStorageArea(
  810. NULL, // NULL == already impersonating the client
  811. GENERIC_READ,
  812. *ppszUserStorageArea,
  813. REGVAL_PREFERRED_MK,
  814. &hFile
  815. );
  816. if( dwLastError == ERROR_SUCCESS)
  817. {
  818. CloseHandle( hFile );
  819. }
  820. else
  821. {
  822. if(fCreate)
  823. {
  824. dwLastError = DPAPICreateNestedDirectories(
  825. *ppszUserStorageArea,
  826. (LPWSTR)((LPBYTE)*ppszUserStorageArea + cbUserStorageRoot + sizeof(WCHAR))
  827. );
  828. }
  829. }
  830. if((ERROR_SUCCESS == dwLastError) &&
  831. (NULL == pSid))
  832. {
  833. pServerContext->szUserStorageArea = (LPWSTR)SSAlloc((wcslen(*ppszUserStorageArea)+1)*sizeof(WCHAR));
  834. if(NULL == pServerContext->szUserStorageArea)
  835. {
  836. dwLastError = ERROR_NOT_ENOUGH_MEMORY;
  837. }
  838. else
  839. {
  840. wcscpy(pServerContext->szUserStorageArea, *ppszUserStorageArea);
  841. }
  842. }
  843. cleanup:
  844. if( fImpersonated )
  845. CPSRevertToSelf( pvContext );
  846. if(pszUser)
  847. SSFree(pszUser);
  848. if( dwLastError != ERROR_SUCCESS && *ppszUserStorageArea )
  849. {
  850. SSFree( *ppszUserStorageArea );
  851. *ppszUserStorageArea = NULL;
  852. }
  853. return dwLastError;
  854. }
  855. #if 0
  856. HKEY GetLMRegistryProviderKey()
  857. {
  858. HKEY hBaseKey = NULL;
  859. DWORD dwCreate;
  860. DWORD dwDesiredAccess = KEY_READ | KEY_WRITE;
  861. static const WCHAR szKeyName[] = REG_CRYPTPROTECT_LOC L"\\" REG_CRYPTPROTECT_PROVIDERS_SUBKEYLOC;
  862. // Open Key //
  863. if (ERROR_SUCCESS !=
  864. RegCreateKeyExU(
  865. HKEY_LOCAL_MACHINE,
  866. szKeyName,
  867. 0,
  868. NULL, // address of class string
  869. 0,
  870. dwDesiredAccess,
  871. NULL,
  872. &hBaseKey,
  873. &dwCreate))
  874. goto Ret;
  875. Ret:
  876. return hBaseKey;
  877. }
  878. #endif
  879. DWORD GetPolicyBits()
  880. {
  881. return 0;
  882. }
  883. ///////////////////////////////////////////////////////////////////////
  884. // RPC-exposed functions
  885. //
  886. // these functions return a DWORD equivalent to GetLastError().
  887. // the client side stub code will check if the return code is not
  888. // ERROR_SUCCESS, and if this is the case, the client stub will return
  889. // FALSE and SetLastError() to this DWORD.
  890. //
  891. DWORD
  892. s_SSCryptProtectData(
  893. handle_t h,
  894. BYTE __RPC_FAR *__RPC_FAR *ppbOut,
  895. DWORD __RPC_FAR *pcbOut,
  896. BYTE __RPC_FAR *pbIn,
  897. DWORD cbIn,
  898. LPCWSTR szDataDescr,
  899. BYTE* pbOptionalEntropy,
  900. DWORD cbOptionalEntropy,
  901. PSSCRYPTPROTECTDATA_PROMPTSTRUCT pPromptStruct,
  902. DWORD dwFlags,
  903. BYTE* pbOptionalPassword,
  904. DWORD cbOptionalPassword
  905. )
  906. {
  907. DWORD dwRet;
  908. DWORD dwHeaderSize = sizeof(GUID)+sizeof(DWORD);
  909. PBYTE pbWritePtr;
  910. PBYTE pTemp;
  911. CRYPT_SERVER_CONTEXT ServerContext;
  912. // User mode cannot request encryption of system blobs
  913. if(dwFlags & CRYPTPROTECT_SYSTEM)
  914. {
  915. return ERROR_INVALID_PARAMETER;
  916. }
  917. // Create a server context.
  918. dwRet = CPSCreateServerContext(&ServerContext, h);
  919. if(dwRet != ERROR_SUCCESS)
  920. {
  921. return dwRet;
  922. }
  923. // get policy for this level
  924. // UNDONE: what do policy bits allow an admin to set?
  925. // maybe a recovery agent, other defaults?
  926. GetPolicyBits();
  927. dwRet = SPCryptProtect(
  928. &ServerContext,
  929. ppbOut,
  930. pcbOut,
  931. pbIn,
  932. cbIn,
  933. szDataDescr,
  934. pbOptionalEntropy,
  935. cbOptionalEntropy,
  936. pPromptStruct,
  937. dwFlags,
  938. pbOptionalPassword, // following 2 fields considered temporary
  939. cbOptionalPassword // until SAS UI supported
  940. );
  941. RtlSecureZeroMemory( pbIn, cbIn );
  942. if ( dwRet != ERROR_SUCCESS || *ppbOut == NULL )
  943. goto Ret;
  944. // move entire block down, sneak header in
  945. pTemp = (PBYTE)SSReAlloc(*ppbOut, *pcbOut + dwHeaderSize);
  946. if(NULL == pTemp)
  947. {
  948. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  949. SSFree(*ppbOut);
  950. *ppbOut = NULL;
  951. *pcbOut = 0;
  952. goto Ret;
  953. }
  954. *ppbOut = pTemp;
  955. MoveMemory(*ppbOut + dwHeaderSize, *ppbOut, *pcbOut);
  956. *pcbOut += dwHeaderSize;
  957. pbWritePtr = *ppbOut;
  958. *(DWORD*)pbWritePtr = CRYPTPROTECT_SVR_VERSION_1;
  959. pbWritePtr += sizeof(DWORD);
  960. CopyMemory(pbWritePtr, &g_guidDefaultProvider, sizeof(GUID));
  961. pbWritePtr += sizeof(GUID);
  962. dwRet = ERROR_SUCCESS;
  963. Ret:
  964. CPSDeleteServerContext( &ServerContext );
  965. return dwRet;
  966. }
  967. DWORD
  968. s_SSCryptUnprotectData(
  969. handle_t h,
  970. BYTE __RPC_FAR *__RPC_FAR *ppbOut,
  971. DWORD __RPC_FAR *pcbOut,
  972. BYTE __RPC_FAR *pbIn,
  973. DWORD cbIn,
  974. LPWSTR* ppszDataDescr,
  975. BYTE* pbOptionalEntropy,
  976. DWORD cbOptionalEntropy,
  977. PSSCRYPTPROTECTDATA_PROMPTSTRUCT pPromptStruct,
  978. DWORD dwFlags,
  979. BYTE* pbOptionalPassword,
  980. DWORD cbOptionalPassword
  981. )
  982. {
  983. DWORD dwRet;
  984. PBYTE pbReadPtr = pbIn;
  985. GUID guidProvider;
  986. CRYPT_SERVER_CONTEXT ServerContext;
  987. // Zero output parameters.
  988. *ppbOut = NULL;
  989. *pcbOut = 0;
  990. // User mode cannot request decryption of system blobs
  991. if(dwFlags & CRYPTPROTECT_SYSTEM)
  992. {
  993. return ERROR_INVALID_PARAMETER;
  994. }
  995. // Error out if input buffer is smaller than the minumum size.
  996. if(cbIn < sizeof(DWORD) + sizeof(GUID))
  997. {
  998. return ERROR_INVALID_DATA;
  999. }
  1000. // Create a server context.
  1001. dwRet = CPSCreateServerContext(&ServerContext, h);
  1002. if(dwRet != ERROR_SUCCESS)
  1003. {
  1004. return dwRet;
  1005. }
  1006. // UNDONE: what do policy bits allow an admin to set?
  1007. // maybe a recovery agent, other defaults?
  1008. GetPolicyBits();
  1009. if (*(DWORD*)pbReadPtr != CRYPTPROTECT_SVR_VERSION_1)
  1010. {
  1011. dwRet = ERROR_INVALID_DATA;
  1012. goto Ret;
  1013. }
  1014. pbReadPtr += sizeof(DWORD);
  1015. // next field in Data is provider GUID
  1016. CopyMemory(&guidProvider, pbReadPtr, sizeof(GUID));
  1017. pbReadPtr += sizeof(GUID);
  1018. dwRet = SPCryptUnprotect(
  1019. &ServerContext,
  1020. ppbOut,
  1021. pcbOut,
  1022. pbReadPtr,
  1023. (cbIn - (LONG)(pbReadPtr - pbIn)) , // eg (200 - (0x00340020 - 0x00340000))
  1024. ppszDataDescr,
  1025. pbOptionalEntropy,
  1026. cbOptionalEntropy,
  1027. pPromptStruct,
  1028. dwFlags,
  1029. pbOptionalPassword, // following 2 fields considered temporary
  1030. cbOptionalPassword // until SAS UI supported
  1031. );
  1032. RtlSecureZeroMemory( pbIn, cbIn );
  1033. if (dwRet != ERROR_SUCCESS)
  1034. goto Ret;
  1035. dwRet = ERROR_SUCCESS;
  1036. Ret:
  1037. CPSDeleteServerContext( &ServerContext );
  1038. return dwRet;
  1039. }
  1040. BOOLEAN
  1041. LsaICryptProtectData(
  1042. IN PVOID DataIn,
  1043. IN ULONG DataInLength,
  1044. IN PUNICODE_STRING DataDescr,
  1045. IN PVOID OptionalEntropy,
  1046. IN ULONG OptionalEntropyLength,
  1047. IN PVOID Reserved,
  1048. IN PVOID Reserved2,
  1049. IN ULONG Flags,
  1050. OUT PVOID * DataOut,
  1051. OUT PULONG DataOutLength)
  1052. {
  1053. DWORD dwRetVal = ERROR_SUCCESS;
  1054. CRYPT_SERVER_CONTEXT ServerContext;;
  1055. DWORD dwHeaderSize = sizeof(GUID)+sizeof(DWORD);
  1056. PBYTE pbWritePtr;
  1057. PBYTE pTemp;
  1058. dwRetVal = CPSCreateServerContext(&ServerContext, NULL);
  1059. if(dwRetVal != ERROR_SUCCESS)
  1060. {
  1061. SetLastError(dwRetVal);
  1062. return FALSE;
  1063. }
  1064. // check params
  1065. if ((DataOut == NULL) ||
  1066. (DataIn == NULL) ||
  1067. (NULL == DataDescr))
  1068. {
  1069. dwRetVal = ERROR_INVALID_PARAMETER;
  1070. goto error;
  1071. }
  1072. if(ServerContext.fImpersonating)
  1073. {
  1074. CPSRevertToSelf(&ServerContext);
  1075. }
  1076. // get policy for this level
  1077. // UNDONE: what do policy bits allow an admin to set?
  1078. // maybe a recovery agent, other defaults?
  1079. GetPolicyBits();
  1080. *DataOut = NULL;
  1081. *DataOutLength = 0;
  1082. dwRetVal = SPCryptProtect(
  1083. &ServerContext,
  1084. (PBYTE *)DataOut,
  1085. DataOutLength,
  1086. (PBYTE)DataIn,
  1087. DataInLength,
  1088. DataDescr?DataDescr->Buffer:NULL,
  1089. (PBYTE)OptionalEntropy,
  1090. OptionalEntropyLength,
  1091. NULL,
  1092. Flags,
  1093. NULL, // following 2 fields considered temporary
  1094. 0 // until SAS UI supported
  1095. );
  1096. if ( dwRetVal != ERROR_SUCCESS || *DataOut == NULL )
  1097. goto error;
  1098. // move entire block down, sneak header in
  1099. pTemp =(PBYTE) SSReAlloc(*DataOut, *DataOutLength + dwHeaderSize);
  1100. if(NULL == pTemp)
  1101. {
  1102. dwRetVal = ERROR_NOT_ENOUGH_MEMORY;
  1103. SSFree(*DataOut);
  1104. *DataOut = NULL;
  1105. *DataOutLength = 0;
  1106. goto error;
  1107. }
  1108. *DataOut = pTemp;
  1109. MoveMemory((PBYTE)*DataOut + dwHeaderSize, *DataOut, *DataOutLength);
  1110. *DataOutLength += dwHeaderSize;
  1111. pbWritePtr = (PBYTE)*DataOut;
  1112. *(DWORD*)pbWritePtr = CRYPTPROTECT_SVR_VERSION_1;
  1113. pbWritePtr += sizeof(DWORD);
  1114. CopyMemory(pbWritePtr, &g_guidDefaultProvider, sizeof(GUID));
  1115. pbWritePtr += sizeof(GUID);
  1116. error:
  1117. if(ServerContext.fImpersonating)
  1118. {
  1119. CPSImpersonateClient(&ServerContext);
  1120. }
  1121. CPSDeleteServerContext( &ServerContext );
  1122. if(dwRetVal != ERROR_SUCCESS) {
  1123. SetLastError(dwRetVal);
  1124. return FALSE;
  1125. }
  1126. return TRUE;
  1127. }
  1128. BOOLEAN
  1129. LsaICryptUnprotectData(
  1130. IN PVOID DataIn,
  1131. IN ULONG DataInLength,
  1132. IN PVOID OptionalEntropy,
  1133. IN ULONG OptionalEntropyLength,
  1134. IN PVOID Reserved,
  1135. IN PVOID Reserved2,
  1136. IN ULONG Flags,
  1137. OUT PUNICODE_STRING DataDescr,
  1138. OUT PVOID * DataOut,
  1139. OUT PULONG DataOutLength)
  1140. {
  1141. DWORD dwRetVal = ERROR_SUCCESS;
  1142. CRYPT_SERVER_CONTEXT ServerContext;;
  1143. DWORD dwHeaderSize = sizeof(GUID)+sizeof(DWORD);
  1144. PBYTE pbWritePtr;
  1145. LPWSTR wszDataDescr = NULL;
  1146. dwRetVal = CPSCreateServerContext(&ServerContext, NULL);
  1147. if(dwRetVal != ERROR_SUCCESS)
  1148. {
  1149. SetLastError(dwRetVal);
  1150. return FALSE;
  1151. }
  1152. // check params
  1153. if ((DataOut == NULL) ||
  1154. (DataIn == NULL))
  1155. {
  1156. dwRetVal = ERROR_INVALID_PARAMETER;
  1157. goto error;
  1158. }
  1159. if(ServerContext.fImpersonating)
  1160. {
  1161. CPSRevertToSelf(&ServerContext);
  1162. }
  1163. // don't validate flags parameter
  1164. // get policy for this level
  1165. // UNDONE: what do policy bits allow an admin to set?
  1166. // maybe a recovery agent, other defaults?
  1167. GetPolicyBits();
  1168. //
  1169. // define outer+inner wrapper for security blob.
  1170. // this won't be necessary once SAS support is provided by the OS.
  1171. //
  1172. typedef struct {
  1173. DWORD dwOuterVersion;
  1174. GUID guidProvider;
  1175. DWORD dwVersion;
  1176. GUID guidMK;
  1177. DWORD dwPromptFlags;
  1178. DWORD cbDataDescr;
  1179. WCHAR szDataDescr[1];
  1180. } sec_blob, *psec_blob;
  1181. sec_blob *SecurityBlob = (sec_blob*)(DataIn);
  1182. //
  1183. // zero so client stub allocates
  1184. //
  1185. *DataOut = NULL;
  1186. *DataOutLength = 0;
  1187. //
  1188. // only call UI function if prompt flags dictate, because we don't
  1189. // want to bring in cryptui.dll unless necessary.
  1190. //
  1191. if( ((SecurityBlob->dwPromptFlags & CRYPTPROTECT_PROMPT_ON_UNPROTECT) ||
  1192. (SecurityBlob->dwPromptFlags & CRYPTPROTECT_PROMPT_ON_PROTECT))
  1193. )
  1194. {
  1195. dwRetVal = ERROR_INVALID_PARAMETER;
  1196. goto error;
  1197. } else {
  1198. if(SecurityBlob->dwPromptFlags & CRYPTPROTECT_PROMPT_STRONG )
  1199. {
  1200. dwRetVal = ERROR_INVALID_PARAMETER;
  1201. goto error;
  1202. }
  1203. }
  1204. if (SecurityBlob->dwOuterVersion != CRYPTPROTECT_SVR_VERSION_1)
  1205. {
  1206. dwRetVal = ERROR_INVALID_DATA;
  1207. goto error;
  1208. }
  1209. if(0 != memcmp(&SecurityBlob->guidProvider, &g_guidDefaultProvider, sizeof(GUID)))
  1210. {
  1211. dwRetVal = ERROR_INVALID_DATA;
  1212. goto error;
  1213. }
  1214. Flags |= CRYPTPROTECT_IN_PROCESS;
  1215. dwRetVal = SPCryptUnprotect(
  1216. &ServerContext,
  1217. (PBYTE *)DataOut,
  1218. DataOutLength,
  1219. (PBYTE)DataIn + sizeof(DWORD) + sizeof(GUID),
  1220. (DataInLength - (LONG)(sizeof(DWORD) + sizeof(GUID))) ,
  1221. DataDescr?&wszDataDescr:NULL,
  1222. (PBYTE)OptionalEntropy,
  1223. OptionalEntropyLength,
  1224. NULL,
  1225. Flags,
  1226. NULL, // following 2 fields considered temporary
  1227. 0 // until SAS UI supported
  1228. );
  1229. if (dwRetVal != ERROR_SUCCESS)
  1230. {
  1231. goto error;
  1232. }
  1233. if(NULL != DataDescr)
  1234. {
  1235. RtlInitUnicodeString(DataDescr, wszDataDescr);
  1236. }
  1237. error:
  1238. if(ServerContext.fImpersonating)
  1239. {
  1240. // Impersonate back to the impersonation context
  1241. CPSImpersonateClient(&ServerContext);
  1242. }
  1243. CPSDeleteServerContext( &ServerContext );
  1244. SetLastError(dwRetVal);
  1245. if(dwRetVal != ERROR_SUCCESS && dwRetVal != CRYPT_I_NEW_PROTECTION_REQUIRED ) {
  1246. return FALSE;
  1247. }
  1248. return TRUE;
  1249. }
  1250. DWORD
  1251. WINAPI
  1252. CPSGetSidHistory(
  1253. IN PVOID pvContext,
  1254. OUT PSID **papsidHistory,
  1255. OUT DWORD *cpsidHistory
  1256. )
  1257. {
  1258. DWORD dwLastError = ERROR_SUCCESS;
  1259. BYTE FastBuffer[256];
  1260. BYTE GroupsFastBuffer[256];
  1261. LPBYTE SlowBuffer = NULL;
  1262. PTOKEN_USER ptgUser;
  1263. PTOKEN_GROUPS ptgGroups = NULL;
  1264. DWORD cbBuffer;
  1265. DWORD cbSid;
  1266. DWORD cSids = 0;
  1267. PBYTE pbCurrentSid = NULL;
  1268. DWORD i;
  1269. PCRYPT_SERVER_CONTEXT pServerContext = (PCRYPT_SERVER_CONTEXT)pvContext;
  1270. //
  1271. // try querying based on a fast stack based buffer first.
  1272. //
  1273. ptgUser = (PTOKEN_USER)FastBuffer;
  1274. cbBuffer = sizeof(FastBuffer);
  1275. if(!GetTokenInformation(
  1276. pServerContext->hToken, // identifies access token
  1277. TokenUser, // TokenUser info type
  1278. ptgUser, // retrieved info buffer
  1279. cbBuffer, // size of buffer passed-in
  1280. &cbBuffer // required buffer size
  1281. ))
  1282. {
  1283. dwLastError = GetLastError();
  1284. if(dwLastError != ERROR_INSUFFICIENT_BUFFER)
  1285. {
  1286. goto error;
  1287. }
  1288. //
  1289. // try again with the specified buffer size
  1290. //
  1291. ptgUser = (PTOKEN_USER)SSAlloc(cbBuffer);
  1292. if(NULL == ptgUser)
  1293. {
  1294. dwLastError = ERROR_NOT_ENOUGH_MEMORY;
  1295. goto error;
  1296. }
  1297. if(!GetTokenInformation(
  1298. pServerContext->hToken, // identifies access token
  1299. TokenUser, // TokenUser info type
  1300. ptgUser, // retrieved info buffer
  1301. cbBuffer, // size of buffer passed-in
  1302. &cbBuffer // required buffer size
  1303. ))
  1304. {
  1305. dwLastError = GetLastError();
  1306. goto error;
  1307. }
  1308. }
  1309. //
  1310. // try querying based on a fast stack based buffer first.
  1311. //
  1312. ptgGroups = (PTOKEN_GROUPS)GroupsFastBuffer;
  1313. cbBuffer = sizeof(GroupsFastBuffer);
  1314. if(!GetTokenInformation(
  1315. pServerContext->hToken, // identifies access token
  1316. TokenGroups, // TokenUser info type
  1317. ptgGroups, // retrieved info buffer
  1318. cbBuffer, // size of buffer passed-in
  1319. &cbBuffer // required buffer size
  1320. ))
  1321. {
  1322. dwLastError = GetLastError();
  1323. if(dwLastError != ERROR_INSUFFICIENT_BUFFER)
  1324. {
  1325. goto error;
  1326. }
  1327. dwLastError = ERROR_SUCCESS;
  1328. //
  1329. // try again with the specified buffer size
  1330. //
  1331. ptgGroups = (PTOKEN_GROUPS)SSAlloc(cbBuffer);
  1332. if(NULL == ptgGroups)
  1333. {
  1334. dwLastError = ERROR_NOT_ENOUGH_MEMORY;
  1335. goto error;
  1336. }
  1337. if(!GetTokenInformation(
  1338. pServerContext->hToken, // identifies access token
  1339. TokenGroups, // TokenUser info type
  1340. ptgGroups, // retrieved info buffer
  1341. cbBuffer, // size of buffer passed-in
  1342. &cbBuffer // required buffer size
  1343. ))
  1344. {
  1345. dwLastError = GetLastError();
  1346. goto error;
  1347. }
  1348. }
  1349. //
  1350. // if we got the token info successfully, copy the
  1351. // relevant element for the caller.
  1352. //
  1353. cbSid = GetLengthSid(ptgUser->User.Sid);
  1354. cSids = 1;
  1355. for(i=0; i < ptgGroups->GroupCount; i++)
  1356. {
  1357. if(0 == (SE_GROUP_ENABLED & ptgGroups->Groups[i].Attributes))
  1358. {
  1359. continue;
  1360. }
  1361. if(0 == ((SE_GROUP_OWNER | SE_GROUP_USE_FOR_DENY_ONLY) & ptgGroups->Groups[i].Attributes))
  1362. {
  1363. continue;
  1364. }
  1365. cbSid += GetLengthSid(ptgGroups->Groups[i].Sid);
  1366. cSids ++;
  1367. }
  1368. *cpsidHistory = cSids;
  1369. *papsidHistory = (PSID *)SSAlloc(cSids*sizeof(PSID) + cbSid );
  1370. if(*papsidHistory == NULL)
  1371. {
  1372. dwLastError = ERROR_NOT_ENOUGH_MEMORY;
  1373. goto error;
  1374. }
  1375. else
  1376. {
  1377. pbCurrentSid = (PBYTE)((*papsidHistory)+cSids);
  1378. // Fill in the primary user SID
  1379. (*papsidHistory)[0] = (PSID)pbCurrentSid;
  1380. cbSid = GetLengthSid(ptgUser->User.Sid);
  1381. CopySid(cbSid, pbCurrentSid, ptgUser->User.Sid);
  1382. pbCurrentSid += cbSid;
  1383. cSids = 1;
  1384. // Fill in the rest of the SIDs
  1385. for(i=0; i < ptgGroups->GroupCount; i++)
  1386. {
  1387. if(0 == (SE_GROUP_ENABLED & ptgGroups->Groups[i].Attributes))
  1388. {
  1389. continue;
  1390. }
  1391. if(0 == ((SE_GROUP_OWNER | SE_GROUP_USE_FOR_DENY_ONLY) & ptgGroups->Groups[i].Attributes))
  1392. {
  1393. continue;
  1394. }
  1395. (*papsidHistory)[cSids++] = pbCurrentSid;
  1396. cbSid = GetLengthSid(ptgGroups->Groups[i].Sid);
  1397. CopySid(cbSid, pbCurrentSid,ptgGroups->Groups[i].Sid);
  1398. pbCurrentSid += cbSid;
  1399. }
  1400. }
  1401. error:
  1402. if(FastBuffer != (PBYTE)ptgUser)
  1403. {
  1404. SSFree(ptgUser);
  1405. }
  1406. if(GroupsFastBuffer != (PBYTE)ptgGroups)
  1407. {
  1408. SSFree(ptgGroups);
  1409. }
  1410. return dwLastError;
  1411. }