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.

626 lines
19 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: orm.cpp
  7. //
  8. // Contents: Implementation of object retrieval manager
  9. //
  10. // History: 24-Jul-97 kirtd Created
  11. // 01-Jan-02 philh Changed to internally use UNICODE Urls
  12. //
  13. //----------------------------------------------------------------------------
  14. #include <global.hxx>
  15. #ifndef INTERNET_MAX_SCHEME_LENGTH
  16. #define INTERNET_MAX_SCHEME_LENGTH 32 // longest protocol name length
  17. #endif
  18. //+---------------------------------------------------------------------------
  19. //
  20. // Member: CObjectRetrievalManager::CObjectRetrievalManager, public
  21. //
  22. // Synopsis: Constructor
  23. //
  24. //----------------------------------------------------------------------------
  25. CObjectRetrievalManager::CObjectRetrievalManager ()
  26. {
  27. m_cRefs = 1;
  28. m_hSchemeRetrieve = NULL;
  29. m_pfnSchemeRetrieve = NULL;
  30. m_hContextCreate = NULL;
  31. m_pfnContextCreate = NULL;
  32. }
  33. //+---------------------------------------------------------------------------
  34. //
  35. // Member: CObjectRetrievalManager::~CObjectRetrievalManager, public
  36. //
  37. // Synopsis: Destructor
  38. //
  39. //----------------------------------------------------------------------------
  40. CObjectRetrievalManager::~CObjectRetrievalManager ()
  41. {
  42. }
  43. //+---------------------------------------------------------------------------
  44. //
  45. // Member: CObjectRetrievalManager::AddRef, public
  46. //
  47. // Synopsis: IRefCountedObject::AddRef
  48. //
  49. //----------------------------------------------------------------------------
  50. VOID
  51. CObjectRetrievalManager::AddRef ()
  52. {
  53. InterlockedIncrement( (LONG *)&m_cRefs );
  54. }
  55. //+---------------------------------------------------------------------------
  56. //
  57. // Member: CObjectRetrievalManager::Release, public
  58. //
  59. // Synopsis: IRefCountedObject::Release
  60. //
  61. //----------------------------------------------------------------------------
  62. VOID
  63. CObjectRetrievalManager::Release ()
  64. {
  65. if ( InterlockedDecrement( (LONG *)&m_cRefs ) == 0 )
  66. {
  67. delete this;
  68. }
  69. }
  70. //+---------------------------------------------------------------------------
  71. //
  72. // Member: CObjectRetrievalManager::RetrieveObjectByUrl, public
  73. //
  74. // Synopsis: object retrieval given an URL
  75. //
  76. //----------------------------------------------------------------------------
  77. BOOL
  78. CObjectRetrievalManager::RetrieveObjectByUrl (
  79. LPCWSTR pwszUrl,
  80. LPCSTR pszObjectOid,
  81. DWORD dwRetrievalFlags,
  82. DWORD dwTimeout,
  83. LPVOID* ppvObject,
  84. PFN_FREE_ENCODED_OBJECT_FUNC* ppfnFreeObject,
  85. LPVOID* ppvFreeContext,
  86. HCRYPTASYNC hAsyncRetrieve,
  87. PCRYPT_CREDENTIALS pCredentials,
  88. LPVOID pvVerify,
  89. PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
  90. )
  91. {
  92. BOOL fResult;
  93. CRYPT_BLOB_ARRAY cba;
  94. PFN_FREE_ENCODED_OBJECT_FUNC pfnFreeObject = NULL;
  95. LPVOID pvFreeContext = NULL;
  96. assert( ppfnFreeObject == NULL );
  97. assert( ppvFreeContext == NULL );
  98. //
  99. // Validate arguments and initialize the providers
  100. //
  101. fResult = ValidateRetrievalArguments(
  102. pwszUrl,
  103. pszObjectOid,
  104. dwRetrievalFlags,
  105. dwTimeout,
  106. ppvObject,
  107. hAsyncRetrieve,
  108. pCredentials,
  109. pvVerify,
  110. pAuxInfo
  111. );
  112. if ( fResult == TRUE )
  113. {
  114. fResult = LoadProviders( pwszUrl, pszObjectOid );
  115. }
  116. //
  117. // For Async support we should prepare here
  118. //
  119. //
  120. // Call the scheme provider to process the retrieval
  121. //
  122. if ( fResult == TRUE )
  123. {
  124. // +1 - Online
  125. // 0 - Offline, current time >= earliest online time, hit the wire
  126. // -1 - Offline, current time < earliest onlime time
  127. LONG lStatus;
  128. if ( CRYPT_OFFLINE_CHECK_RETRIEVAL ==
  129. ( dwRetrievalFlags & ( CRYPT_OFFLINE_CHECK_RETRIEVAL |
  130. CRYPT_CACHE_ONLY_RETRIEVAL ) ) )
  131. {
  132. lStatus = GetUrlStatusW( pwszUrl, pszObjectOid, dwRetrievalFlags );
  133. }
  134. else
  135. {
  136. lStatus = 1;
  137. }
  138. if (lStatus >= 0)
  139. {
  140. fResult = CallSchemeRetrieveObjectByUrl(
  141. pwszUrl,
  142. pszObjectOid,
  143. dwRetrievalFlags,
  144. dwTimeout,
  145. &cba,
  146. &pfnFreeObject,
  147. &pvFreeContext,
  148. hAsyncRetrieve,
  149. pCredentials,
  150. pAuxInfo
  151. );
  152. if ( CRYPT_OFFLINE_CHECK_RETRIEVAL ==
  153. ( dwRetrievalFlags & ( CRYPT_OFFLINE_CHECK_RETRIEVAL |
  154. CRYPT_CACHE_ONLY_RETRIEVAL ) ) )
  155. {
  156. if ( fResult != TRUE )
  157. {
  158. DWORD dwErr = GetLastError();
  159. SetOfflineUrlW( pwszUrl, pszObjectOid, dwRetrievalFlags );
  160. SetLastError( dwErr );
  161. }
  162. else if ( lStatus == 0 )
  163. {
  164. SetOnlineUrlW( pwszUrl, pszObjectOid, dwRetrievalFlags );
  165. }
  166. }
  167. }
  168. else
  169. {
  170. SetLastError( (DWORD) ERROR_NOT_CONNECTED );
  171. fResult = FALSE;
  172. }
  173. }
  174. //
  175. // If we successfully retrieved the object and this is a synchronous
  176. // retrieval, then we call our own OnRetrievalCompletion in order
  177. // to complete the processing
  178. //
  179. if ( ( fResult == TRUE ) && !( dwRetrievalFlags & CRYPT_ASYNC_RETRIEVAL ) )
  180. {
  181. fResult = OnRetrievalCompletion(
  182. S_OK,
  183. pwszUrl,
  184. pszObjectOid,
  185. dwRetrievalFlags,
  186. &cba,
  187. pfnFreeObject,
  188. pvFreeContext,
  189. pvVerify,
  190. ppvObject
  191. );
  192. }
  193. return( fResult );
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Member: CObjectRetrievalManager::CancelAsyncRetrieval, public
  198. //
  199. // Synopsis: cancel asynchronous retrieval
  200. //
  201. //----------------------------------------------------------------------------
  202. BOOL
  203. CObjectRetrievalManager::CancelAsyncRetrieval ()
  204. {
  205. SetLastError( (DWORD) E_NOTIMPL );
  206. return( FALSE );
  207. }
  208. //+---------------------------------------------------------------------------
  209. //
  210. // Member: CObjectRetrievalManager::OnRetrievalCompletion, public
  211. //
  212. // Synopsis: completion notification
  213. //
  214. //----------------------------------------------------------------------------
  215. BOOL
  216. CObjectRetrievalManager::OnRetrievalCompletion (
  217. DWORD dwCompletionCode,
  218. LPCWSTR pwszUrl,
  219. LPCSTR pszObjectOid,
  220. DWORD dwRetrievalFlags,
  221. PCRYPT_BLOB_ARRAY pObject,
  222. PFN_FREE_ENCODED_OBJECT_FUNC pfnFreeObject,
  223. LPVOID pvFreeContext,
  224. LPVOID pvVerify,
  225. LPVOID* ppvObject
  226. )
  227. {
  228. BOOL fResult = FALSE;
  229. //
  230. // If the retrieval was successfully completed, we go about getting the
  231. // appropriate return value for *ppvObject. If an OID was given then
  232. // we must use the context provider to convert the encoded bits into
  233. // a context value. Otherwise, we hand back a buffer with the encoded
  234. // bits
  235. //
  236. if ( dwCompletionCode == (DWORD)S_OK )
  237. {
  238. if ( pszObjectOid != NULL )
  239. {
  240. fResult = CallContextCreateObjectContext(
  241. pszObjectOid,
  242. dwRetrievalFlags,
  243. pObject,
  244. ppvObject
  245. );
  246. if ( fResult == TRUE )
  247. {
  248. if ( dwRetrievalFlags & CRYPT_VERIFY_CONTEXT_SIGNATURE )
  249. {
  250. fResult = ObjectContextVerifySignature(
  251. pszObjectOid,
  252. *ppvObject,
  253. (PCCERT_CONTEXT)pvVerify
  254. );
  255. }
  256. }
  257. }
  258. else
  259. {
  260. CCryptBlobArray cba( pObject, 0 );
  261. fResult = cba.GetArrayInSingleBufferEncodedForm(
  262. (PCRYPT_BLOB_ARRAY *)ppvObject
  263. );
  264. }
  265. ( *pfnFreeObject )( pszObjectOid, pObject, pvFreeContext );
  266. }
  267. //
  268. // We can now unload the providers
  269. //
  270. UnloadProviders();
  271. return( fResult );
  272. }
  273. //+---------------------------------------------------------------------------
  274. //
  275. // Member: CObjectRetrievalManager::ValidateRetrievalArguments, private
  276. //
  277. // Synopsis: validate arguments to RetrieveObjectByUrl
  278. //
  279. //----------------------------------------------------------------------------
  280. BOOL
  281. CObjectRetrievalManager::ValidateRetrievalArguments (
  282. LPCWSTR pwszUrl,
  283. LPCSTR pszObjectOid,
  284. DWORD dwRetrievalFlags,
  285. DWORD dwTimeout,
  286. LPVOID* ppvObject,
  287. HCRYPTASYNC hAsyncRetrieve,
  288. PCRYPT_CREDENTIALS pCredentials,
  289. LPVOID pvVerify,
  290. PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
  291. )
  292. {
  293. //
  294. // Assume badness :-)
  295. //
  296. SetLastError( (DWORD) E_INVALIDARG );
  297. //
  298. // Must have an URL
  299. //
  300. // It is possible that this will be ok in the async case
  301. // and the URLs will be parameters on the HCRYPTASYNC
  302. //
  303. if ( pwszUrl == NULL )
  304. {
  305. return( FALSE );
  306. }
  307. //
  308. // NOTENOTE: For now we fail async support and I know that I have
  309. // other async flag checks below, they are there as a
  310. // reminder :-)
  311. //
  312. if ( dwRetrievalFlags & CRYPT_ASYNC_RETRIEVAL )
  313. {
  314. return( FALSE );
  315. }
  316. //
  317. // If we retrieve from the cache then we can't be async
  318. //
  319. if ( ( dwRetrievalFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) &&
  320. ( dwRetrievalFlags & CRYPT_ASYNC_RETRIEVAL ) )
  321. {
  322. return( FALSE );
  323. }
  324. //
  325. // If we retrieve from the wire we can't be only retrieving from the
  326. // cache
  327. //
  328. if ( ( dwRetrievalFlags & CRYPT_WIRE_ONLY_RETRIEVAL ) &&
  329. ( dwRetrievalFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) )
  330. {
  331. return( FALSE );
  332. }
  333. //
  334. // If we are retrieving async we must have an async handle
  335. //
  336. if ( ( dwRetrievalFlags & CRYPT_ASYNC_RETRIEVAL ) &&
  337. ( hAsyncRetrieve == NULL ) )
  338. {
  339. return( FALSE );
  340. }
  341. //
  342. // This is a temporary check since CRYPT_VERIFY_DATA_HASH is not
  343. // yet implemented
  344. //
  345. if ( dwRetrievalFlags & CRYPT_VERIFY_DATA_HASH )
  346. {
  347. SetLastError( (DWORD) E_NOTIMPL );
  348. return( FALSE );
  349. }
  350. //
  351. // We can't have both CRYPT_VERIFY_CONTEXT_SIGNATURE and
  352. // CRYPT_VERIFY_DATA_HASH set
  353. //
  354. if ( ( dwRetrievalFlags &
  355. ( CRYPT_VERIFY_CONTEXT_SIGNATURE | CRYPT_VERIFY_DATA_HASH ) ) ==
  356. ( CRYPT_VERIFY_CONTEXT_SIGNATURE | CRYPT_VERIFY_DATA_HASH ) )
  357. {
  358. return( FALSE );
  359. }
  360. //
  361. // If either of the above is set, then pvVerify should be non NULL and
  362. // CRYPT_RETRIEVE_MULTIPLE_OBJECTS should not be set
  363. //
  364. if ( ( dwRetrievalFlags &
  365. ( CRYPT_VERIFY_CONTEXT_SIGNATURE | CRYPT_VERIFY_DATA_HASH ) ) &&
  366. ( ( pvVerify == NULL ) ||
  367. ( dwRetrievalFlags & CRYPT_RETRIEVE_MULTIPLE_OBJECTS ) ) )
  368. {
  369. return( FALSE );
  370. }
  371. //
  372. // We must have an out parameter
  373. //
  374. if ( ppvObject == NULL )
  375. {
  376. return( FALSE );
  377. }
  378. SetLastError( 0 );
  379. return( TRUE );
  380. }
  381. //+---------------------------------------------------------------------------
  382. //
  383. // Member: CObjectRetrievalManager::LoadProviders, private
  384. //
  385. // Synopsis: load scheme and context providers based on URL and OID resp.
  386. //
  387. //----------------------------------------------------------------------------
  388. BOOL
  389. CObjectRetrievalManager::LoadProviders (
  390. LPCWSTR pwszUrl,
  391. LPCSTR pszObjectOid
  392. )
  393. {
  394. WCHAR pwszScheme[INTERNET_MAX_SCHEME_LENGTH+1];
  395. DWORD cchScheme = INTERNET_MAX_SCHEME_LENGTH;
  396. CHAR pszScheme[INTERNET_MAX_SCHEME_LENGTH+1];
  397. HRESULT hr = E_UNEXPECTED;
  398. //
  399. // Get the scheme
  400. //
  401. __try
  402. {
  403. hr = UrlGetPartW(
  404. pwszUrl,
  405. pwszScheme,
  406. &cchScheme,
  407. URL_PART_SCHEME,
  408. 0 // dwFlags
  409. );
  410. }
  411. __except(EXCEPTION_EXECUTE_HANDLER)
  412. {
  413. hr = E_UNEXPECTED;
  414. }
  415. if (S_OK != hr || 0 == cchScheme)
  416. {
  417. LPWSTR pwsz;
  418. DWORD cch;
  419. pwsz = wcschr( pwszUrl, L':' );
  420. if ( pwsz != NULL )
  421. {
  422. cch = (DWORD)(pwsz - pwszUrl);
  423. if ( cch > INTERNET_MAX_SCHEME_LENGTH )
  424. {
  425. return( FALSE );
  426. }
  427. memcpy( pwszScheme, pwszUrl, cch * sizeof(WCHAR) );
  428. pwszScheme[cch] = L'\0';
  429. }
  430. else
  431. {
  432. wcscpy( pwszScheme, L"file" );
  433. }
  434. }
  435. if (!WideCharToMultiByte(
  436. CP_ACP,
  437. 0,
  438. pwszScheme,
  439. -1,
  440. pszScheme,
  441. sizeof(pszScheme) - 1,
  442. NULL,
  443. NULL
  444. ))
  445. {
  446. return( FALSE );
  447. }
  448. //
  449. // Use the scheme to load the appropriate scheme provider
  450. //
  451. if ( CryptGetOIDFunctionAddress(
  452. hSchemeRetrieveFuncSet,
  453. X509_ASN_ENCODING,
  454. pszScheme,
  455. 0,
  456. (LPVOID *)&m_pfnSchemeRetrieve,
  457. &m_hSchemeRetrieve
  458. ) == FALSE )
  459. {
  460. return( FALSE );
  461. }
  462. //
  463. // Load the appropriate context provider using the object oid
  464. //
  465. if ( pszObjectOid != NULL )
  466. {
  467. if ( CryptGetOIDFunctionAddress(
  468. hContextCreateFuncSet,
  469. X509_ASN_ENCODING,
  470. pszObjectOid,
  471. 0,
  472. (LPVOID *)&m_pfnContextCreate,
  473. &m_hContextCreate
  474. ) == FALSE )
  475. {
  476. return( FALSE );
  477. }
  478. }
  479. return( TRUE );
  480. }
  481. //+---------------------------------------------------------------------------
  482. //
  483. // Member: CObjectRetrievalManager::UnloadProviders, private
  484. //
  485. // Synopsis: unload scheme and context providers
  486. //
  487. //----------------------------------------------------------------------------
  488. VOID
  489. CObjectRetrievalManager::UnloadProviders ()
  490. {
  491. if ( m_hSchemeRetrieve != NULL )
  492. {
  493. CryptFreeOIDFunctionAddress( m_hSchemeRetrieve, 0 );
  494. m_hSchemeRetrieve = NULL;
  495. }
  496. if ( m_hContextCreate != NULL )
  497. {
  498. CryptFreeOIDFunctionAddress( m_hContextCreate, 0 );
  499. m_hContextCreate = NULL;
  500. }
  501. }
  502. //+---------------------------------------------------------------------------
  503. //
  504. // Member: CObjectRetrievalManager::CallSchemeRetrieveObjectByUrl, private
  505. //
  506. // Synopsis: Call the scheme provider RetrieveObjectByUrl entry point
  507. //
  508. //----------------------------------------------------------------------------
  509. BOOL
  510. CObjectRetrievalManager::CallSchemeRetrieveObjectByUrl (
  511. LPCWSTR pwszUrl,
  512. LPCSTR pszObjectOid,
  513. DWORD dwRetrievalFlags,
  514. DWORD dwTimeout,
  515. PCRYPT_BLOB_ARRAY pObject,
  516. PFN_FREE_ENCODED_OBJECT_FUNC* ppfnFreeObject,
  517. LPVOID* ppvFreeContext,
  518. HCRYPTASYNC hAsyncRetrieve,
  519. PCRYPT_CREDENTIALS pCredentials,
  520. PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
  521. )
  522. {
  523. return( ( *m_pfnSchemeRetrieve ) (
  524. pwszUrl,
  525. pszObjectOid,
  526. dwRetrievalFlags,
  527. dwTimeout,
  528. pObject,
  529. ppfnFreeObject,
  530. ppvFreeContext,
  531. hAsyncRetrieve,
  532. pCredentials,
  533. pAuxInfo
  534. ) );
  535. }
  536. //+---------------------------------------------------------------------------
  537. //
  538. // Member: CObjectRetrievalManager::CallContextCreateObjectContext, private
  539. //
  540. // Synopsis: call the context provider CreateObjectContext entry point
  541. //
  542. //----------------------------------------------------------------------------
  543. BOOL
  544. CObjectRetrievalManager::CallContextCreateObjectContext (
  545. LPCSTR pszObjectOid,
  546. DWORD dwRetrievalFlags,
  547. PCRYPT_BLOB_ARRAY pObject,
  548. LPVOID* ppvContext
  549. )
  550. {
  551. return( ( *m_pfnContextCreate ) (
  552. pszObjectOid,
  553. dwRetrievalFlags,
  554. pObject,
  555. ppvContext
  556. ) );
  557. }