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.

1311 lines
42 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. create.c
  5. Abstract:
  6. This module will handle the IRP_MJ_CREATE (and all associated support
  7. routines) requests.
  8. Author:
  9. Robert Gu (robertg) 29-Oct-1996
  10. Environment:
  11. Kernel Mode Only
  12. Revision History:
  13. --*/
  14. #include "efs.h"
  15. #include "efsrtl.h"
  16. #include "efsext.h"
  17. #ifdef ALLOC_PRAGMA
  18. //
  19. // cannot make this code paged because of calls to
  20. // virtual memory functions.
  21. //
  22. //#pragma alloc_text(PAGE, EFSFilePostCreate)
  23. //#pragma alloc_text(PAGE, EFSPostCreate)
  24. //
  25. #endif
  26. NTSTATUS
  27. EFSFilePostCreate(
  28. IN PDEVICE_OBJECT VolDo,
  29. IN PIRP Irp,
  30. IN PFILE_OBJECT FileObject,
  31. IN NTSTATUS Status,
  32. IN OUT PVOID *PCreateContext
  33. )
  34. {
  35. PEFS_CONTEXT pEfsContext;
  36. KIRQL savedIrql;
  37. NTSTATUS EfsStatus = STATUS_SUCCESS;
  38. PAGED_CODE();
  39. if (!PCreateContext) {
  40. return Status;
  41. }
  42. pEfsContext = *PCreateContext;
  43. if (( NT_SUCCESS( Status ) && (Status != STATUS_PENDING) && (Status != STATUS_REPARSE))
  44. && pEfsContext){
  45. if ( NO_FURTHER_PROCESSING != pEfsContext->Status ){
  46. PIO_STACK_LOCATION irpSp;
  47. irpSp = IoGetCurrentIrpStackLocation( Irp );
  48. #if DBG
  49. if ( (EFSTRACEALL | EFSTRACELIGHT ) & EFSDebug ){
  50. DbgPrint( " EFSFILTER: Begin post create. \n" );
  51. }
  52. #endif
  53. if ((pEfsContext->EfsStreamData) &&
  54. (EFS_STREAM_TRANSITION == ((PEFS_STREAM)(pEfsContext->EfsStreamData))->Status)) {
  55. PSID SystemSid;
  56. SID_IDENTIFIER_AUTHORITY IdentifierAuthority = SECURITY_NT_AUTHORITY;
  57. //
  58. // $EFS indicates transition state.
  59. // Only the system can open it
  60. //
  61. SystemSid = ExAllocatePoolWithTag(
  62. PagedPool,
  63. RtlLengthRequiredSid(1),
  64. 'msfE'
  65. );
  66. if ( SystemSid ){
  67. EfsStatus = RtlInitializeSid( SystemSid, &IdentifierAuthority, (UCHAR) 1 );
  68. if ( NT_SUCCESS(EfsStatus) ){
  69. PACCESS_TOKEN accessToken = NULL;
  70. PTOKEN_USER UserId = NULL;
  71. *(RtlSubAuthoritySid(SystemSid, 0 )) = SECURITY_LOCAL_SYSTEM_RID;
  72. //
  73. // We got the system SID. Now try to get the caller's SID.
  74. //
  75. accessToken = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.ClientToken;
  76. if(!accessToken) {
  77. accessToken = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.PrimaryToken;
  78. }
  79. if ( accessToken ){
  80. //
  81. // Get User ID
  82. //
  83. EfsStatus = SeQueryInformationToken(
  84. accessToken,
  85. TokenUser,
  86. &UserId
  87. );
  88. if ( NT_SUCCESS(EfsStatus) ){
  89. //
  90. // Got the user SID
  91. //
  92. if ( !RtlEqualSid ( SystemSid, UserId->User.Sid) ) {
  93. EfsStatus = STATUS_ACCESS_DENIED;
  94. }
  95. }
  96. ExFreePool( UserId );
  97. } else {
  98. //
  99. // Cannot get the user token
  100. //
  101. EfsStatus = STATUS_ACCESS_DENIED;
  102. }
  103. }
  104. ExFreePool( SystemSid );
  105. } else {
  106. EfsStatus = STATUS_INSUFFICIENT_RESOURCES;
  107. }
  108. } else {
  109. //
  110. // $EFS in normal status
  111. // Set Key Blob and/or write $EFS
  112. //
  113. // Legacy problem, The fourth parameter of EfsPostCreate (OpenType)
  114. // was used to indicate a recovery open. The design was changed. Now
  115. // this parameter is not used. It is not worth to take out the parameter
  116. // now. This will need to change several modules, EFS.SYS, KSECDD.SYS
  117. // SEcur32.lib and LSASRV.DLL. We might just leave it as reserved for future use.
  118. // To speed up a little bit, pass in 0.
  119. //
  120. EfsStatus = EFSPostCreate(
  121. VolDo,
  122. Irp,
  123. pEfsContext,
  124. 0
  125. );
  126. }
  127. }
  128. }
  129. if (pEfsContext){
  130. //
  131. // Release memory if necessary
  132. //
  133. *PCreateContext = NULL;
  134. if ( pEfsContext->EfsStreamData ) {
  135. ExFreePool(pEfsContext->EfsStreamData);
  136. pEfsContext->EfsStreamData = NULL;
  137. }
  138. ExFreeToNPagedLookasideList(&(EfsData.EfsContextPool), pEfsContext );
  139. }
  140. if (!NT_SUCCESS(EfsStatus)) {
  141. return EfsStatus;
  142. }
  143. return Status; // If EFS operation succeeded, just return the original status code.
  144. }
  145. NTSTATUS
  146. EFSPostCreate(
  147. IN PDEVICE_OBJECT DeviceObject,
  148. IN PIRP Irp,
  149. IN PEFS_CONTEXT EfsContext,
  150. IN ULONG OpenType
  151. )
  152. /*++
  153. Routine Description:
  154. This function calls the EFS server to get FEK, $EFS, set Key Blob and or write $EFS.
  155. We could not use user's space to talk to LSA so we need to attach to LSA to allocate
  156. memory in LSA space. We could cause APC dead lock if we call LSA while attached to LSA.
  157. We need to detach before calling LSA and reattach to get data back from LSA.
  158. Arguments:
  159. DeviceObject - Pointer to the target device object.
  160. Irp - Pointer to the I/O Request Packet that represents the operation.
  161. EfsContext - A context block associated with the file object.
  162. OpenType - File create(open) option
  163. IrpContext - NTFS internal data
  164. FileHdl - NTFS internal data
  165. AttributeHandle - NTFS internal data
  166. --*/
  167. {
  168. PEFS_KEY fek = NULL;
  169. PEFS_DATA_STREAM_HEADER efsStream = NULL;
  170. PVOID currentEfsStream = NULL;
  171. NTSTATUS status = STATUS_SUCCESS;
  172. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  173. PVOID bufferBase = NULL;
  174. ULONG currentEfsStreamLength = 0;
  175. ULONG bufferLength;
  176. SIZE_T regionSize = 0;
  177. PACCESS_TOKEN accessToken = NULL;
  178. PTOKEN_USER UserId = NULL;
  179. GUID *EfsId = NULL;
  180. HANDLE CrntProcess = NULL;
  181. BOOLEAN ProcessAttached = FALSE;
  182. BOOLEAN ProcessNeedAttach = FALSE;
  183. SECURITY_IMPERSONATION_LEVEL ImpersonationLevel = SecurityImpersonation;
  184. KAPC_STATE ApcState;
  185. /*
  186. PIO_SECURITY_CONTEXT sContext;
  187. sContext = irpSp->Parameters.Create.SecurityContext;
  188. DbgPrint( "\n PostCreate: Desired Access %x\n", sContext->DesiredAccess );
  189. DbgPrint( "\n PostCreate: Orginal Desired Access %x\n", sContext->AccessState->OriginalDesiredAccess );
  190. DbgPrint( "\n PostCreate: PrevGrant Access %x\n", sContext->AccessState->PreviouslyGrantedAccess );
  191. DbgPrint( "\n PostCreate: Remaining Desired Access %x\n", sContext->AccessState->RemainingDesiredAccess );
  192. */
  193. //
  194. // Check if we can use the cache to verify the open
  195. //
  196. if ( !(EfsContext->Status & NO_OPEN_CACHE_CHECK) ){
  197. if ( irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.ClientToken ){
  198. accessToken = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.ClientToken;
  199. ImpersonationLevel = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.ImpersonationLevel;
  200. } else {
  201. accessToken = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.PrimaryToken;
  202. }
  203. if ( accessToken ){
  204. //
  205. // Get User ID
  206. //
  207. status = SeQueryInformationToken(
  208. accessToken,
  209. TokenUser,
  210. &UserId
  211. );
  212. if ( NT_SUCCESS(status) ){
  213. if ( EfsFindInCache(
  214. &((( PEFS_DATA_STREAM_HEADER ) EfsContext->EfsStreamData)->EfsId),
  215. UserId
  216. )) {
  217. ExFreePool( UserId );
  218. #if DBG
  219. if ( (EFSTRACEALL ) & EFSDebug ){
  220. DbgPrint( " EFS:Open with cache. \n" );
  221. }
  222. #endif
  223. return ( STATUS_SUCCESS );
  224. }
  225. }
  226. //
  227. // UserId will be freed later
  228. //
  229. }
  230. //
  231. // Check cache failure should not block the normal operations
  232. //
  233. status = STATUS_SUCCESS;
  234. }
  235. //
  236. // Clear the cache bit
  237. //
  238. EfsContext->Status &= ~NO_OPEN_CACHE_CHECK;
  239. //
  240. // Check if it is ACCESS_ATTRIBUTE ONLY
  241. //
  242. if ( !( irpSp->Parameters.Create.SecurityContext->AccessState->PreviouslyGrantedAccess &
  243. ( FILE_APPEND_DATA | FILE_READ_DATA | FILE_WRITE_DATA | FILE_EXECUTE )) &&
  244. ( EfsContext->Status & TURN_ON_ENCRYPTION_BIT ) &&
  245. ( !(EfsContext->Status & (NEW_FILE_EFS_REQUIRED | NEW_DIR_EFS_REQUIRED)))){
  246. //
  247. // A new stream is to be created without data access required. We might not
  248. // have the keys to decrypt the $EFS. We just need to turn on the bit here.
  249. // Changed the real action required.
  250. // Free the memory not required by this action.
  251. //
  252. #if DBG
  253. if ( (EFSTRACEALL ) & EFSDebug ){
  254. DbgPrint( " EFS:Open accessing attr only. \n" );
  255. }
  256. #endif
  257. if (EfsContext->EfsStreamData){
  258. ExFreePool(EfsContext->EfsStreamData);
  259. EfsContext->EfsStreamData = NULL;
  260. }
  261. EfsContext->Status = TURN_ON_ENCRYPTION_BIT | TURN_ON_BIT_ONLY ;
  262. } else if ( !(EfsContext->Status & TURN_ON_BIT_ONLY) ) {
  263. if (accessToken == NULL){
  264. if ( irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.ClientToken ){
  265. accessToken = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.ClientToken;
  266. ImpersonationLevel = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.ImpersonationLevel;
  267. } else {
  268. accessToken = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.PrimaryToken;
  269. }
  270. //
  271. // Get User ID
  272. //
  273. status = SeQueryInformationToken(
  274. accessToken,
  275. TokenUser,
  276. &UserId
  277. );
  278. if (!NT_SUCCESS(status)) {
  279. //
  280. // Do not refresh the cache
  281. //
  282. UserId = NULL;
  283. status = STATUS_SUCCESS;
  284. }
  285. }
  286. //
  287. // Allocate virtual memory.
  288. // Move the $EFS to virtual memory, LPC requires this.
  289. //
  290. if ( PsGetCurrentProcess() != EfsData.LsaProcess ){
  291. ProcessNeedAttach = TRUE;
  292. status = ObReferenceObjectByPointer(
  293. EfsData.LsaProcess,
  294. 0,
  295. NULL,
  296. KernelMode);
  297. if ( NT_SUCCESS(status) ) {
  298. KeStackAttachProcess (
  299. EfsData.LsaProcess,
  300. &ApcState
  301. );
  302. ProcessAttached = TRUE;
  303. }
  304. }
  305. CrntProcess = NtCurrentProcess();
  306. if ( NT_SUCCESS(status) ) {
  307. if (EfsContext->EfsStreamData){
  308. regionSize = currentEfsStreamLength = * (ULONG*)(EfsContext->EfsStreamData);
  309. status = ZwAllocateVirtualMemory(
  310. CrntProcess,
  311. (PVOID *) &currentEfsStream,
  312. 0,
  313. &regionSize,
  314. MEM_COMMIT,
  315. PAGE_READWRITE
  316. );
  317. }
  318. }
  319. }
  320. if ( NT_SUCCESS(status) ){
  321. BOOLEAN OldCopyOnOpen;
  322. BOOLEAN OldEffectiveOnly;
  323. SECURITY_IMPERSONATION_LEVEL OldImpersonationLevel;
  324. PACCESS_TOKEN OldClientToken;
  325. OldClientToken = PsReferenceImpersonationToken(
  326. PsGetCurrentThread(),
  327. &OldCopyOnOpen,
  328. &OldEffectiveOnly,
  329. &OldImpersonationLevel
  330. );
  331. if ( EfsContext->Status != (TURN_ON_ENCRYPTION_BIT | TURN_ON_BIT_ONLY) &&
  332. ( NULL != currentEfsStream) ){
  333. RtlCopyMemory(
  334. currentEfsStream,
  335. EfsContext->EfsStreamData,
  336. currentEfsStreamLength
  337. );
  338. //
  339. // Free the memory first to increase chance of getting new memory
  340. //
  341. ExFreePool(EfsContext->EfsStreamData);
  342. EfsContext->EfsStreamData = NULL;
  343. }
  344. //
  345. // Detach process before calling user mode
  346. //
  347. if (ProcessAttached){
  348. KeUnstackDetachProcess(&ApcState);
  349. ProcessAttached = FALSE;
  350. }
  351. switch ( EfsContext->Status & ACTION_REQUIRED){
  352. case VERIFY_USER_REQUIRED:
  353. status = PsImpersonateClient(
  354. PsGetCurrentThread(),
  355. accessToken,
  356. TRUE,
  357. TRUE,
  358. ImpersonationLevel
  359. );
  360. //
  361. // Call service to verify the user
  362. //
  363. if (NT_SUCCESS(status)) {
  364. status = EfsDecryptFek(
  365. &fek,
  366. (PEFS_DATA_STREAM_HEADER) currentEfsStream,
  367. currentEfsStreamLength,
  368. OpenType,
  369. &efsStream,
  370. &bufferBase,
  371. &bufferLength
  372. );
  373. if ( OldClientToken ) {
  374. PsImpersonateClient(
  375. PsGetCurrentThread(),
  376. OldClientToken,
  377. OldCopyOnOpen,
  378. OldEffectiveOnly,
  379. OldImpersonationLevel
  380. );
  381. PsDereferenceImpersonationToken(OldClientToken);
  382. } else {
  383. PsRevertToSelf( );
  384. }
  385. } else {
  386. //
  387. // Impersonation failed
  388. //
  389. if ( OldClientToken ) {
  390. PsDereferenceImpersonationToken(OldClientToken);
  391. }
  392. }
  393. break;
  394. case NEW_FILE_EFS_REQUIRED:
  395. //
  396. // Call service to get new FEK, $EFS
  397. //
  398. if (EfsContext->Flags & SYSTEM_IS_READONLY) {
  399. ASSERT(FALSE);
  400. status = STATUS_MEDIA_WRITE_PROTECTED;
  401. if ( OldClientToken ) {
  402. PsDereferenceImpersonationToken(OldClientToken);
  403. }
  404. break;
  405. }
  406. status = PsImpersonateClient(
  407. PsGetCurrentThread(),
  408. accessToken,
  409. TRUE,
  410. TRUE,
  411. ImpersonationLevel
  412. );
  413. if (NT_SUCCESS(status)) {
  414. status = EfsGenerateKey(
  415. &fek,
  416. &efsStream,
  417. (PEFS_DATA_STREAM_HEADER) currentEfsStream,
  418. currentEfsStreamLength,
  419. &bufferBase,
  420. &bufferLength
  421. );
  422. if ( OldClientToken ) {
  423. PsImpersonateClient(
  424. PsGetCurrentThread(),
  425. OldClientToken,
  426. OldCopyOnOpen,
  427. OldEffectiveOnly,
  428. OldImpersonationLevel
  429. );
  430. PsDereferenceImpersonationToken(OldClientToken);
  431. } else {
  432. PsRevertToSelf( );
  433. }
  434. } else {
  435. //
  436. // Impersonation failed
  437. //
  438. if ( OldClientToken ) {
  439. PsDereferenceImpersonationToken(OldClientToken);
  440. }
  441. }
  442. break;
  443. case NEW_DIR_EFS_REQUIRED:
  444. //
  445. // Call service to get new $EFS
  446. //
  447. if (EfsContext->Flags & SYSTEM_IS_READONLY) {
  448. ASSERT(FALSE);
  449. status = STATUS_MEDIA_WRITE_PROTECTED;
  450. if ( OldClientToken ) {
  451. PsDereferenceImpersonationToken(OldClientToken);
  452. }
  453. break;
  454. }
  455. status = PsImpersonateClient(
  456. PsGetCurrentThread(),
  457. accessToken,
  458. TRUE,
  459. TRUE,
  460. ImpersonationLevel
  461. );
  462. if (NT_SUCCESS(status)) {
  463. status = GenerateDirEfs(
  464. (PEFS_DATA_STREAM_HEADER) currentEfsStream,
  465. currentEfsStreamLength,
  466. &efsStream,
  467. &bufferBase,
  468. &bufferLength
  469. );
  470. if ( OldClientToken ) {
  471. PsImpersonateClient(
  472. PsGetCurrentThread(),
  473. OldClientToken,
  474. OldCopyOnOpen,
  475. OldEffectiveOnly,
  476. OldImpersonationLevel
  477. );
  478. PsDereferenceImpersonationToken(OldClientToken);
  479. } else {
  480. PsRevertToSelf( );
  481. }
  482. } else {
  483. //
  484. // Impersonation failed
  485. //
  486. if ( OldClientToken ) {
  487. PsDereferenceImpersonationToken(OldClientToken);
  488. }
  489. }
  490. break;
  491. case TURN_ON_BIT_ONLY:
  492. //
  493. // Fall through intended
  494. //
  495. default:
  496. if ( OldClientToken ) {
  497. PsDereferenceImpersonationToken(OldClientToken);
  498. }
  499. break;
  500. }
  501. if ( ProcessNeedAttach ){
  502. KeStackAttachProcess (
  503. EfsData.LsaProcess,
  504. &ApcState
  505. );
  506. ProcessAttached = TRUE;
  507. }
  508. if (fek && (fek->Algorithm == CALG_3DES) && !EfsData.FipsFunctionTable.Fips3Des3Key ) {
  509. //
  510. // User requested 3des but fips is not available, quit.
  511. //
  512. if (bufferBase){
  513. SIZE_T bufferSize;
  514. bufferSize = bufferLength;
  515. ZwFreeVirtualMemory(
  516. CrntProcess,
  517. &bufferBase,
  518. &bufferSize,
  519. MEM_RELEASE
  520. );
  521. }
  522. status = STATUS_ACCESS_DENIED;
  523. }
  524. if ( NT_SUCCESS(status) ){
  525. KEVENT event;
  526. IO_STATUS_BLOCK ioStatus;
  527. PIRP fsCtlIrp;
  528. PIO_STACK_LOCATION fsCtlIrpSp;
  529. ULONG inputDataLength;
  530. ULONG actionType;
  531. ULONG usingCurrentEfs;
  532. ULONG FsCode;
  533. PULONG pUlong;
  534. //
  535. // We got our FEK, $EFS. Set it with a FSCTL
  536. // Prepare the input data buffer first
  537. //
  538. switch ( EfsContext->Status & ACTION_REQUIRED ){
  539. case VERIFY_USER_REQUIRED:
  540. EfsId = ExAllocatePoolWithTag(
  541. PagedPool,
  542. sizeof (GUID),
  543. 'msfE'
  544. );
  545. if ( EfsId ){
  546. RtlCopyMemory(
  547. EfsId,
  548. &(((PEFS_DATA_STREAM_HEADER) currentEfsStream)->EfsId),
  549. sizeof( GUID ) );
  550. }
  551. //
  552. // Free memory first
  553. //
  554. ZwFreeVirtualMemory(
  555. CrntProcess,
  556. &currentEfsStream,
  557. &regionSize,
  558. MEM_RELEASE
  559. );
  560. //
  561. // Prepare input data buffer
  562. //
  563. inputDataLength = EFS_FSCTL_HEADER_LENGTH + 2 * EFS_KEY_SIZE( fek );
  564. actionType = SET_EFS_KEYBLOB;
  565. if ( efsStream && !(EfsContext->Flags & SYSTEM_IS_READONLY)){
  566. //
  567. // $EFS updated
  568. //
  569. inputDataLength += *(ULONG *)efsStream;
  570. actionType |= WRITE_EFS_ATTRIBUTE;
  571. }
  572. currentEfsStream = ExAllocatePoolWithTag(
  573. PagedPool,
  574. inputDataLength,
  575. 'msfE'
  576. );
  577. //
  578. // Deal with out of memory here
  579. //
  580. if ( NULL == currentEfsStream ){
  581. //
  582. // Out of memory
  583. //
  584. status = STATUS_INSUFFICIENT_RESOURCES;
  585. break;
  586. }
  587. pUlong = (ULONG *) currentEfsStream;
  588. *pUlong = ((PFSCTL_INPUT)currentEfsStream)->CipherSubCode
  589. = actionType;
  590. ((PFSCTL_INPUT)currentEfsStream)->EfsFsCode = EFS_SET_ATTRIBUTE;
  591. RtlCopyMemory(
  592. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH,
  593. fek,
  594. EFS_KEY_SIZE( fek )
  595. );
  596. RtlCopyMemory(
  597. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  598. + EFS_KEY_SIZE( fek ),
  599. fek,
  600. EFS_KEY_SIZE( fek )
  601. );
  602. if ( efsStream && !(EfsContext->Flags & SYSTEM_IS_READONLY)){
  603. RtlCopyMemory(
  604. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  605. + 2 * EFS_KEY_SIZE( fek ),
  606. efsStream,
  607. *(ULONG *)efsStream
  608. );
  609. }
  610. //
  611. // Encrypt our Input data
  612. //
  613. EfsEncryptKeyFsData(
  614. currentEfsStream,
  615. inputDataLength,
  616. sizeof(ULONG),
  617. EFS_FSCTL_HEADER_LENGTH + EFS_KEY_SIZE( fek ),
  618. EFS_KEY_SIZE( fek )
  619. );
  620. //
  621. // Let's clear the plain FEK
  622. //
  623. RtlSecureZeroMemory(EFS_KEY_DATA(fek), fek->KeyLength);
  624. break;
  625. case NEW_FILE_EFS_REQUIRED:
  626. EfsId = ExAllocatePoolWithTag(
  627. PagedPool,
  628. sizeof (GUID),
  629. 'msfE'
  630. );
  631. if ( EfsId ){
  632. RtlCopyMemory(
  633. EfsId,
  634. &(efsStream->EfsId),
  635. sizeof( GUID ) );
  636. }
  637. //
  638. // Free memory first
  639. //
  640. if ( currentEfsStream ){
  641. ZwFreeVirtualMemory(
  642. CrntProcess,
  643. &currentEfsStream,
  644. &regionSize,
  645. MEM_RELEASE
  646. );
  647. }
  648. //
  649. // Prepare input data buffer
  650. //
  651. inputDataLength = EFS_FSCTL_HEADER_LENGTH
  652. + 2 * EFS_KEY_SIZE( fek )
  653. + *(ULONG *)efsStream;
  654. currentEfsStream = ExAllocatePoolWithTag(
  655. PagedPool,
  656. inputDataLength,
  657. 'msfE'
  658. );
  659. //
  660. // Deal with out of memory here
  661. //
  662. if ( NULL == currentEfsStream ){
  663. status = STATUS_INSUFFICIENT_RESOURCES;
  664. break;
  665. }
  666. pUlong = (ULONG *) currentEfsStream;
  667. *pUlong = ((PFSCTL_INPUT)currentEfsStream)->CipherSubCode
  668. = WRITE_EFS_ATTRIBUTE | SET_EFS_KEYBLOB;
  669. ((PFSCTL_INPUT)currentEfsStream)->EfsFsCode = EFS_SET_ATTRIBUTE;
  670. RtlCopyMemory(
  671. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH,
  672. fek,
  673. EFS_KEY_SIZE( fek )
  674. );
  675. RtlCopyMemory(
  676. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  677. + EFS_KEY_SIZE( fek ),
  678. fek,
  679. EFS_KEY_SIZE( fek )
  680. );
  681. RtlCopyMemory(
  682. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  683. + 2 * EFS_KEY_SIZE( fek ) ,
  684. efsStream,
  685. *(ULONG *)efsStream
  686. );
  687. //
  688. // Encrypt our Input data
  689. //
  690. EfsEncryptKeyFsData(
  691. currentEfsStream,
  692. inputDataLength,
  693. sizeof(ULONG),
  694. EFS_FSCTL_HEADER_LENGTH + EFS_KEY_SIZE( fek ),
  695. EFS_KEY_SIZE( fek )
  696. );
  697. //
  698. // Let's clear the plain FEK
  699. //
  700. RtlSecureZeroMemory(EFS_KEY_DATA(fek), fek->KeyLength);
  701. break;
  702. case NEW_DIR_EFS_REQUIRED:
  703. //
  704. // Prepare input data buffer
  705. //
  706. inputDataLength = EFS_FSCTL_HEADER_LENGTH
  707. + 2 * ( sizeof( EFS_KEY ) + DES_KEYSIZE );
  708. if ( NULL == efsStream ){
  709. //
  710. // New directory will inherit the parent $EFS
  711. //
  712. usingCurrentEfs = TRUE;
  713. inputDataLength += currentEfsStreamLength;
  714. efsStream = currentEfsStream;
  715. } else {
  716. //
  717. // New $EFS generated. Not in ver 1.0
  718. //
  719. usingCurrentEfs = FALSE;
  720. inputDataLength += *(ULONG *)efsStream;
  721. //
  722. // Free memory first
  723. //
  724. if (currentEfsStream){
  725. ZwFreeVirtualMemory(
  726. CrntProcess,
  727. &currentEfsStream,
  728. &regionSize,
  729. MEM_RELEASE
  730. );
  731. }
  732. }
  733. currentEfsStream = ExAllocatePoolWithTag(
  734. PagedPool,
  735. inputDataLength,
  736. 'msfE'
  737. );
  738. //
  739. // Deal with out of memory here
  740. //
  741. if ( NULL == currentEfsStream ){
  742. status = STATUS_INSUFFICIENT_RESOURCES;
  743. break;
  744. }
  745. pUlong = (ULONG *) currentEfsStream;
  746. *pUlong = ((PFSCTL_INPUT)currentEfsStream)->CipherSubCode
  747. = WRITE_EFS_ATTRIBUTE;
  748. ((PFSCTL_INPUT)currentEfsStream)->EfsFsCode = EFS_SET_ATTRIBUTE;
  749. //
  750. // Make up an false FEK with session key
  751. //
  752. ((PEFS_KEY)&(((PFSCTL_INPUT)currentEfsStream)->EfsFsData[0]))->KeyLength
  753. = DES_KEYSIZE;
  754. ((PEFS_KEY)&(((PFSCTL_INPUT)currentEfsStream)->EfsFsData[0]))->Algorithm
  755. = CALG_DES;
  756. RtlCopyMemory(
  757. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH + sizeof ( EFS_KEY ),
  758. &(EfsData.SessionKey),
  759. DES_KEYSIZE
  760. );
  761. RtlCopyMemory(
  762. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  763. + DES_KEYSIZE + sizeof ( EFS_KEY ) ,
  764. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH,
  765. DES_KEYSIZE + sizeof ( EFS_KEY )
  766. );
  767. RtlCopyMemory(
  768. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  769. + 2 * ( sizeof ( EFS_KEY ) + DES_KEYSIZE) ,
  770. efsStream,
  771. *(ULONG *)efsStream
  772. );
  773. if ( usingCurrentEfs && efsStream ) {
  774. //
  775. // Free memory
  776. //
  777. ZwFreeVirtualMemory(
  778. CrntProcess,
  779. &efsStream,
  780. &regionSize,
  781. MEM_RELEASE
  782. );
  783. }
  784. //
  785. // Encrypt our Input data
  786. //
  787. EfsEncryptKeyFsData(
  788. currentEfsStream,
  789. inputDataLength,
  790. sizeof(ULONG),
  791. EFS_FSCTL_HEADER_LENGTH + DES_KEYSIZE + sizeof ( EFS_KEY ),
  792. DES_KEYSIZE + sizeof ( EFS_KEY )
  793. );
  794. break;
  795. case TURN_ON_BIT_ONLY:
  796. //
  797. // Prepare input data buffer
  798. //
  799. inputDataLength = EFS_FSCTL_HEADER_LENGTH
  800. + 2 * ( sizeof( EFS_KEY ) + DES_KEYSIZE );
  801. currentEfsStream = ExAllocatePoolWithTag(
  802. PagedPool,
  803. inputDataLength,
  804. 'msfE'
  805. );
  806. //
  807. // Deal with out of memory here
  808. //
  809. if ( NULL == currentEfsStream ){
  810. status = STATUS_INSUFFICIENT_RESOURCES;
  811. break;
  812. }
  813. ((PFSCTL_INPUT)currentEfsStream)->CipherSubCode = 0;
  814. ((PFSCTL_INPUT)currentEfsStream)->EfsFsCode = EFS_SET_ATTRIBUTE;
  815. //
  816. // Make up an false FEK with session key
  817. //
  818. ((PEFS_KEY)&(((PFSCTL_INPUT)currentEfsStream)->EfsFsData[0]))->KeyLength
  819. = DES_KEYSIZE;
  820. ((PEFS_KEY)&(((PFSCTL_INPUT)currentEfsStream)->EfsFsData[0]))->Algorithm
  821. = CALG_DES;
  822. RtlCopyMemory(
  823. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH + sizeof ( EFS_KEY ),
  824. &(EfsData.SessionKey),
  825. DES_KEYSIZE
  826. );
  827. RtlCopyMemory(
  828. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  829. + DES_KEYSIZE + sizeof ( EFS_KEY ) ,
  830. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH,
  831. DES_KEYSIZE + sizeof ( EFS_KEY )
  832. );
  833. //
  834. // Encrypt our Input data
  835. //
  836. EfsEncryptKeyFsData(
  837. currentEfsStream,
  838. inputDataLength,
  839. sizeof(ULONG),
  840. EFS_FSCTL_HEADER_LENGTH + DES_KEYSIZE + sizeof ( EFS_KEY ),
  841. DES_KEYSIZE + sizeof ( EFS_KEY )
  842. );
  843. default:
  844. break;
  845. }
  846. //
  847. // Free the memory from the EFS server
  848. //
  849. if (bufferBase){
  850. SIZE_T bufferSize;
  851. bufferSize = bufferLength;
  852. ZwFreeVirtualMemory(
  853. CrntProcess,
  854. &bufferBase,
  855. &bufferSize,
  856. MEM_RELEASE
  857. );
  858. }
  859. if (ProcessAttached){
  860. KeUnstackDetachProcess(&ApcState);
  861. ObDereferenceObject(EfsData.LsaProcess);
  862. ProcessAttached = FALSE;
  863. }
  864. if ( NT_SUCCESS(status) ){
  865. //
  866. // Prepare a FSCTL IRP
  867. //
  868. KeInitializeEvent( &event, SynchronizationEvent, FALSE);
  869. if ( EfsContext->Status & TURN_ON_ENCRYPTION_BIT ) {
  870. FsCode = FSCTL_SET_ENCRYPTION;
  871. *(ULONG *) currentEfsStream = EFS_ENCRYPT_STREAM;
  872. } else {
  873. FsCode = FSCTL_ENCRYPTION_FSCTL_IO;
  874. }
  875. fsCtlIrp = IoBuildDeviceIoControlRequest( FsCode,
  876. DeviceObject,
  877. currentEfsStream,
  878. inputDataLength,
  879. NULL,
  880. 0,
  881. FALSE,
  882. &event,
  883. &ioStatus
  884. );
  885. if ( fsCtlIrp ) {
  886. fsCtlIrpSp = IoGetNextIrpStackLocation( fsCtlIrp );
  887. fsCtlIrpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
  888. fsCtlIrpSp->MinorFunction = IRP_MN_USER_FS_REQUEST;
  889. fsCtlIrpSp->FileObject = irpSp->FileObject;
  890. status = IoCallDriver( DeviceObject, fsCtlIrp);
  891. if (status == STATUS_PENDING) {
  892. status = KeWaitForSingleObject( &event,
  893. Executive,
  894. KernelMode,
  895. FALSE,
  896. (PLARGE_INTEGER) NULL );
  897. status = ioStatus.Status;
  898. }
  899. if ( !NT_SUCCESS(status) ){
  900. //
  901. // Write EFS and set Key Blob failed. Failed the create
  902. //
  903. status = STATUS_ACCESS_DENIED;
  904. } else {
  905. //
  906. // Refresh the cache
  907. //
  908. if ( EfsId ){
  909. if ( !accessToken ){
  910. if ( irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.ClientToken ){
  911. accessToken = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.ClientToken;
  912. } else {
  913. accessToken = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.PrimaryToken;
  914. }
  915. if ( accessToken ){
  916. //
  917. // Get User ID
  918. //
  919. status = SeQueryInformationToken(
  920. accessToken,
  921. TokenUser,
  922. &UserId
  923. );
  924. }
  925. }
  926. if (UserId && NT_SUCCESS(status)){
  927. status = EfsRefreshCache(
  928. EfsId,
  929. UserId
  930. );
  931. if (NT_SUCCESS(status)){
  932. //
  933. // Cache set successfully.
  934. // UserId should not be deleted in this routine.
  935. //
  936. UserId = NULL;
  937. }
  938. }
  939. //
  940. // Cache should not affect the normal operations
  941. //
  942. status = STATUS_SUCCESS;
  943. }
  944. }
  945. } else {
  946. //
  947. // Failed allocate IRP
  948. //
  949. status = STATUS_INSUFFICIENT_RESOURCES;
  950. }
  951. ExFreePool( currentEfsStream );
  952. } else {
  953. //
  954. // Failed allocating memory for currentEfsStream
  955. // Use the status returned.
  956. //
  957. }
  958. } else {
  959. //
  960. // Failed on calling EFS server.
  961. // Because of the down level support, we cannot return the new error status code.
  962. //
  963. status = STATUS_ACCESS_DENIED;
  964. ZwFreeVirtualMemory(
  965. CrntProcess,
  966. &currentEfsStream,
  967. &regionSize,
  968. MEM_RELEASE
  969. );
  970. if (ProcessAttached){
  971. KeUnstackDetachProcess(&ApcState);
  972. ObDereferenceObject(EfsData.LsaProcess);
  973. ProcessAttached = FALSE;
  974. }
  975. }
  976. } else {
  977. //
  978. // Allocate virtual memory failed. Use the status returned.
  979. //
  980. if (ProcessAttached){
  981. KeUnstackDetachProcess(&ApcState);
  982. ObDereferenceObject(EfsData.LsaProcess);
  983. ProcessAttached = FALSE;
  984. }
  985. }
  986. if ( UserId ){
  987. ExFreePool( UserId );
  988. }
  989. if ( EfsId ){
  990. ExFreePool( EfsId );
  991. }
  992. return status;
  993. }