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.

2071 lines
52 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. feclient.cpp
  5. Abstract:
  6. This module implements stubs to call EFS Api
  7. Author:
  8. Robert Reichel (RobertRe)
  9. Robert Gu (RobertG)
  10. Revision History:
  11. --*/
  12. //
  13. // Turn off lean and mean so we get wincrypt.h and winefs.h included
  14. //
  15. #undef WIN32_LEAN_AND_MEAN
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <windows.h>
  20. #include <feclient.h>
  21. #include <efsstruc.h>
  22. #include <userenv.h>
  23. //
  24. // Constants used in export\import file
  25. //
  26. #define FILE_SIGNATURE L"ROBS"
  27. #define STREAM_SIGNATURE L"NTFS"
  28. #define DATA_SIGNATURE L"GURE"
  29. #define DEFAULT_STREAM L"::$DATA"
  30. #define DEF_STR_LEN 14
  31. #define PROPERTY_SET L":$PROPERTY_SET"
  32. #define INISECTIONNAME L"Encryption"
  33. #define INIKEYNAME L"Disable"
  34. #define INIFILENAME L"\\Desktop.ini"
  35. #define TRUSTEDPEOPLE L"TrustedPeople"
  36. #define PROPERTY_SET_LEN wcslen(PROPERTY_SET)
  37. #if DBG
  38. ULONG DebugLevel = 0;
  39. #endif
  40. LPSTR EfsOidlpstr = szOID_KP_EFS;
  41. //
  42. // External prototypes
  43. //
  44. extern "C" {
  45. DWORD
  46. EfsReadFileRawRPCClient(
  47. IN PFE_EXPORT_FUNC ExportCallback,
  48. IN PVOID CallbackContext,
  49. IN PVOID Context
  50. );
  51. DWORD
  52. EfsWriteFileRawRPCClient(
  53. IN PFE_IMPORT_FUNC ImportCallback,
  54. IN PVOID CallbackContext,
  55. IN PVOID Context
  56. );
  57. DWORD
  58. EfsAddUsersRPCClient(
  59. IN LPCWSTR lpFileName,
  60. IN PENCRYPTION_CERTIFICATE_LIST pEncryptionCertificates
  61. );
  62. DWORD
  63. EfsRemoveUsersRPCClient(
  64. IN LPCWSTR lpFileName,
  65. IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashes
  66. );
  67. DWORD
  68. EfsQueryRecoveryAgentsRPCClient(
  69. IN LPCWSTR lpFileName,
  70. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pRecoveryAgents
  71. );
  72. DWORD
  73. EfsQueryUsersRPCClient(
  74. IN LPCWSTR lpFileName,
  75. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pUsers
  76. );
  77. DWORD
  78. EfsSetEncryptionKeyRPCClient(
  79. IN PENCRYPTION_CERTIFICATE pEncryptionCertificate
  80. );
  81. DWORD
  82. EfsDuplicateEncryptionInfoRPCClient(
  83. IN LPCWSTR lpSrcFileName,
  84. IN LPCWSTR lpDestFileName,
  85. IN DWORD dwCreationDistribution,
  86. IN DWORD dwAttributes,
  87. IN PEFS_RPC_BLOB pRelativeSD,
  88. IN BOOL bInheritHandle
  89. );
  90. DWORD
  91. EfsFileKeyInfoRPCClient(
  92. IN LPCWSTR lpFileName,
  93. IN DWORD InfoClass,
  94. OUT PEFS_RPC_BLOB *KeyInfo
  95. );
  96. }
  97. //
  98. // Internal function prototypes
  99. //
  100. NTSTATUS
  101. GetStreamInformation(
  102. IN HANDLE SourceFile,
  103. OUT PFILE_STREAM_INFORMATION * StreamInfoBase,
  104. PULONG StreamInfoSize
  105. );
  106. DWORD
  107. OpenFileStreams(
  108. IN HANDLE hSourceFile,
  109. IN ULONG ShareMode,
  110. IN PFILE_STREAM_INFORMATION StreamInfoBase,
  111. IN ULONG FileAccess,
  112. IN ULONG CreateDisposition,
  113. IN ULONG CreateOption,
  114. OUT PUNICODE_STRING * StreamNames,
  115. OUT PHANDLE * StreamHandles,
  116. OUT PULONG StreamCount
  117. );
  118. VOID
  119. CleanupOpenFileStreams(
  120. IN PHANDLE Handles OPTIONAL,
  121. IN PUNICODE_STRING StreamNames OPTIONAL,
  122. IN PFILE_STREAM_INFORMATION StreamInfoBase OPTIONAL,
  123. IN HANDLE HSourceFile OPTIONAL,
  124. IN ULONG StreamCount
  125. );
  126. ULONG
  127. CheckSignature(
  128. IN void *Signature
  129. );
  130. //
  131. // Exported function prototypes
  132. //
  133. DWORD
  134. EfsClientEncryptFile(
  135. IN LPCWSTR FileName
  136. );
  137. DWORD
  138. EfsClientDecryptFile(
  139. IN LPCWSTR FileName,
  140. IN DWORD Recovery
  141. );
  142. BOOL
  143. EfsClientFileEncryptionStatus(
  144. IN LPCWSTR FileName,
  145. OUT LPDWORD lpStatus
  146. );
  147. DWORD
  148. EfsClientOpenFileRaw(
  149. IN LPCWSTR lpFileName,
  150. IN ULONG Flags,
  151. OUT PVOID * Context
  152. );
  153. DWORD
  154. EfsClientReadFileRaw(
  155. IN PFE_EXPORT_FUNC ExportCallback,
  156. IN PVOID CallbackContext,
  157. IN PVOID Context
  158. );
  159. DWORD
  160. EfsClientWriteFileRaw(
  161. IN PFE_IMPORT_FUNC ImportCallback,
  162. IN PVOID CallbackContext,
  163. IN PVOID Context
  164. );
  165. VOID
  166. EfsClientCloseFileRaw(
  167. IN PVOID Context
  168. );
  169. DWORD
  170. EfsClientAddUsers(
  171. IN LPCTSTR lpFileName,
  172. IN PENCRYPTION_CERTIFICATE_LIST pEncryptionCertificates
  173. );
  174. DWORD
  175. EfsClientRemoveUsers(
  176. IN LPCTSTR lpFileName,
  177. IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashes
  178. );
  179. DWORD
  180. EfsClientQueryRecoveryAgents(
  181. IN LPCTSTR lpFileName,
  182. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pRecoveryAgents
  183. );
  184. DWORD
  185. EfsClientQueryUsers(
  186. IN LPCTSTR lpFileName,
  187. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pUsers
  188. );
  189. DWORD
  190. EfsClientSetEncryptionKey(
  191. IN PENCRYPTION_CERTIFICATE pEncryptionCertificate
  192. );
  193. VOID
  194. EfsClientFreeHashList(
  195. IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashList
  196. );
  197. DWORD
  198. EfsClientDuplicateEncryptionInfo(
  199. IN LPCWSTR lpSrcFile,
  200. IN LPCWSTR lpDestFile,
  201. IN DWORD dwCreationDistribution,
  202. IN DWORD dwAttributes,
  203. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes
  204. );
  205. BOOL
  206. EfsClientEncryptionDisable(
  207. IN LPCWSTR DirPath,
  208. IN BOOL Disable
  209. );
  210. DWORD
  211. EfsClientFileKeyInfo(
  212. IN LPCWSTR lpFileName,
  213. IN DWORD InfoClass,
  214. OUT PEFS_RPC_BLOB *KeyInfo
  215. );
  216. VOID
  217. EfsClientFreeKeyInfo(
  218. IN PEFS_RPC_BLOB pKeyInfo
  219. );
  220. FE_CLIENT_DISPATCH_TABLE DispatchTable = { EfsClientEncryptFile,
  221. EfsClientDecryptFile,
  222. EfsClientFileEncryptionStatus,
  223. EfsClientOpenFileRaw,
  224. EfsClientReadFileRaw,
  225. EfsClientWriteFileRaw,
  226. EfsClientCloseFileRaw,
  227. EfsClientAddUsers,
  228. EfsClientRemoveUsers,
  229. EfsClientQueryRecoveryAgents,
  230. EfsClientQueryUsers,
  231. EfsClientSetEncryptionKey,
  232. EfsClientFreeHashList,
  233. EfsClientDuplicateEncryptionInfo,
  234. EfsClientEncryptionDisable,
  235. EfsClientFileKeyInfo,
  236. EfsClientFreeKeyInfo
  237. };
  238. FE_CLIENT_INFO ClientInfo = {
  239. FE_REVISION_1_0,
  240. &DispatchTable
  241. };
  242. //
  243. // Internal function prototypes
  244. //
  245. BOOL
  246. TranslateFileName(
  247. IN LPCWSTR FileName,
  248. OUT PUNICODE_STRING FullFileNameU
  249. );
  250. BOOL
  251. RemoteFile(
  252. IN LPCWSTR FileName
  253. );
  254. extern "C"
  255. BOOL
  256. EfsClientInit(
  257. IN PVOID hmod,
  258. IN ULONG Reason,
  259. IN PCONTEXT Context
  260. )
  261. {
  262. return( TRUE );
  263. }
  264. extern "C"
  265. BOOL
  266. FeClientInitialize(
  267. IN DWORD dwFeRevision,
  268. OUT LPFE_CLIENT_INFO *lpFeInfo
  269. )
  270. /*++
  271. Routine Description:
  272. description-of-function.
  273. Arguments:
  274. dwFeRevision - Is the revision of the current FEAPI interface.
  275. lpFeInfo - On successful return, must contain a pointer to a structure
  276. describing the FE Client Interface. Once returned, the FE Client
  277. must assume that the caller will continue to reference this table until
  278. an unload call has been made. Any changes to this information, or
  279. deallocation of the memory containing the information may result in
  280. system corruptions.
  281. Return Value:
  282. TRUE - Indicates the Client DLL successfully initialized.
  283. FALSE - Indicates the client DLL has not loaded. More information may be
  284. obtained by calling GetLastError().
  285. --*/
  286. {
  287. *lpFeInfo = &ClientInfo;
  288. return( TRUE );
  289. }
  290. BOOL
  291. TranslateFileName(
  292. IN LPCWSTR FileName,
  293. OUT PUNICODE_STRING FullFileNameU
  294. )
  295. /*++
  296. Routine Description:
  297. This routine takes the filename passed by the user and converts
  298. it to a fully qualified pathname in the passed Unicode string.
  299. Arguments:
  300. FileName - Supplies the user-supplied file name.
  301. FullFileNameU - Returns the fully qualified pathname of the passed file.
  302. The buffer in this string is allocated out of heap memory and
  303. must be freed by the caller.
  304. Return Value:
  305. TRUE on success, FALSE otherwise.
  306. --*/
  307. //
  308. // Note: need to free the buffer of the returned string
  309. //
  310. {
  311. UNICODE_STRING FileNameU;
  312. BOOLEAN TranslationStatus;
  313. LPWSTR SrcFileName = (LPWSTR)FileName;
  314. WCHAR Sep = L'\\';
  315. int SrcLen =wcslen(FileName);
  316. if (0 == SrcLen) {
  317. SetLastError(ERROR_INVALID_PARAMETER);
  318. return FALSE;
  319. }
  320. FullFileNameU->Buffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(), 0, MAX_PATH * sizeof( WCHAR ));
  321. if (!FullFileNameU->Buffer) {
  322. SetLastError(ERROR_OUTOFMEMORY);
  323. return FALSE;
  324. }
  325. FullFileNameU->MaximumLength = MAX_PATH * sizeof( WCHAR );
  326. FullFileNameU->Length = (USHORT)RtlGetFullPathName_U(
  327. SrcFileName,
  328. FullFileNameU->MaximumLength,
  329. FullFileNameU->Buffer,
  330. NULL
  331. );
  332. //
  333. // The return value is supposed to be the length of the filename, without counting
  334. // the trailing NULL character. MAX_PATH is supposed be long enough to contain
  335. // the length of the file name and the trailing NULL, so what we get back had
  336. // better be less than MAX_PATH wchars.
  337. //
  338. if ( FullFileNameU->Length >= FullFileNameU->MaximumLength ){
  339. RtlFreeHeap( RtlProcessHeap(), 0, FullFileNameU->Buffer );
  340. FullFileNameU->Buffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(), 0, FullFileNameU->Length + sizeof(WCHAR));
  341. if (FullFileNameU->Buffer == NULL) {
  342. return( FALSE );
  343. }
  344. FullFileNameU->MaximumLength = FullFileNameU->Length + sizeof(WCHAR);
  345. FullFileNameU->Length = (USHORT)RtlGetFullPathName_U(
  346. SrcFileName,
  347. FullFileNameU->MaximumLength,
  348. FullFileNameU->Buffer,
  349. NULL
  350. );
  351. }
  352. if (FullFileNameU->Length == 0) {
  353. //
  354. // We failed for some reason
  355. //
  356. RtlFreeHeap( RtlProcessHeap(), 0, FullFileNameU->Buffer );
  357. return( FALSE );
  358. }
  359. return( TRUE );
  360. /******************
  361. if (0 == SrcLen) {
  362. SetLastError(ERROR_INVALID_PARAMETER);
  363. return FALSE;
  364. }
  365. FullFileNameU->Buffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(), 0, MAX_PATH * sizeof( WCHAR ));
  366. if (FullFileNameU->Buffer == NULL) {
  367. SetLastError(ERROR_OUTOFMEMORY);
  368. return( FALSE );
  369. }
  370. if ((SrcLen >= 5) && (FileName[0] == Sep) && (FileName[1] == Sep) && (FileName[2] == L'?') && (FileName[3] == Sep)){
  371. if (FileName[5] == L':') {
  372. SrcFileName = (LPWSTR)&FileName[4];
  373. } else if ((SrcLen >= 7) && (FileName[4] == L'U') && (FileName[5] == L'N') && (FileName[6] == L'C') && (FileName[7] == Sep)){
  374. SrcFileName = (LPWSTR)&FileName[6];
  375. SrcFileName[0] = Sep;
  376. }
  377. } else if ((SrcLen >= 6) && (FileName[0] == Sep) && (FileName[1] == L'?') && (FileName[2] == FileName[1]) && (FileName[3] == FileName[0])) {
  378. //
  379. // /??/... format
  380. //
  381. SrcFileName = (LPWSTR)&FileName[4];
  382. }
  383. if ( SrcFileName != (LPWSTR)FileName ){
  384. //
  385. // User passed in a FULL path with \\?\ format.
  386. // RtlGetFullPathName_U may fail if we pass in a long file name without \\?\
  387. //
  388. FullFileNameU->Length = wcslen(SrcFileName)*sizeof( WCHAR );
  389. if ( FullFileNameU->Length >= MAX_PATH * sizeof( WCHAR ) ){
  390. RtlFreeHeap( RtlProcessHeap(), 0, FullFileNameU->Buffer );
  391. FullFileNameU->Buffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(), 0, FullFileNameU->Length + sizeof(WCHAR));
  392. if (FullFileNameU->Buffer == NULL) {
  393. if ((SrcLen >= 7) && (SrcFileName == &FileName[6])) {
  394. SrcFileName[0] = L'C';
  395. }
  396. return( FALSE );
  397. }
  398. FullFileNameU->MaximumLength = FullFileNameU->Length + sizeof(WCHAR);
  399. }
  400. RtlCopyMemory(FullFileNameU->Buffer, SrcFileName, FullFileNameU->Length + sizeof(WCHAR));
  401. } else {
  402. FullFileNameU->MaximumLength = MAX_PATH * sizeof( WCHAR );
  403. FullFileNameU->Length = (USHORT)RtlGetFullPathName_U(
  404. SrcFileName,
  405. FullFileNameU->MaximumLength,
  406. FullFileNameU->Buffer,
  407. NULL
  408. );
  409. //
  410. // The return value is supposed to be the length of the filename, without counting
  411. // the trailing NULL character. MAX_PATH is supposed be long enough to contain
  412. // the length of the file name and the trailing NULL, so what we get back had
  413. // better be less than MAX_PATH wchars.
  414. //
  415. if ( FullFileNameU->Length >= FullFileNameU->MaximumLength ){
  416. RtlFreeHeap( RtlProcessHeap(), 0, FullFileNameU->Buffer );
  417. FullFileNameU->Buffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(), 0, FullFileNameU->Length + sizeof(WCHAR));
  418. if (FullFileNameU->Buffer == NULL) {
  419. if (SrcFileName == &FileName[6]) {
  420. SrcFileName[0] = L'C';
  421. }
  422. return( FALSE );
  423. }
  424. FullFileNameU->MaximumLength = FullFileNameU->Length + sizeof(WCHAR);
  425. FullFileNameU->Length = (USHORT)RtlGetFullPathName_U(
  426. SrcFileName,
  427. FullFileNameU->MaximumLength,
  428. FullFileNameU->Buffer,
  429. NULL
  430. );
  431. }
  432. }
  433. if ((SrcLen >= 7) && (SrcFileName == &FileName[6])) {
  434. SrcFileName[0] = L'C';
  435. }
  436. if (FullFileNameU->Length == 0) {
  437. //
  438. // We failed for some reason
  439. //
  440. RtlFreeHeap( RtlProcessHeap(), 0, FullFileNameU->Buffer );
  441. return( FALSE );
  442. }
  443. return( TRUE );
  444. *******************/
  445. }
  446. BOOL
  447. WriteEfsIni(
  448. IN LPCWSTR SectionName,
  449. IN LPCWSTR KeyName,
  450. IN LPCWSTR WriteValue,
  451. IN LPCWSTR IniFileName
  452. )
  453. /*++
  454. Routine Description:
  455. This routine writes to the ini file. A wrap of WritePrivateProfileString
  456. Arguments:
  457. SectionName - Section name (Encryption).
  458. KeyName - Key name (Disable).
  459. WriteValue - The value to be write (1).
  460. IniFileName - The path for ini file (dir\desktop.ini).
  461. Return Value:
  462. TRUE on success
  463. --*/
  464. {
  465. BOOL bRet;
  466. bRet = WritePrivateProfileString(
  467. SectionName,
  468. KeyName,
  469. WriteValue,
  470. IniFileName
  471. );
  472. //
  473. // If SetFileAttributes fails, life should go on.
  474. //
  475. SetFileAttributes(IniFileName, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN );
  476. return bRet;
  477. }
  478. BOOL
  479. EfsClientEncryptionDisable(
  480. IN LPCWSTR DirPath,
  481. IN BOOL Disable
  482. )
  483. /*++
  484. Routine Description:
  485. This routine disable and enable EFS in the directory DirPath.
  486. Arguments:
  487. DirPath - Directory path.
  488. Disable - TRUE to disable
  489. Return Value:
  490. TRUE for SUCCESS
  491. --*/
  492. {
  493. LPWSTR IniFilePath;
  494. WCHAR WriteValue[2];
  495. BOOL bRet = FALSE;
  496. if (DirPath) {
  497. IniFilePath = (LPWSTR)RtlAllocateHeap(
  498. RtlProcessHeap(),
  499. 0,
  500. (wcslen(DirPath)+1+wcslen(INIFILENAME))*sizeof(WCHAR)
  501. );
  502. if (IniFilePath) {
  503. if (Disable) {
  504. wcscpy(WriteValue, L"1");
  505. } else {
  506. wcscpy(WriteValue, L"0");
  507. }
  508. wcscpy(IniFilePath, DirPath);
  509. wcscat(IniFilePath, INIFILENAME);
  510. bRet = WriteEfsIni(INISECTIONNAME, INIKEYNAME, WriteValue, IniFilePath);
  511. RtlFreeHeap( RtlProcessHeap(), 0, IniFilePath );
  512. }
  513. } else {
  514. SetLastError(ERROR_INVALID_PARAMETER);
  515. }
  516. return bRet;
  517. }
  518. BOOL
  519. EfsDisabled(
  520. IN LPCWSTR SectionName,
  521. IN LPCWSTR KeyName,
  522. IN LPCWSTR IniFileName
  523. )
  524. /*++
  525. Routine Description:
  526. This routine checks if the encryption has been turned off for the ini file.
  527. Arguments:
  528. SectionName - Section name (Encryption).
  529. KeyName - Key name (Disable).
  530. IniFileName - The path for ini file (dir\desktop.ini).
  531. Return Value:
  532. TRUE for disabled
  533. --*/
  534. {
  535. DWORD ValueLength;
  536. WCHAR ResultString[4];
  537. memset( ResultString, 0, sizeof(ResultString) );
  538. ValueLength = GetPrivateProfileString(
  539. SectionName,
  540. KeyName,
  541. L"0",
  542. ResultString,
  543. sizeof(ResultString)/sizeof(WCHAR),
  544. IniFileName
  545. );
  546. //
  547. // If GetPrivateProfileString failed, EFS will be enabled
  548. //
  549. return (!wcscmp(L"1", ResultString));
  550. }
  551. BOOL
  552. DirEfsDisabled(
  553. IN LPCWSTR DirName
  554. )
  555. /*++
  556. Routine Description:
  557. This routine checks if the encryption has been turned off for the dir.
  558. Arguments:
  559. SectionName - Section name (Encryption).
  560. KeyName - Key name (Disable).
  561. IniFileName - The path for ini file (dir\desktop.ini).
  562. Return Value:
  563. TRUE for disabled
  564. --*/
  565. {
  566. LPWSTR FileName;
  567. DWORD FileLength = (wcslen(INIFILENAME)+wcslen(DirName)+1)*sizeof (WCHAR);
  568. BOOL bRet = FALSE;
  569. FileName = (PWSTR)RtlAllocateHeap( RtlProcessHeap(), 0, FileLength );
  570. if (FileName) {
  571. wcscpy( FileName, DirName );
  572. wcscat( FileName, INIFILENAME );
  573. bRet = EfsDisabled( INISECTIONNAME, INIKEYNAME, FileName );
  574. RtlFreeHeap( RtlProcessHeap(), 0, FileName );
  575. }
  576. return bRet;
  577. }
  578. BOOL
  579. RemoteFile(
  580. IN LPCWSTR FileName
  581. )
  582. /*++
  583. Routine Description:
  584. This routine checks if the file is a local file.
  585. If a UNC name is passed in, it assumes a remote file. A loopback operation will occur.
  586. Arguments:
  587. FileName - Supplies the user-supplied file name.
  588. Return Value:
  589. TRUE for remote file.
  590. --*/
  591. {
  592. if ( FileName[1] == L':' ){
  593. WCHAR DriveLetter[3];
  594. DWORD BufferLength = 3;
  595. DWORD RetCode = ERROR_SUCCESS;
  596. DriveLetter[0] = FileName[0];
  597. DriveLetter[1] = FileName[1];
  598. DriveLetter[2] = 0;
  599. RetCode = WNetGetConnectionW(
  600. DriveLetter,
  601. DriveLetter,
  602. &BufferLength
  603. );
  604. if (RetCode == ERROR_NOT_CONNECTED) {
  605. return FALSE;
  606. } else {
  607. return TRUE;
  608. }
  609. } else {
  610. return TRUE;
  611. }
  612. }
  613. DWORD
  614. EfsClientEncryptFile(
  615. IN LPCWSTR FileName
  616. )
  617. {
  618. DWORD rc;
  619. BOOL Result;
  620. UNICODE_STRING FullFileNameU;
  621. if (NULL == FileName) {
  622. return ERROR_INVALID_PARAMETER;
  623. }
  624. Result = TranslateFileName( FileName, &FullFileNameU );
  625. if (Result) {
  626. //
  627. // Call the server
  628. //
  629. rc = EfsEncryptFileRPCClient( &FullFileNameU );
  630. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  631. } else {
  632. rc = GetLastError();
  633. }
  634. return( rc );
  635. }
  636. DWORD
  637. EfsClientDecryptFile(
  638. IN LPCWSTR FileName,
  639. IN DWORD dwRecovery
  640. )
  641. {
  642. DWORD rc;
  643. BOOL Result;
  644. UNICODE_STRING FullFileNameU;
  645. if (NULL == FileName) {
  646. return ERROR_INVALID_PARAMETER;
  647. }
  648. Result = TranslateFileName( FileName, &FullFileNameU );
  649. if (Result) {
  650. //
  651. // Call the server
  652. //
  653. //rc = EfsDecryptFileAPI( &FullFileNameU, dwRecovery );
  654. rc = EfsDecryptFileRPCClient( &FullFileNameU, dwRecovery );
  655. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  656. } else {
  657. rc = GetLastError();
  658. }
  659. return( rc );
  660. }
  661. BOOL
  662. EfsClientFileEncryptionStatus(
  663. IN LPCWSTR FileName,
  664. OUT LPDWORD lpStatus
  665. )
  666. /*++
  667. Routine Description:
  668. This routine checks if a file is encryptable or not.
  669. We do not test the NTFS Volume 5 for the reason of performance.
  670. This means we might return a file encryptable (on FAT at etc.), but
  671. actually it could not be encrypted. This should be OK. This is a best effort
  672. API. We have the same problem with network file. Any way, a file could fail
  673. to be encrypted for many reasons, delegation, disk space and etc.
  674. We disable the encryption from %windir% down.
  675. We might change these features later.
  676. Arguments:
  677. FileName - The file to be checked.
  678. lpStatus - The encryption status of the file. Error code if the return value is
  679. FALSE.
  680. Return Value:
  681. TRUE on success, FALSE otherwise.
  682. --*/
  683. {
  684. BOOL Result;
  685. DWORD FileAttributes;
  686. UNICODE_STRING FullFileNameU;
  687. if ((NULL == FileName) || ( NULL == lpStatus)) {
  688. SetLastError(ERROR_INVALID_PARAMETER);
  689. return FALSE;
  690. }
  691. //
  692. // GetFileAttributes should use the name before TanslateFileName
  693. // in case the passed in name is longer than MAX_PATH and using the
  694. // format \\?\
  695. //
  696. FileAttributes = GetFileAttributes( FileName );
  697. if (FileAttributes == -1){
  698. *lpStatus = GetLastError();
  699. return FALSE;
  700. }
  701. Result = TranslateFileName( FileName, &FullFileNameU );
  702. ASSERT(FullFileNameU.Buffer[FullFileNameU.Length / 2] == 0);
  703. if (Result) {
  704. if ( (FileAttributes & FILE_ATTRIBUTE_ENCRYPTED) ||
  705. (FileAttributes & FILE_ATTRIBUTE_SYSTEM) ) {
  706. //
  707. // File not encryptable. Either it is encypted or a system file.
  708. //
  709. if ( FileAttributes & FILE_ATTRIBUTE_ENCRYPTED ){
  710. *lpStatus = FILE_IS_ENCRYPTED;
  711. } else {
  712. *lpStatus = FILE_SYSTEM_ATTR ;
  713. }
  714. } else {
  715. LPWSTR TmpBuffer;
  716. LPWSTR FullPathName;
  717. UINT TmpBuffLen;
  718. UINT FullPathLen;
  719. UINT PathLength;
  720. BOOL GotRoot;
  721. BOOL EfsDisabled = FALSE;
  722. //
  723. // Check if it is the root.
  724. //
  725. if ( FullFileNameU.Length >= MAX_PATH * sizeof(WCHAR)){
  726. //
  727. // We need to put back the \\?\ or \\?\UNC\ to use the
  728. // Win 32 API
  729. //
  730. FullPathLen = FullFileNameU.Length + 7 * sizeof(WCHAR);
  731. TmpBuffLen = FullPathLen;
  732. FullPathName = (LPWSTR)RtlAllocateHeap(
  733. RtlProcessHeap(),
  734. 0,
  735. FullPathLen
  736. );
  737. TmpBuffer = (LPWSTR)RtlAllocateHeap(
  738. RtlProcessHeap(),
  739. 0,
  740. TmpBuffLen
  741. );
  742. if ((FullPathName == NULL) || (TmpBuffer == NULL)){
  743. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  744. if (FullPathName){
  745. RtlFreeHeap(RtlProcessHeap(), 0, FullPathName);
  746. }
  747. if (TmpBuffer){
  748. RtlFreeHeap(RtlProcessHeap(), 0, TmpBuffer);
  749. }
  750. *lpStatus = ERROR_OUTOFMEMORY;
  751. return FALSE;
  752. }
  753. if ( FullFileNameU.Buffer[0] == L'\\' ){
  754. //
  755. // Put back the \\?\UNC\
  756. //
  757. wcscpy(FullPathName, L"\\\\?\\UNC");
  758. wcscat(FullPathName, &(FullFileNameU.Buffer[1]));
  759. FullPathLen = FullFileNameU.Length + 6 * sizeof(WCHAR);
  760. } else {
  761. //
  762. // Put back the \\?\
  763. //
  764. wcscpy(FullPathName, L"\\\\?\\");
  765. wcscat(FullPathName, FullFileNameU.Buffer);
  766. FullPathLen = FullFileNameU.Length + 4 * sizeof(WCHAR);
  767. }
  768. } else {
  769. TmpBuffLen = MAX_PATH * sizeof(WCHAR);
  770. TmpBuffer = (LPWSTR)RtlAllocateHeap(
  771. RtlProcessHeap(),
  772. 0,
  773. TmpBuffLen
  774. );
  775. if (TmpBuffer == NULL){
  776. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  777. *lpStatus = ERROR_OUTOFMEMORY;
  778. return FALSE;
  779. }
  780. FullPathName = FullFileNameU.Buffer;
  781. FullPathLen = FullFileNameU.Length;
  782. }
  783. //
  784. // Check desktop.ini here
  785. //
  786. wcscpy(TmpBuffer, FullFileNameU.Buffer);
  787. if (!(FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  788. //
  789. // This is a file. Get the DIR path
  790. //
  791. int ii;
  792. ii = wcslen(TmpBuffer) - 1;
  793. while ((ii >= 0) && (TmpBuffer[ii] != L'\\')) {
  794. ii--;
  795. }
  796. if (ii>=0) {
  797. TmpBuffer[ii] = 0;
  798. }
  799. }
  800. EfsDisabled = DirEfsDisabled( TmpBuffer );
  801. if (EfsDisabled) {
  802. *lpStatus = FILE_DIR_DISALLOWED;
  803. } else if (!(FileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (FileAttributes & FILE_ATTRIBUTE_READONLY)){
  804. //
  805. // Read only file
  806. //
  807. *lpStatus = FILE_READ_ONLY;
  808. } else {
  809. GotRoot = GetVolumePathName(
  810. FullPathName,
  811. TmpBuffer,
  812. TmpBuffLen
  813. );
  814. if ( GotRoot ){
  815. DWORD RootLength = wcslen(TmpBuffer) - 1;
  816. TmpBuffer[RootLength] = NULL;
  817. if ( (FullPathLen == RootLength * sizeof (WCHAR))
  818. && !wcscmp(TmpBuffer, FullPathName)){
  819. //
  820. // It is the root
  821. //
  822. *lpStatus = FILE_ROOT_DIR;
  823. } else {
  824. //
  825. // Check if it is the Windows\system32 directories
  826. //
  827. PathLength = GetSystemWindowsDirectory( TmpBuffer, TmpBuffLen );
  828. //PathLength = GetWindowsDirectory( TmpBuffer, TmpBuffLen );
  829. //PathLength = GetSystemDirectory( TmpBuffer, TmpBuffLen );
  830. ASSERT(PathLength <= TmpBuffLen);
  831. if ( PathLength > TmpBuffLen ) {
  832. //
  833. // This is unlikely. Not sure who will ever have the length
  834. // of %windir%\system32 longer than MAXPATH in the real world.
  835. // Even this happen, user could still encrypt the file. FILE_UNKNOWN
  836. // does not mean file could\or couldn't be encrypted.
  837. //
  838. *lpStatus = FILE_UNKNOWN ;
  839. } else {
  840. if ( ( FullFileNameU.Length < PathLength * sizeof (WCHAR) ) ||
  841. ( ( FullFileNameU.Buffer[PathLength] ) &&
  842. ( FullFileNameU.Buffer[PathLength] != L'\\') )){
  843. //
  844. // Check if a remote file
  845. //
  846. if ( RemoteFile( FullFileNameU.Buffer ) ){
  847. *lpStatus = FILE_UNKNOWN;
  848. } else {
  849. *lpStatus = FILE_ENCRYPTABLE;
  850. }
  851. } else {
  852. if ( _wcsnicmp(TmpBuffer, FullFileNameU.Buffer, PathLength)){
  853. //
  854. // Not under %SystemRoot%
  855. //
  856. if ( RemoteFile( FullFileNameU.Buffer ) ){
  857. *lpStatus = FILE_UNKNOWN;
  858. } else {
  859. *lpStatus = FILE_ENCRYPTABLE;
  860. }
  861. } else {
  862. //
  863. // In windows root directory. WINNT
  864. //
  865. BOOL bRet;
  866. DWORD allowPathLen;
  867. //
  868. // Check for allow lists
  869. //
  870. allowPathLen = (DWORD) TmpBuffLen;
  871. bRet = GetProfilesDirectory(TmpBuffer, &allowPathLen);
  872. if (!bRet){
  873. RtlFreeHeap(RtlProcessHeap(), 0, TmpBuffer);
  874. TmpBuffer = (LPWSTR)RtlAllocateHeap(
  875. RtlProcessHeap(),
  876. 0,
  877. allowPathLen
  878. );
  879. if (TmpBuffer){
  880. bRet = GetProfilesDirectory(TmpBuffer, &allowPathLen);
  881. } else {
  882. *lpStatus = ERROR_OUTOFMEMORY;
  883. Result = FALSE;
  884. }
  885. }
  886. if (bRet){
  887. //
  888. // Check for Profiles directory
  889. //
  890. if (!_wcsnicmp(TmpBuffer, FullFileNameU.Buffer, allowPathLen - 1)){
  891. *lpStatus = FILE_ENCRYPTABLE;
  892. } else {
  893. //
  894. // Under %windir% but not profiles
  895. //
  896. *lpStatus = FILE_SYSTEM_DIR;
  897. }
  898. } else {
  899. if ( *lpStatus != ERROR_OUTOFMEMORY){
  900. //
  901. // This should not happen, unless a bug in GetProfilesDirectoryEx()
  902. //
  903. ASSERT(FALSE);
  904. *lpStatus = FILE_UNKNOWN;
  905. }
  906. }
  907. }
  908. }
  909. }
  910. }
  911. } else {
  912. //
  913. // Cannot get the root. The reason might very well be out of memory.
  914. // Return FILE_UNKNOWN and let other codes dealing with the memory
  915. // problem.
  916. //
  917. *lpStatus = FILE_UNKNOWN ;
  918. }
  919. }
  920. if ((FullPathName != FullFileNameU.Buffer) && FullPathName){
  921. RtlFreeHeap(RtlProcessHeap(), 0, FullPathName);
  922. }
  923. if (TmpBuffer){
  924. RtlFreeHeap(RtlProcessHeap(), 0, TmpBuffer);
  925. }
  926. }
  927. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  928. } else {
  929. *lpStatus = GetLastError();
  930. }
  931. return Result;
  932. }
  933. DWORD
  934. EfsClientOpenFileRaw(
  935. IN LPCWSTR FileName,
  936. IN ULONG Flags,
  937. OUT PVOID * Context
  938. )
  939. /*++
  940. Routine Description:
  941. This routine is used to open an encrypted file. It opens the file and
  942. prepares the necessary context to be used in ReadRaw data and WriteRaw
  943. data.
  944. Arguments:
  945. FileName -- File name of the file to be exported
  946. Flags -- Indicating if open for export or import; for directory or file.
  947. Context - Export context to be used by READ operation later. Caller should
  948. pass this back in ReadRaw().
  949. Return Value:
  950. Result of the operation.
  951. --*/
  952. {
  953. DWORD rc;
  954. BOOL Result;
  955. UNICODE_STRING FullFileNameU;
  956. if ((NULL == FileName) || ( NULL == Context)) {
  957. return ERROR_INVALID_PARAMETER;
  958. }
  959. Result = TranslateFileName( FileName, &FullFileNameU );
  960. if (Result) {
  961. rc = (EfsOpenFileRawRPCClient(
  962. FullFileNameU.Buffer,
  963. Flags,
  964. Context
  965. )
  966. );
  967. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  968. } else {
  969. rc = GetLastError();
  970. }
  971. return rc;
  972. }
  973. DWORD
  974. EfsClientReadFileRaw(
  975. IN PFE_EXPORT_FUNC ExportCallback,
  976. IN PVOID CallbackContext,
  977. IN PVOID Context
  978. )
  979. /*++
  980. Routine Description:
  981. This routine is used to read encrypted file's raw data. It uses
  982. NTFS FSCTL to get the data.
  983. Arguments:
  984. ExportCallback -- Caller supplied callback function to process the
  985. raw data.
  986. CallbackContext -- Caller's context passed back in ExportCallback.
  987. Context - Export context created in the CreateRaw.
  988. Return Value:
  989. Result of the operation.
  990. --*/
  991. {
  992. return ( EfsReadFileRawRPCClient(
  993. ExportCallback,
  994. CallbackContext,
  995. Context
  996. ));
  997. }
  998. DWORD
  999. EfsClientWriteFileRaw(
  1000. IN PFE_IMPORT_FUNC ImportCallback,
  1001. IN PVOID CallbackContext,
  1002. IN PVOID Context
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. This routine is used to write encrypted file's raw data. It uses
  1007. NTFS FSCTL to write the data.
  1008. Arguments:
  1009. ImportCallback -- Caller supplied callback function to provide the
  1010. raw data.
  1011. CallbackContext -- Caller's context passed back in ImportCallback.
  1012. Context - Import context created in the CreateRaw.
  1013. Return Value:
  1014. Result of the operation.
  1015. --*/
  1016. {
  1017. return ( EfsWriteFileRawRPCClient(
  1018. ImportCallback,
  1019. CallbackContext,
  1020. Context
  1021. ));
  1022. }
  1023. VOID
  1024. EfsClientCloseFileRaw(
  1025. IN PVOID Context
  1026. )
  1027. /*++
  1028. Routine Description:
  1029. This routine frees the resources allocated by the CreateRaw
  1030. Arguments:
  1031. Context - Created by the CreateRaw.
  1032. Return Value:
  1033. NO.
  1034. --*/
  1035. {
  1036. if ( !Context ){
  1037. return;
  1038. }
  1039. EfsCloseFileRawRPCClient( Context );
  1040. }
  1041. //
  1042. // Beta 2 API
  1043. //
  1044. DWORD
  1045. EfsClientAddUsers(
  1046. IN LPCWSTR lpFileName,
  1047. IN PENCRYPTION_CERTIFICATE_LIST pEncryptionCertificates
  1048. )
  1049. /*++
  1050. Routine Description:
  1051. Calls client stub for AddUsersToFile EFS API.
  1052. Arguments:
  1053. lpFileName - Supplies the name of the file to be modified.
  1054. nUsers - Supplies the number of entries in teh pEncryptionCertificates array
  1055. pEncryptionCertificates - Supplies an array of pointers to PENCRYPTION_CERTIFICATE
  1056. structures. Length of array is given in nUsers parameter.
  1057. Return Value:
  1058. --*/
  1059. {
  1060. DWORD rc = ERROR_SUCCESS;
  1061. UNICODE_STRING FullFileNameU;
  1062. DWORD ii = 0;
  1063. CERT_CHAIN_PARA CertChainPara;
  1064. if ((NULL == lpFileName) || (NULL == pEncryptionCertificates)) {
  1065. return ERROR_INVALID_PARAMETER;
  1066. }
  1067. //
  1068. // Let's check to see if the certs are good or not.
  1069. //
  1070. CertChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
  1071. CertChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  1072. CertChainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
  1073. CertChainPara.RequestedUsage.Usage.rgpszUsageIdentifier=&EfsOidlpstr;
  1074. while ((ERROR_SUCCESS == rc) && (ii < pEncryptionCertificates->nUsers)) {
  1075. PCCERT_CONTEXT pCertContext = CertCreateCertificateContext(
  1076. X509_ASN_ENCODING,
  1077. pEncryptionCertificates->pUsers[ii]->pCertBlob->pbData,
  1078. pEncryptionCertificates->pUsers[ii]->pCertBlob->cbData
  1079. );
  1080. if (pCertContext != NULL) {
  1081. PCCERT_CHAIN_CONTEXT pChainContext;
  1082. //
  1083. // Do the chain validation
  1084. //
  1085. if (CertGetCertificateChain (
  1086. HCCE_CURRENT_USER,
  1087. pCertContext,
  1088. NULL,
  1089. NULL,
  1090. &CertChainPara,
  1091. 0,
  1092. NULL,
  1093. &pChainContext
  1094. )) {
  1095. //
  1096. // Let's check the chain
  1097. //
  1098. PCERT_SIMPLE_CHAIN pChain = pChainContext->rgpChain[ pChainContext->cChain - 1 ];
  1099. PCERT_CHAIN_ELEMENT pElement = pChain->rgpElement[ pChain->cElement - 1 ];
  1100. BOOL bSelfSigned = pElement->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED;
  1101. DWORD dwErrorStatus = pChainContext->TrustStatus.dwErrorStatus;
  1102. if (dwErrorStatus) {
  1103. if ((dwErrorStatus == CERT_TRUST_IS_UNTRUSTED_ROOT) && bSelfSigned ){
  1104. //
  1105. // Self signed. Check if it is in the my trusted store
  1106. //
  1107. HCERTSTORE trustedStore;
  1108. PCCERT_CONTEXT pCert=NULL;
  1109. trustedStore = CertOpenStore(
  1110. CERT_STORE_PROV_SYSTEM_W,
  1111. 0, // dwEncodingType
  1112. 0, // hCryptProv,
  1113. CERT_SYSTEM_STORE_CURRENT_USER,
  1114. TRUSTEDPEOPLE
  1115. );
  1116. if (trustedStore) {
  1117. pCert = CertFindCertificateInStore(
  1118. trustedStore,
  1119. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1120. 0,
  1121. CERT_FIND_EXISTING,
  1122. pCertContext,
  1123. pCert
  1124. );
  1125. if (pCert) {
  1126. //
  1127. // We found it.
  1128. //
  1129. CertFreeCertificateContext(pCert);
  1130. } else {
  1131. //
  1132. // Not trusted self-signed cert
  1133. //
  1134. rc = CERT_E_UNTRUSTEDROOT;
  1135. }
  1136. CertCloseStore( trustedStore, 0 );
  1137. } else {
  1138. rc = GetLastError();
  1139. }
  1140. } else {
  1141. //
  1142. // Other chain build error
  1143. // Let's get the error code of the chain building.
  1144. //
  1145. CERT_CHAIN_POLICY_PARA PolicyPara;
  1146. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  1147. RtlZeroMemory(&PolicyPara, sizeof(CERT_CHAIN_POLICY_PARA));
  1148. RtlZeroMemory(&PolicyStatus, sizeof(CERT_CHAIN_POLICY_STATUS));
  1149. PolicyPara.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
  1150. PolicyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
  1151. if (!CertVerifyCertificateChainPolicy(
  1152. CERT_CHAIN_POLICY_BASE,
  1153. pChainContext,
  1154. &PolicyPara,
  1155. &PolicyStatus
  1156. )) {
  1157. rc = PolicyStatus.dwError;
  1158. }
  1159. }
  1160. }
  1161. CertFreeCertificateChain( pChainContext );
  1162. } else {
  1163. rc = GetLastError();
  1164. }
  1165. CertFreeCertificateContext(pCertContext);
  1166. } else {
  1167. rc = GetLastError();
  1168. }
  1169. ii++;
  1170. }
  1171. if (ERROR_SUCCESS == rc) {
  1172. if (TranslateFileName( lpFileName, &FullFileNameU )) {
  1173. rc = EfsAddUsersRPCClient( FullFileNameU.Buffer, pEncryptionCertificates );
  1174. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  1175. } else {
  1176. rc = GetLastError();
  1177. }
  1178. }
  1179. return rc;
  1180. }
  1181. DWORD
  1182. EfsClientRemoveUsers(
  1183. IN LPCWSTR lpFileName,
  1184. IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashes
  1185. )
  1186. /*++
  1187. Routine Description:
  1188. Calls client stub for RemoveUsersFromFile EFS API
  1189. Arguments:
  1190. lpFileName - Supplies the name of the file to be modified.
  1191. pHashes - Supplies a structure containing a list of PENCRYPTION_CERTIFICATE_HASH
  1192. structures, each of which represents a user to remove from the specified file.
  1193. Return Value:
  1194. --*/
  1195. {
  1196. DWORD rc;
  1197. UNICODE_STRING FullFileNameU;
  1198. if ((NULL == lpFileName) || (NULL == pHashes) || (pHashes->pUsers == NULL)) {
  1199. return ERROR_INVALID_PARAMETER;
  1200. }
  1201. if (TranslateFileName( lpFileName, &FullFileNameU )) {
  1202. rc = EfsRemoveUsersRPCClient( FullFileNameU.Buffer, pHashes );
  1203. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  1204. } else {
  1205. rc = GetLastError();
  1206. }
  1207. return rc;
  1208. }
  1209. DWORD
  1210. EfsClientQueryRecoveryAgents(
  1211. IN LPCWSTR lpFileName,
  1212. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pRecoveryAgents
  1213. )
  1214. /*++
  1215. Routine Description:
  1216. Calls client stub for QueryRecoveryAgents EFS API
  1217. Arguments:
  1218. lpFileName - Supplies the name of the file to be modified.
  1219. pRecoveryAgents - Returns a pointer to a structure containing a list
  1220. of PENCRYPTION_CERTIFICATE_HASH structures, each of which represents
  1221. a recovery agent on the file.
  1222. Return Value:
  1223. --*/
  1224. {
  1225. DWORD rc;
  1226. UNICODE_STRING FullFileNameU;
  1227. if ((NULL == lpFileName) || (NULL == pRecoveryAgents)) {
  1228. return ERROR_INVALID_PARAMETER;
  1229. }
  1230. if (TranslateFileName( lpFileName, &FullFileNameU )) {
  1231. rc = EfsQueryRecoveryAgentsRPCClient( FullFileNameU.Buffer, pRecoveryAgents );
  1232. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  1233. } else {
  1234. rc = GetLastError();
  1235. }
  1236. return rc;
  1237. }
  1238. DWORD
  1239. EfsClientQueryUsers(
  1240. IN LPCWSTR lpFileName,
  1241. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pUsers
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. Calls client stub for QueryUsersOnFile EFS API
  1246. Arguments:
  1247. lpFileName - Supplies the name of the file to be modified.
  1248. pUsers - Returns a pointer to a structure containing a list
  1249. of PENCRYPTION_CERTIFICATE_HASH structures, each of which represents
  1250. a user of this file (that is, someone who can decrypt the file).
  1251. Return Value:
  1252. --*/
  1253. {
  1254. DWORD rc;
  1255. UNICODE_STRING FullFileNameU;
  1256. if ((NULL == lpFileName) || (NULL == pUsers)) {
  1257. return ERROR_INVALID_PARAMETER;
  1258. }
  1259. if (TranslateFileName( lpFileName, &FullFileNameU )) {
  1260. rc = EfsQueryUsersRPCClient( FullFileNameU.Buffer, pUsers );
  1261. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  1262. } else {
  1263. rc = GetLastError();
  1264. }
  1265. return rc;
  1266. }
  1267. DWORD
  1268. EfsClientSetEncryptionKey(
  1269. IN PENCRYPTION_CERTIFICATE pEncryptionCertificate
  1270. )
  1271. /*++
  1272. Routine Description:
  1273. Calls client stub for SetFileEncryptionKey EFS API
  1274. Arguments:
  1275. pEncryptionCertificate - Supplies a pointer to an EFS certificate
  1276. representing the public key to use for future encryption operations.
  1277. Return Value:
  1278. --*/
  1279. {
  1280. /*
  1281. if ((NULL == pEncryptionCertificate) || ( NULL == pEncryptionCertificate->pCertBlob)) {
  1282. return ERROR_INVALID_PARAMETER;
  1283. }
  1284. */
  1285. if ( pEncryptionCertificate && ( NULL == pEncryptionCertificate->pCertBlob)) {
  1286. return ERROR_INVALID_PARAMETER;
  1287. }
  1288. DWORD rc = EfsSetEncryptionKeyRPCClient( pEncryptionCertificate );
  1289. return( rc );
  1290. }
  1291. VOID
  1292. EfsClientFreeHashList(
  1293. IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashList
  1294. )
  1295. /*++
  1296. Routine Description:
  1297. This routine frees the memory allocated by a call to
  1298. QueryUsersOnEncryptedFile and QueryRecoveryAgentsOnEncryptedFile
  1299. Arguments:
  1300. pHashList - Supplies the hash list to be freed.
  1301. Return Value:
  1302. None. Faults in user's context if passed bogus data.
  1303. --*/
  1304. {
  1305. if (NULL == pHashList) {
  1306. SetLastError(ERROR_INVALID_PARAMETER);
  1307. return;
  1308. }
  1309. for (DWORD i=0; i<pHashList->nCert_Hash ; i++) {
  1310. PENCRYPTION_CERTIFICATE_HASH pHash = pHashList->pUsers[i];
  1311. if (pHash->lpDisplayInformation) {
  1312. MIDL_user_free( pHash->lpDisplayInformation );
  1313. }
  1314. if (pHash->pUserSid) {
  1315. MIDL_user_free( pHash->pUserSid );
  1316. }
  1317. MIDL_user_free( pHash->pHash->pbData );
  1318. MIDL_user_free( pHash->pHash );
  1319. MIDL_user_free( pHash );
  1320. }
  1321. MIDL_user_free( pHashList->pUsers );
  1322. MIDL_user_free( pHashList );
  1323. return;
  1324. }
  1325. DWORD
  1326. EfsGetMySDRpcBlob(
  1327. IN PSECURITY_DESCRIPTOR pInSD,
  1328. OUT PEFS_RPC_BLOB *pOutSDRpcBlob
  1329. )
  1330. {
  1331. DWORD rc = ERROR_SUCCESS;
  1332. PSECURITY_DESCRIPTOR pRelativeSD;
  1333. ULONG SDLength = 0;
  1334. if ( (pInSD == NULL) || !RtlValidSecurityDescriptor(pInSD) ) {
  1335. return(ERROR_INVALID_PARAMETER);
  1336. }
  1337. if ( ((PISECURITY_DESCRIPTOR)pInSD)->Control & SE_SELF_RELATIVE) {
  1338. //
  1339. // The input SD is already RELATIVE
  1340. // Just fill EFS_RPC_BLOB
  1341. //
  1342. *pOutSDRpcBlob = (PEFS_RPC_BLOB) RtlAllocateHeap(
  1343. RtlProcessHeap(),
  1344. 0,
  1345. sizeof(EFS_RPC_BLOB)
  1346. );
  1347. if (*pOutSDRpcBlob) {
  1348. (*pOutSDRpcBlob)->cbData = RtlLengthSecurityDescriptor (
  1349. pInSD
  1350. );
  1351. (*pOutSDRpcBlob)->pbData = (PBYTE) pInSD;
  1352. } else {
  1353. return(ERROR_NOT_ENOUGH_MEMORY);
  1354. }
  1355. } else {
  1356. //
  1357. // get the length
  1358. //
  1359. RtlMakeSelfRelativeSD( pInSD,
  1360. NULL,
  1361. &SDLength
  1362. );
  1363. if ( SDLength > 0 ) {
  1364. *pOutSDRpcBlob = (PEFS_RPC_BLOB) RtlAllocateHeap(
  1365. RtlProcessHeap(),
  1366. 0,
  1367. SDLength + sizeof(EFS_RPC_BLOB)
  1368. );
  1369. if ( !(*pOutSDRpcBlob) ) {
  1370. return(ERROR_NOT_ENOUGH_MEMORY);
  1371. }
  1372. pRelativeSD = (PSECURITY_DESCRIPTOR)(*pOutSDRpcBlob + 1);
  1373. (*pOutSDRpcBlob)->cbData = SDLength;
  1374. (*pOutSDRpcBlob)->pbData = (PBYTE) pRelativeSD;
  1375. rc = RtlNtStatusToDosError(
  1376. RtlMakeSelfRelativeSD( pInSD,
  1377. pRelativeSD,
  1378. &SDLength
  1379. ));
  1380. if ( rc != ERROR_SUCCESS ) {
  1381. RtlFreeHeap(RtlProcessHeap(), 0, *pOutSDRpcBlob);
  1382. *pOutSDRpcBlob = NULL;
  1383. return(rc);
  1384. }
  1385. } else {
  1386. //
  1387. // something is wrong with the SD
  1388. //
  1389. return(ERROR_INVALID_PARAMETER);
  1390. }
  1391. }
  1392. return(rc);
  1393. }
  1394. DWORD
  1395. EfsClientDuplicateEncryptionInfo(
  1396. IN LPCWSTR lpSrcFile,
  1397. IN LPCWSTR lpDestFile,
  1398. IN DWORD dwCreationDistribution,
  1399. IN DWORD dwAttributes,
  1400. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes
  1401. )
  1402. {
  1403. DWORD rc = ERROR_SUCCESS;
  1404. UNICODE_STRING SrcFullFileNameU;
  1405. UNICODE_STRING DestFullFileNameU;
  1406. if (TranslateFileName( lpSrcFile, &SrcFullFileNameU )) {
  1407. if (TranslateFileName( lpDestFile, &DestFullFileNameU )) {
  1408. PEFS_RPC_BLOB pRpcBlob = NULL;
  1409. BOOL bInheritHandle = FALSE;
  1410. if (lpSecurityAttributes) {
  1411. rc = EfsGetMySDRpcBlob(lpSecurityAttributes->lpSecurityDescriptor, &pRpcBlob);
  1412. bInheritHandle = lpSecurityAttributes->bInheritHandle;
  1413. }
  1414. if (ERROR_SUCCESS == rc) {
  1415. rc = EfsDuplicateEncryptionInfoRPCClient(
  1416. SrcFullFileNameU.Buffer,
  1417. DestFullFileNameU.Buffer,
  1418. dwCreationDistribution,
  1419. dwAttributes,
  1420. pRpcBlob,
  1421. bInheritHandle
  1422. );
  1423. if (pRpcBlob) {
  1424. RtlFreeHeap(RtlProcessHeap(), 0, pRpcBlob);
  1425. }
  1426. }
  1427. RtlFreeHeap(RtlProcessHeap(), 0, DestFullFileNameU.Buffer);
  1428. } else {
  1429. rc = GetLastError();
  1430. }
  1431. RtlFreeHeap(RtlProcessHeap(), 0, SrcFullFileNameU.Buffer);
  1432. } else {
  1433. rc = GetLastError();
  1434. }
  1435. return( rc );
  1436. }
  1437. DWORD
  1438. EfsClientFileKeyInfo(
  1439. IN LPCWSTR lpFileName,
  1440. IN DWORD InfoClass,
  1441. OUT PEFS_RPC_BLOB *KeyInfo
  1442. )
  1443. /*++
  1444. Routine Description:
  1445. Calls client stub for EncryptedFileKeyInfo EFS API
  1446. Arguments:
  1447. lpFileName - Supplies the name of the file.
  1448. KeyInfo - Returns a pointer to a structure containing key info.
  1449. Return Value:
  1450. --*/
  1451. {
  1452. DWORD rc;
  1453. UNICODE_STRING FullFileNameU;
  1454. if ((NULL == lpFileName) || (NULL == KeyInfo)) {
  1455. return ERROR_INVALID_PARAMETER;
  1456. }
  1457. if (TranslateFileName( lpFileName, &FullFileNameU )) {
  1458. rc = EfsFileKeyInfoRPCClient( FullFileNameU.Buffer, InfoClass, KeyInfo );
  1459. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  1460. } else {
  1461. rc = GetLastError();
  1462. }
  1463. return rc;
  1464. }
  1465. VOID
  1466. EfsClientFreeKeyInfo(
  1467. IN PEFS_RPC_BLOB pKeyInfo
  1468. )
  1469. /*++
  1470. Routine Description:
  1471. This routine frees the memory allocated by a call to
  1472. EfsClientFileKeyInfo
  1473. Arguments:
  1474. pKeyInfo - Supplies the memory pointer to be freed.
  1475. Return Value:
  1476. None. Faults in user's context if passed bogus data.
  1477. --*/
  1478. {
  1479. if (NULL == pKeyInfo) {
  1480. SetLastError(ERROR_INVALID_PARAMETER);
  1481. return;
  1482. }
  1483. if (pKeyInfo->pbData) {
  1484. MIDL_user_free( pKeyInfo->pbData );
  1485. }
  1486. MIDL_user_free( pKeyInfo );
  1487. return;
  1488. }