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.

625 lines
16 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: filesp.cpp
  7. //
  8. // Contents: File Scheme Provider
  9. //
  10. // History: 08-Aug-97 kirtd Created
  11. // 01-Jan-02 philh Changed to internally use UNICODE Urls
  12. //
  13. //----------------------------------------------------------------------------
  14. #include <global.hxx>
  15. //+---------------------------------------------------------------------------
  16. //
  17. // Function: FileRetrieveEncodedObject
  18. //
  19. // Synopsis: retrieve encoded object via Win32 File I/O
  20. //
  21. //----------------------------------------------------------------------------
  22. BOOL WINAPI FileRetrieveEncodedObject (
  23. IN LPCWSTR pwszUrl,
  24. IN LPCSTR pszObjectOid,
  25. IN DWORD dwRetrievalFlags,
  26. IN DWORD dwTimeout,
  27. OUT PCRYPT_BLOB_ARRAY pObject,
  28. OUT PFN_FREE_ENCODED_OBJECT_FUNC* ppfnFreeObject,
  29. OUT LPVOID* ppvFreeContext,
  30. IN HCRYPTASYNC hAsyncRetrieve,
  31. IN PCRYPT_CREDENTIALS pCredentials,
  32. IN PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
  33. )
  34. {
  35. BOOL fResult;
  36. IObjectRetriever* por = NULL;
  37. if ( !( dwRetrievalFlags & CRYPT_ASYNC_RETRIEVAL ) )
  38. {
  39. por = new CFileSynchronousRetriever;
  40. }
  41. if ( por == NULL )
  42. {
  43. SetLastError( (DWORD) E_OUTOFMEMORY );
  44. return( FALSE );
  45. }
  46. fResult = por->RetrieveObjectByUrl(
  47. pwszUrl,
  48. pszObjectOid,
  49. dwRetrievalFlags,
  50. dwTimeout,
  51. (LPVOID *)pObject,
  52. ppfnFreeObject,
  53. ppvFreeContext,
  54. hAsyncRetrieve,
  55. pCredentials,
  56. NULL,
  57. pAuxInfo
  58. );
  59. por->Release();
  60. return( fResult );
  61. }
  62. //+---------------------------------------------------------------------------
  63. //
  64. // Function: FileFreeEncodedObject
  65. //
  66. // Synopsis: free encoded object retrieved via FileRetrieveEncodedObject
  67. //
  68. //----------------------------------------------------------------------------
  69. VOID WINAPI FileFreeEncodedObject (
  70. IN LPCSTR pszObjectOid,
  71. IN PCRYPT_BLOB_ARRAY pObject,
  72. IN LPVOID pvFreeContext
  73. )
  74. {
  75. BOOL fFreeBlobs = TRUE;
  76. PFILE_BINDINGS pfb = (PFILE_BINDINGS)pvFreeContext;
  77. //
  78. // If no file bindings were given in the context then this
  79. // must be a mapped file so we deal with it as such
  80. //
  81. if ( pfb != NULL )
  82. {
  83. fFreeBlobs = FALSE;
  84. FileFreeBindings( pfb );
  85. }
  86. FileFreeCryptBlobArray( pObject, fFreeBlobs );
  87. }
  88. //+---------------------------------------------------------------------------
  89. //
  90. // Function: FileCancelAsyncRetrieval
  91. //
  92. // Synopsis: cancel asynchronous object retrieval
  93. //
  94. //----------------------------------------------------------------------------
  95. BOOL WINAPI FileCancelAsyncRetrieval (
  96. IN HCRYPTASYNC hAsyncRetrieve
  97. )
  98. {
  99. SetLastError( (DWORD) E_NOTIMPL );
  100. return( FALSE );
  101. }
  102. //+---------------------------------------------------------------------------
  103. //
  104. // Member: CFileSynchronousRetriever::CFileSynchronousRetriever, public
  105. //
  106. // Synopsis: Constructor
  107. //
  108. //----------------------------------------------------------------------------
  109. CFileSynchronousRetriever::CFileSynchronousRetriever ()
  110. {
  111. m_cRefs = 1;
  112. }
  113. //+---------------------------------------------------------------------------
  114. //
  115. // Member: CFileSynchronousRetriever::~CFileSynchronousRetriever, public
  116. //
  117. // Synopsis: Destructor
  118. //
  119. //----------------------------------------------------------------------------
  120. CFileSynchronousRetriever::~CFileSynchronousRetriever ()
  121. {
  122. }
  123. //+---------------------------------------------------------------------------
  124. //
  125. // Member: CFileSynchronousRetriever::AddRef, public
  126. //
  127. // Synopsis: IRefCountedObject::AddRef
  128. //
  129. //----------------------------------------------------------------------------
  130. VOID
  131. CFileSynchronousRetriever::AddRef ()
  132. {
  133. InterlockedIncrement( (LONG *)&m_cRefs );
  134. }
  135. //+---------------------------------------------------------------------------
  136. //
  137. // Member: CFileSynchronousRetriever::Release, public
  138. //
  139. // Synopsis: IRefCountedObject::Release
  140. //
  141. //----------------------------------------------------------------------------
  142. VOID
  143. CFileSynchronousRetriever::Release ()
  144. {
  145. if ( InterlockedDecrement( (LONG *)&m_cRefs ) == 0 )
  146. {
  147. delete this;
  148. }
  149. }
  150. //+---------------------------------------------------------------------------
  151. //
  152. // Member: CFileSynchronousRetriever::RetrieveObjectByUrl, public
  153. //
  154. // Synopsis: IObjectRetriever::RetrieveObjectByUrl
  155. //
  156. //----------------------------------------------------------------------------
  157. BOOL
  158. CFileSynchronousRetriever::RetrieveObjectByUrl (
  159. LPCWSTR pwszUrl,
  160. LPCSTR pszObjectOid,
  161. DWORD dwRetrievalFlags,
  162. DWORD dwTimeout,
  163. LPVOID* ppvObject,
  164. PFN_FREE_ENCODED_OBJECT_FUNC* ppfnFreeObject,
  165. LPVOID* ppvFreeContext,
  166. HCRYPTASYNC hAsyncRetrieve,
  167. PCRYPT_CREDENTIALS pCredentials,
  168. LPVOID pvVerify,
  169. PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
  170. )
  171. {
  172. BOOL fResult = FALSE;
  173. DWORD LastError = 0;
  174. PFILE_BINDINGS pfb = NULL;
  175. LPVOID pvFreeContext = NULL;
  176. BOOL fIsUncUrl;
  177. assert( hAsyncRetrieve == NULL );
  178. fIsUncUrl = FileIsUncUrl( pwszUrl );
  179. if ( ( dwRetrievalFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) &&
  180. ( fIsUncUrl == TRUE ) )
  181. {
  182. return( SchemeRetrieveCachedCryptBlobArray(
  183. pwszUrl,
  184. dwRetrievalFlags,
  185. (PCRYPT_BLOB_ARRAY)ppvObject,
  186. ppfnFreeObject,
  187. ppvFreeContext,
  188. pAuxInfo
  189. ) );
  190. }
  191. fResult = FileGetBindings(
  192. pwszUrl,
  193. dwRetrievalFlags,
  194. pCredentials,
  195. &pfb,
  196. pAuxInfo
  197. );
  198. if ( fResult == TRUE )
  199. {
  200. if ( pfb->fMapped == FALSE )
  201. {
  202. fResult = FileSendReceiveUrlRequest(
  203. pfb,
  204. (PCRYPT_BLOB_ARRAY)ppvObject
  205. );
  206. LastError = GetLastError();
  207. FileFreeBindings( pfb );
  208. }
  209. else
  210. {
  211. fResult = FileConvertMappedBindings(
  212. pfb,
  213. (PCRYPT_BLOB_ARRAY)ppvObject
  214. );
  215. if ( fResult == TRUE )
  216. {
  217. pvFreeContext = (LPVOID)pfb;
  218. }
  219. else
  220. {
  221. LastError = GetLastError();
  222. FileFreeBindings( pfb );
  223. }
  224. }
  225. }
  226. if ( fResult == TRUE )
  227. {
  228. if ( !( dwRetrievalFlags & CRYPT_DONT_CACHE_RESULT ) &&
  229. ( fIsUncUrl == TRUE ) )
  230. {
  231. fResult = SchemeCacheCryptBlobArray(
  232. pwszUrl,
  233. dwRetrievalFlags,
  234. (PCRYPT_BLOB_ARRAY)ppvObject,
  235. pAuxInfo
  236. );
  237. if ( fResult == FALSE )
  238. {
  239. FileFreeEncodedObject(
  240. pszObjectOid,
  241. (PCRYPT_BLOB_ARRAY)ppvObject,
  242. pvFreeContext
  243. );
  244. }
  245. }
  246. else
  247. {
  248. SchemeRetrieveUncachedAuxInfo( pAuxInfo );
  249. }
  250. }
  251. if ( fResult == TRUE )
  252. {
  253. *ppfnFreeObject = FileFreeEncodedObject;
  254. *ppvFreeContext = pvFreeContext;
  255. }
  256. if ( LastError != 0 )
  257. {
  258. SetLastError( LastError );
  259. }
  260. return( fResult );
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // Member: CInetSynchronousRetriever::CancelAsyncRetrieval, public
  265. //
  266. // Synopsis: IObjectRetriever::CancelAsyncRetrieval
  267. //
  268. //----------------------------------------------------------------------------
  269. BOOL
  270. CFileSynchronousRetriever::CancelAsyncRetrieval ()
  271. {
  272. SetLastError( (DWORD) E_NOTIMPL );
  273. return( FALSE );
  274. }
  275. //+---------------------------------------------------------------------------
  276. //
  277. // Function: FileGetBindings
  278. //
  279. // Synopsis: get the file bindings
  280. //
  281. //----------------------------------------------------------------------------
  282. BOOL
  283. FileGetBindings (
  284. LPCWSTR pwszUrl,
  285. DWORD dwRetrievalFlags,
  286. PCRYPT_CREDENTIALS pCredentials,
  287. PFILE_BINDINGS* ppfb,
  288. PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
  289. )
  290. {
  291. DWORD LastError;
  292. LPWSTR pwszFile = (LPWSTR)pwszUrl;
  293. HANDLE hFile;
  294. HANDLE hFileMap;
  295. LPVOID pvMap = NULL;
  296. DWORD dwSize;
  297. PFILE_BINDINGS pfb;
  298. BOOL fResult;
  299. WIN32_FILE_ATTRIBUTE_DATA FileAttr;
  300. DWORD dwMaxUrlRetrievalByteCount = 0; // 0 => no max
  301. if (pAuxInfo &&
  302. offsetof(CRYPT_RETRIEVE_AUX_INFO, dwMaxUrlRetrievalByteCount) <
  303. pAuxInfo->cbSize)
  304. dwMaxUrlRetrievalByteCount = pAuxInfo->dwMaxUrlRetrievalByteCount;
  305. if ( pCredentials != NULL )
  306. {
  307. SetLastError( (DWORD) E_NOTIMPL );
  308. return( FALSE );
  309. }
  310. if ( wcsstr( pwszUrl, FILE_SCHEME_PLUSPLUS ) != NULL )
  311. {
  312. pwszFile += wcslen( FILE_SCHEME_PLUSPLUS );
  313. }
  314. fResult = GetFileAttributesExW(
  315. pwszFile,
  316. GetFileExInfoStandard,
  317. &FileAttr
  318. );
  319. if (!fResult)
  320. {
  321. return(FALSE);
  322. }
  323. dwSize = FileAttr.nFileSizeLow;
  324. if ((FileAttr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
  325. (0 != FileAttr.nFileSizeHigh) || (0 == dwSize)
  326. ||
  327. ((0 != dwMaxUrlRetrievalByteCount) &&
  328. (dwSize > dwMaxUrlRetrievalByteCount)))
  329. {
  330. I_CryptNetDebugErrorPrintfA(
  331. "CRYPTNET.DLL --> Invalid File(%S):: Attributes: 0x%x Size: %d\n",
  332. pwszFile, FileAttr.dwFileAttributes, FileAttr.nFileSizeLow);
  333. SetLastError(ERROR_INVALID_DATA);
  334. return FALSE;
  335. }
  336. pfb = new FILE_BINDINGS;
  337. if ( pfb == NULL )
  338. {
  339. SetLastError( (DWORD) E_OUTOFMEMORY );
  340. return( FALSE );
  341. }
  342. hFile = CreateFileW(
  343. pwszFile,
  344. GENERIC_READ,
  345. FILE_SHARE_READ,
  346. NULL,
  347. OPEN_EXISTING,
  348. 0,
  349. NULL
  350. );
  351. if ( hFile == INVALID_HANDLE_VALUE )
  352. {
  353. delete pfb;
  354. return( FALSE );
  355. }
  356. if ( dwSize <= FILE_MAPPING_THRESHOLD )
  357. {
  358. pfb->hFile = hFile;
  359. pfb->dwSize = dwSize;
  360. pfb->fMapped = FALSE;
  361. pfb->hFileMap = NULL;
  362. pfb->pvMap = NULL;
  363. *ppfb = pfb;
  364. return( TRUE );
  365. }
  366. hFileMap = CreateFileMappingA(
  367. hFile,
  368. NULL,
  369. PAGE_READONLY,
  370. 0,
  371. 0,
  372. NULL
  373. );
  374. if ( hFileMap != NULL )
  375. {
  376. pvMap = MapViewOfFile( hFileMap, FILE_MAP_READ, 0, 0, 0 );
  377. }
  378. if ( pvMap != NULL )
  379. {
  380. pfb->hFile = hFile;
  381. pfb->dwSize = dwSize;
  382. pfb->fMapped = TRUE;
  383. pfb->hFileMap = hFileMap;
  384. pfb->pvMap = pvMap;
  385. *ppfb = pfb;
  386. return( TRUE );
  387. }
  388. LastError = GetLastError();
  389. if ( hFileMap != NULL )
  390. {
  391. CloseHandle( hFileMap );
  392. }
  393. if ( hFile != INVALID_HANDLE_VALUE )
  394. {
  395. CloseHandle( hFile );
  396. }
  397. delete pfb;
  398. SetLastError( LastError );
  399. return( FALSE );
  400. }
  401. //+---------------------------------------------------------------------------
  402. //
  403. // Function: FileFreeBindings
  404. //
  405. // Synopsis: free the file bindings
  406. //
  407. //----------------------------------------------------------------------------
  408. VOID
  409. FileFreeBindings (
  410. PFILE_BINDINGS pfb
  411. )
  412. {
  413. if ( pfb->fMapped == TRUE )
  414. {
  415. UnmapViewOfFile( pfb->pvMap );
  416. CloseHandle( pfb->hFileMap );
  417. }
  418. CloseHandle( pfb->hFile );
  419. delete pfb;
  420. }
  421. //+---------------------------------------------------------------------------
  422. //
  423. // Function: FileSendReceiveUrlRequest
  424. //
  425. // Synopsis: synchronously process the request for the file bits using
  426. // Win32 File API. Note that this only works for non-mapped
  427. // file bindings, for mapped file bindings use
  428. // FileConvertMappedBindings
  429. //
  430. //----------------------------------------------------------------------------
  431. BOOL
  432. FileSendReceiveUrlRequest (
  433. PFILE_BINDINGS pfb,
  434. PCRYPT_BLOB_ARRAY pcba
  435. )
  436. {
  437. BOOL fResult;
  438. LPBYTE pb;
  439. DWORD dwRead;
  440. assert( pfb->fMapped == FALSE );
  441. pb = CCryptBlobArray::AllocBlob( pfb->dwSize );
  442. if ( pb == NULL )
  443. {
  444. SetLastError( (DWORD) E_OUTOFMEMORY );
  445. return( FALSE );
  446. }
  447. fResult = ReadFile( pfb->hFile, pb, pfb->dwSize, &dwRead, NULL );
  448. if ( fResult == TRUE )
  449. {
  450. CCryptBlobArray cba( 1, 1, fResult );
  451. if ( dwRead == pfb->dwSize )
  452. {
  453. fResult = cba.AddBlob( pfb->dwSize, pb, FALSE );
  454. }
  455. else
  456. {
  457. SetLastError( (DWORD) E_FAIL );
  458. fResult = FALSE;
  459. }
  460. if ( fResult == TRUE )
  461. {
  462. cba.GetArrayInNativeForm( pcba );
  463. }
  464. else
  465. {
  466. cba.FreeArray( FALSE );
  467. }
  468. }
  469. if ( fResult == FALSE )
  470. {
  471. CCryptBlobArray::FreeBlob( pb );
  472. }
  473. return( fResult );
  474. }
  475. //+---------------------------------------------------------------------------
  476. //
  477. // Function: FileConvertMappedBindings
  478. //
  479. // Synopsis: convert mapped bindings to a CRYPT_BLOB_ARRAY
  480. //
  481. //----------------------------------------------------------------------------
  482. BOOL
  483. FileConvertMappedBindings (
  484. PFILE_BINDINGS pfb,
  485. PCRYPT_BLOB_ARRAY pcba
  486. )
  487. {
  488. BOOL fResult;
  489. assert( pfb->fMapped == TRUE );
  490. CCryptBlobArray cba( 1, 1, fResult );
  491. if ( fResult == TRUE )
  492. {
  493. fResult = cba.AddBlob( pfb->dwSize, (LPBYTE)pfb->pvMap, FALSE );
  494. }
  495. if ( fResult == TRUE )
  496. {
  497. cba.GetArrayInNativeForm( pcba );
  498. }
  499. else
  500. {
  501. cba.FreeArray( FALSE );
  502. }
  503. return( fResult );
  504. }
  505. //+---------------------------------------------------------------------------
  506. //
  507. // Function: FileFreeCryptBlobArray
  508. //
  509. // Synopsis: free the CRYPT_BLOB_ARRAY
  510. //
  511. //----------------------------------------------------------------------------
  512. VOID
  513. FileFreeCryptBlobArray (
  514. PCRYPT_BLOB_ARRAY pcba,
  515. BOOL fFreeBlobs
  516. )
  517. {
  518. CCryptBlobArray cba( pcba, 0 );
  519. cba.FreeArray( fFreeBlobs );
  520. }
  521. //+---------------------------------------------------------------------------
  522. //
  523. // Function: FileIsUncUrl
  524. //
  525. // Synopsis: is this a UNC path URL?
  526. //
  527. //----------------------------------------------------------------------------
  528. BOOL
  529. FileIsUncUrl (
  530. LPCWSTR pwszUrl
  531. )
  532. {
  533. DWORD cch = 0;
  534. if ( wcsstr( pwszUrl, FILE_SCHEME_PLUSPLUS ) != NULL )
  535. {
  536. cch += wcslen( FILE_SCHEME_PLUSPLUS );
  537. }
  538. if ( ( pwszUrl[ cch ] == L'\\' ) && ( pwszUrl[ cch + 1 ] == L'\\' ) )
  539. {
  540. return( TRUE );
  541. }
  542. return( FALSE );
  543. }