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.

1257 lines
38 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. PsImpersonateClient(
  354. PsGetCurrentThread(),
  355. accessToken,
  356. TRUE,
  357. TRUE,
  358. ImpersonationLevel
  359. );
  360. //
  361. // Call service to verify the user
  362. //
  363. status = EfsDecryptFek(
  364. &fek,
  365. (PEFS_DATA_STREAM_HEADER) currentEfsStream,
  366. currentEfsStreamLength,
  367. OpenType,
  368. &efsStream,
  369. &bufferBase,
  370. &bufferLength
  371. );
  372. if ( OldClientToken ) {
  373. PsImpersonateClient(
  374. PsGetCurrentThread(),
  375. OldClientToken,
  376. OldCopyOnOpen,
  377. OldEffectiveOnly,
  378. OldImpersonationLevel
  379. );
  380. PsDereferenceImpersonationToken(OldClientToken);
  381. } else {
  382. PsRevertToSelf( );
  383. }
  384. break;
  385. case NEW_FILE_EFS_REQUIRED:
  386. //
  387. // Call service to get new FEK, $EFS
  388. //
  389. if (EfsContext->Flags & SYSTEM_IS_READONLY) {
  390. ASSERT(FALSE);
  391. status = STATUS_MEDIA_WRITE_PROTECTED;
  392. if ( OldClientToken ) {
  393. PsDereferenceImpersonationToken(OldClientToken);
  394. }
  395. break;
  396. }
  397. PsImpersonateClient(
  398. PsGetCurrentThread(),
  399. accessToken,
  400. TRUE,
  401. TRUE,
  402. ImpersonationLevel
  403. );
  404. status = EfsGenerateKey(
  405. &fek,
  406. &efsStream,
  407. (PEFS_DATA_STREAM_HEADER) currentEfsStream,
  408. currentEfsStreamLength,
  409. &bufferBase,
  410. &bufferLength
  411. );
  412. if ( OldClientToken ) {
  413. PsImpersonateClient(
  414. PsGetCurrentThread(),
  415. OldClientToken,
  416. OldCopyOnOpen,
  417. OldEffectiveOnly,
  418. OldImpersonationLevel
  419. );
  420. PsDereferenceImpersonationToken(OldClientToken);
  421. } else {
  422. PsRevertToSelf( );
  423. }
  424. break;
  425. case NEW_DIR_EFS_REQUIRED:
  426. //
  427. // Call service to get new $EFS
  428. //
  429. if (EfsContext->Flags & SYSTEM_IS_READONLY) {
  430. ASSERT(FALSE);
  431. status = STATUS_MEDIA_WRITE_PROTECTED;
  432. if ( OldClientToken ) {
  433. PsDereferenceImpersonationToken(OldClientToken);
  434. }
  435. break;
  436. }
  437. PsImpersonateClient(
  438. PsGetCurrentThread(),
  439. accessToken,
  440. TRUE,
  441. TRUE,
  442. ImpersonationLevel
  443. );
  444. status = GenerateDirEfs(
  445. (PEFS_DATA_STREAM_HEADER) currentEfsStream,
  446. currentEfsStreamLength,
  447. &efsStream,
  448. &bufferBase,
  449. &bufferLength
  450. );
  451. if ( OldClientToken ) {
  452. PsImpersonateClient(
  453. PsGetCurrentThread(),
  454. OldClientToken,
  455. OldCopyOnOpen,
  456. OldEffectiveOnly,
  457. OldImpersonationLevel
  458. );
  459. PsDereferenceImpersonationToken(OldClientToken);
  460. } else {
  461. PsRevertToSelf( );
  462. }
  463. break;
  464. case TURN_ON_BIT_ONLY:
  465. //
  466. // Fall through intended
  467. //
  468. default:
  469. if ( OldClientToken ) {
  470. PsDereferenceImpersonationToken(OldClientToken);
  471. }
  472. break;
  473. }
  474. if ( ProcessNeedAttach ){
  475. KeStackAttachProcess (
  476. EfsData.LsaProcess,
  477. &ApcState
  478. );
  479. ProcessAttached = TRUE;
  480. }
  481. if (fek && (fek->Algorithm == CALG_3DES) && !EfsData.FipsFunctionTable.Fips3Des3Key ) {
  482. //
  483. // User requested 3des but fips is not available, quit.
  484. //
  485. if (bufferBase){
  486. SIZE_T bufferSize;
  487. bufferSize = bufferLength;
  488. ZwFreeVirtualMemory(
  489. CrntProcess,
  490. &bufferBase,
  491. &bufferSize,
  492. MEM_RELEASE
  493. );
  494. }
  495. status = STATUS_ACCESS_DENIED;
  496. }
  497. if ( NT_SUCCESS(status) ){
  498. KEVENT event;
  499. IO_STATUS_BLOCK ioStatus;
  500. PIRP fsCtlIrp;
  501. PIO_STACK_LOCATION fsCtlIrpSp;
  502. ULONG inputDataLength;
  503. ULONG actionType;
  504. ULONG usingCurrentEfs;
  505. ULONG FsCode;
  506. PULONG pUlong;
  507. //
  508. // We got our FEK, $EFS. Set it with a FSCTL
  509. // Prepare the input data buffer first
  510. //
  511. switch ( EfsContext->Status & ACTION_REQUIRED ){
  512. case VERIFY_USER_REQUIRED:
  513. EfsId = ExAllocatePoolWithTag(
  514. PagedPool,
  515. sizeof (GUID),
  516. 'msfE'
  517. );
  518. if ( EfsId ){
  519. RtlCopyMemory(
  520. EfsId,
  521. &(((PEFS_DATA_STREAM_HEADER) currentEfsStream)->EfsId),
  522. sizeof( GUID ) );
  523. }
  524. //
  525. // Free memory first
  526. //
  527. ZwFreeVirtualMemory(
  528. CrntProcess,
  529. &currentEfsStream,
  530. &regionSize,
  531. MEM_RELEASE
  532. );
  533. //
  534. // Prepare input data buffer
  535. //
  536. inputDataLength = EFS_FSCTL_HEADER_LENGTH + 2 * EFS_KEY_SIZE( fek );
  537. actionType = SET_EFS_KEYBLOB;
  538. if ( efsStream && !(EfsContext->Flags & SYSTEM_IS_READONLY)){
  539. //
  540. // $EFS updated
  541. //
  542. inputDataLength += *(ULONG *)efsStream;
  543. actionType |= WRITE_EFS_ATTRIBUTE;
  544. }
  545. currentEfsStream = ExAllocatePoolWithTag(
  546. PagedPool,
  547. inputDataLength,
  548. 'msfE'
  549. );
  550. //
  551. // Deal with out of memory here
  552. //
  553. if ( NULL == currentEfsStream ){
  554. //
  555. // Out of memory
  556. //
  557. status = STATUS_INSUFFICIENT_RESOURCES;
  558. break;
  559. }
  560. pUlong = (ULONG *) currentEfsStream;
  561. *pUlong = ((PFSCTL_INPUT)currentEfsStream)->CipherSubCode
  562. = actionType;
  563. ((PFSCTL_INPUT)currentEfsStream)->EfsFsCode = EFS_SET_ATTRIBUTE;
  564. RtlCopyMemory(
  565. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH,
  566. fek,
  567. EFS_KEY_SIZE( fek )
  568. );
  569. RtlCopyMemory(
  570. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  571. + EFS_KEY_SIZE( fek ),
  572. fek,
  573. EFS_KEY_SIZE( fek )
  574. );
  575. if ( efsStream && !(EfsContext->Flags & SYSTEM_IS_READONLY)){
  576. RtlCopyMemory(
  577. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  578. + 2 * EFS_KEY_SIZE( fek ),
  579. efsStream,
  580. *(ULONG *)efsStream
  581. );
  582. }
  583. //
  584. // Encrypt our Input data
  585. //
  586. EfsEncryptKeyFsData(
  587. currentEfsStream,
  588. inputDataLength,
  589. sizeof(ULONG),
  590. EFS_FSCTL_HEADER_LENGTH + EFS_KEY_SIZE( fek ),
  591. EFS_KEY_SIZE( fek )
  592. );
  593. break;
  594. case NEW_FILE_EFS_REQUIRED:
  595. EfsId = ExAllocatePoolWithTag(
  596. PagedPool,
  597. sizeof (GUID),
  598. 'msfE'
  599. );
  600. if ( EfsId ){
  601. RtlCopyMemory(
  602. EfsId,
  603. &(efsStream->EfsId),
  604. sizeof( GUID ) );
  605. }
  606. //
  607. // Free memory first
  608. //
  609. if ( currentEfsStream ){
  610. ZwFreeVirtualMemory(
  611. CrntProcess,
  612. &currentEfsStream,
  613. &regionSize,
  614. MEM_RELEASE
  615. );
  616. }
  617. //
  618. // Prepare input data buffer
  619. //
  620. inputDataLength = EFS_FSCTL_HEADER_LENGTH
  621. + 2 * EFS_KEY_SIZE( fek )
  622. + *(ULONG *)efsStream;
  623. currentEfsStream = ExAllocatePoolWithTag(
  624. PagedPool,
  625. inputDataLength,
  626. 'msfE'
  627. );
  628. //
  629. // Deal with out of memory here
  630. //
  631. if ( NULL == currentEfsStream ){
  632. status = STATUS_INSUFFICIENT_RESOURCES;
  633. break;
  634. }
  635. pUlong = (ULONG *) currentEfsStream;
  636. *pUlong = ((PFSCTL_INPUT)currentEfsStream)->CipherSubCode
  637. = WRITE_EFS_ATTRIBUTE | SET_EFS_KEYBLOB;
  638. ((PFSCTL_INPUT)currentEfsStream)->EfsFsCode = EFS_SET_ATTRIBUTE;
  639. RtlCopyMemory(
  640. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH,
  641. fek,
  642. EFS_KEY_SIZE( fek )
  643. );
  644. RtlCopyMemory(
  645. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  646. + EFS_KEY_SIZE( fek ),
  647. fek,
  648. EFS_KEY_SIZE( fek )
  649. );
  650. RtlCopyMemory(
  651. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  652. + 2 * EFS_KEY_SIZE( fek ) ,
  653. efsStream,
  654. *(ULONG *)efsStream
  655. );
  656. //
  657. // Encrypt our Input data
  658. //
  659. EfsEncryptKeyFsData(
  660. currentEfsStream,
  661. inputDataLength,
  662. sizeof(ULONG),
  663. EFS_FSCTL_HEADER_LENGTH + EFS_KEY_SIZE( fek ),
  664. EFS_KEY_SIZE( fek )
  665. );
  666. break;
  667. case NEW_DIR_EFS_REQUIRED:
  668. //
  669. // Prepare input data buffer
  670. //
  671. inputDataLength = EFS_FSCTL_HEADER_LENGTH
  672. + 2 * ( sizeof( EFS_KEY ) + DES_KEYSIZE );
  673. if ( NULL == efsStream ){
  674. //
  675. // New directory will inherit the parent $EFS
  676. //
  677. usingCurrentEfs = TRUE;
  678. inputDataLength += currentEfsStreamLength;
  679. efsStream = currentEfsStream;
  680. } else {
  681. //
  682. // New $EFS generated. Not in ver 1.0
  683. //
  684. usingCurrentEfs = FALSE;
  685. inputDataLength += *(ULONG *)efsStream;
  686. //
  687. // Free memory first
  688. //
  689. if (currentEfsStream){
  690. ZwFreeVirtualMemory(
  691. CrntProcess,
  692. &currentEfsStream,
  693. &regionSize,
  694. MEM_RELEASE
  695. );
  696. }
  697. }
  698. currentEfsStream = ExAllocatePoolWithTag(
  699. PagedPool,
  700. inputDataLength,
  701. 'msfE'
  702. );
  703. //
  704. // Deal with out of memory here
  705. //
  706. if ( NULL == currentEfsStream ){
  707. status = STATUS_INSUFFICIENT_RESOURCES;
  708. break;
  709. }
  710. pUlong = (ULONG *) currentEfsStream;
  711. *pUlong = ((PFSCTL_INPUT)currentEfsStream)->CipherSubCode
  712. = WRITE_EFS_ATTRIBUTE;
  713. ((PFSCTL_INPUT)currentEfsStream)->EfsFsCode = EFS_SET_ATTRIBUTE;
  714. //
  715. // Make up an false FEK with session key
  716. //
  717. ((PEFS_KEY)&(((PFSCTL_INPUT)currentEfsStream)->EfsFsData[0]))->KeyLength
  718. = DES_KEYSIZE;
  719. ((PEFS_KEY)&(((PFSCTL_INPUT)currentEfsStream)->EfsFsData[0]))->Algorithm
  720. = CALG_DES;
  721. RtlCopyMemory(
  722. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH + sizeof ( EFS_KEY ),
  723. &(EfsData.SessionKey),
  724. DES_KEYSIZE
  725. );
  726. RtlCopyMemory(
  727. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  728. + DES_KEYSIZE + sizeof ( EFS_KEY ) ,
  729. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH,
  730. DES_KEYSIZE + sizeof ( EFS_KEY )
  731. );
  732. RtlCopyMemory(
  733. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  734. + 2 * ( sizeof ( EFS_KEY ) + DES_KEYSIZE) ,
  735. efsStream,
  736. *(ULONG *)efsStream
  737. );
  738. if ( usingCurrentEfs && efsStream ) {
  739. //
  740. // Free memory
  741. //
  742. ZwFreeVirtualMemory(
  743. CrntProcess,
  744. &efsStream,
  745. &regionSize,
  746. MEM_RELEASE
  747. );
  748. }
  749. //
  750. // Encrypt our Input data
  751. //
  752. EfsEncryptKeyFsData(
  753. currentEfsStream,
  754. inputDataLength,
  755. sizeof(ULONG),
  756. EFS_FSCTL_HEADER_LENGTH + DES_KEYSIZE + sizeof ( EFS_KEY ),
  757. DES_KEYSIZE + sizeof ( EFS_KEY )
  758. );
  759. break;
  760. case TURN_ON_BIT_ONLY:
  761. //
  762. // Prepare input data buffer
  763. //
  764. inputDataLength = EFS_FSCTL_HEADER_LENGTH
  765. + 2 * ( sizeof( EFS_KEY ) + DES_KEYSIZE );
  766. currentEfsStream = ExAllocatePoolWithTag(
  767. PagedPool,
  768. inputDataLength,
  769. 'msfE'
  770. );
  771. //
  772. // Deal with out of memory here
  773. //
  774. if ( NULL == currentEfsStream ){
  775. status = STATUS_INSUFFICIENT_RESOURCES;
  776. break;
  777. }
  778. ((PFSCTL_INPUT)currentEfsStream)->CipherSubCode = 0;
  779. ((PFSCTL_INPUT)currentEfsStream)->EfsFsCode = EFS_SET_ATTRIBUTE;
  780. //
  781. // Make up an false FEK with session key
  782. //
  783. ((PEFS_KEY)&(((PFSCTL_INPUT)currentEfsStream)->EfsFsData[0]))->KeyLength
  784. = DES_KEYSIZE;
  785. ((PEFS_KEY)&(((PFSCTL_INPUT)currentEfsStream)->EfsFsData[0]))->Algorithm
  786. = CALG_DES;
  787. RtlCopyMemory(
  788. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH + sizeof ( EFS_KEY ),
  789. &(EfsData.SessionKey),
  790. DES_KEYSIZE
  791. );
  792. RtlCopyMemory(
  793. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH
  794. + DES_KEYSIZE + sizeof ( EFS_KEY ) ,
  795. ((PUCHAR) currentEfsStream) + EFS_FSCTL_HEADER_LENGTH,
  796. DES_KEYSIZE + sizeof ( EFS_KEY )
  797. );
  798. //
  799. // Encrypt our Input data
  800. //
  801. EfsEncryptKeyFsData(
  802. currentEfsStream,
  803. inputDataLength,
  804. sizeof(ULONG),
  805. EFS_FSCTL_HEADER_LENGTH + DES_KEYSIZE + sizeof ( EFS_KEY ),
  806. DES_KEYSIZE + sizeof ( EFS_KEY )
  807. );
  808. default:
  809. break;
  810. }
  811. //
  812. // Free the memory from the EFS server
  813. //
  814. if (bufferBase){
  815. SIZE_T bufferSize;
  816. bufferSize = bufferLength;
  817. ZwFreeVirtualMemory(
  818. CrntProcess,
  819. &bufferBase,
  820. &bufferSize,
  821. MEM_RELEASE
  822. );
  823. }
  824. if (ProcessAttached){
  825. KeUnstackDetachProcess(&ApcState);
  826. ObDereferenceObject(EfsData.LsaProcess);
  827. ProcessAttached = FALSE;
  828. }
  829. if ( NT_SUCCESS(status) ){
  830. //
  831. // Prepare a FSCTL IRP
  832. //
  833. KeInitializeEvent( &event, SynchronizationEvent, FALSE);
  834. if ( EfsContext->Status & TURN_ON_ENCRYPTION_BIT ) {
  835. FsCode = FSCTL_SET_ENCRYPTION;
  836. *(ULONG *) currentEfsStream = EFS_ENCRYPT_STREAM;
  837. } else {
  838. FsCode = FSCTL_ENCRYPTION_FSCTL_IO;
  839. }
  840. fsCtlIrp = IoBuildDeviceIoControlRequest( FsCode,
  841. DeviceObject,
  842. currentEfsStream,
  843. inputDataLength,
  844. NULL,
  845. 0,
  846. FALSE,
  847. &event,
  848. &ioStatus
  849. );
  850. if ( fsCtlIrp ) {
  851. fsCtlIrpSp = IoGetNextIrpStackLocation( fsCtlIrp );
  852. fsCtlIrpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
  853. fsCtlIrpSp->MinorFunction = IRP_MN_USER_FS_REQUEST;
  854. fsCtlIrpSp->FileObject = irpSp->FileObject;
  855. status = IoCallDriver( DeviceObject, fsCtlIrp);
  856. if (status == STATUS_PENDING) {
  857. status = KeWaitForSingleObject( &event,
  858. Executive,
  859. KernelMode,
  860. FALSE,
  861. (PLARGE_INTEGER) NULL );
  862. status = ioStatus.Status;
  863. }
  864. if ( !NT_SUCCESS(status) ){
  865. //
  866. // Write EFS and set Key Blob failed. Failed the create
  867. //
  868. status = STATUS_ACCESS_DENIED;
  869. } else {
  870. //
  871. // Refresh the cache
  872. //
  873. if ( EfsId ){
  874. if ( !accessToken ){
  875. if ( irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.ClientToken ){
  876. accessToken = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.ClientToken;
  877. } else {
  878. accessToken = irpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext.PrimaryToken;
  879. }
  880. if ( accessToken ){
  881. //
  882. // Get User ID
  883. //
  884. status = SeQueryInformationToken(
  885. accessToken,
  886. TokenUser,
  887. &UserId
  888. );
  889. }
  890. }
  891. if (UserId && NT_SUCCESS(status)){
  892. status = EfsRefreshCache(
  893. EfsId,
  894. UserId
  895. );
  896. if (NT_SUCCESS(status)){
  897. //
  898. // Cache set successfully.
  899. // UserId should not be deleted in this routine.
  900. //
  901. UserId = NULL;
  902. }
  903. }
  904. //
  905. // Cache should not affect the normal operations
  906. //
  907. status = STATUS_SUCCESS;
  908. }
  909. }
  910. } else {
  911. //
  912. // Failed allocate IRP
  913. //
  914. status = STATUS_INSUFFICIENT_RESOURCES;
  915. }
  916. ExFreePool( currentEfsStream );
  917. } else {
  918. //
  919. // Failed allocating memory for currentEfsStream
  920. // Use the status returned.
  921. //
  922. }
  923. } else {
  924. //
  925. // Failed on calling EFS server.
  926. // Because of the down level support, we cannot return the new error status code.
  927. //
  928. status = STATUS_ACCESS_DENIED;
  929. ZwFreeVirtualMemory(
  930. CrntProcess,
  931. &currentEfsStream,
  932. &regionSize,
  933. MEM_RELEASE
  934. );
  935. if (ProcessAttached){
  936. KeUnstackDetachProcess(&ApcState);
  937. ObDereferenceObject(EfsData.LsaProcess);
  938. ProcessAttached = FALSE;
  939. }
  940. }
  941. } else {
  942. //
  943. // Allocate virtual memory failed. Use the status returned.
  944. //
  945. if (ProcessAttached){
  946. KeUnstackDetachProcess(&ApcState);
  947. ObDereferenceObject(EfsData.LsaProcess);
  948. ProcessAttached = FALSE;
  949. }
  950. }
  951. if ( UserId ){
  952. ExFreePool( UserId );
  953. }
  954. if ( EfsId ){
  955. ExFreePool( EfsId );
  956. }
  957. return status;
  958. }