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.

584 lines
13 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. capiutil.cxx
  5. Abstract:
  6. Utility functions for dealing with IIS-CAPI integration
  7. Author:
  8. Alex Mallet (amallet) 02-Dec-1997
  9. --*/
  10. #include "tcpdllp.hxx"
  11. #pragma hdrstop
  12. #include <dbgutil.h>
  13. #include <buffer.hxx>
  14. #include <ole2.h>
  15. #include <imd.h>
  16. #include <mb.hxx>
  17. //
  18. // Local includes
  19. //
  20. #include "iiscert.hxx"
  21. #include "capiutil.hxx"
  22. BOOL RetrieveBlobFromMetabase(MB *pMB,
  23. LPTSTR pszKey IN,
  24. PMETADATA_RECORD pMDR OUT,
  25. DWORD dwSizeHint OPTIONAL)
  26. /*++
  27. Routine Description:
  28. Tries to retrieve a value of variable length from the metabase
  29. Arguments:
  30. pMB - pointer to open MB object
  31. pszKey - key whose value is to be read
  32. pMDR - pointer to metadata record to be used when reading the value. The pbMDData member
  33. will be updated on success
  34. dwSizeHint - if caller has idea of how big value might be, can set this to number of
  35. bytes to try first retrieval call with
  36. Returns:
  37. BOOL indicating whether value was read successfully
  38. --*/
  39. {
  40. BOOL fSuccess = FALSE;
  41. //
  42. // If caller has a clue, let's use it
  43. //
  44. if ( dwSizeHint )
  45. {
  46. pMDR->pbMDData = new UCHAR[dwSizeHint];
  47. if ( !(pMDR->pbMDData) )
  48. {
  49. SetLastError(ERROR_OUTOFMEMORY);
  50. return FALSE;
  51. }
  52. }
  53. pMDR->dwMDDataLen = (dwSizeHint ? dwSizeHint : 0);
  54. fSuccess = pMB->GetData( pszKey,
  55. pMDR->dwMDIdentifier,
  56. pMDR->dwMDUserType,
  57. pMDR->dwMDDataType,
  58. (VOID *) pMDR->pbMDData,
  59. &(pMDR->dwMDDataLen),
  60. pMDR->dwMDAttributes );
  61. if ( !fSuccess )
  62. {
  63. //
  64. // If buffer wasn't big enough, let's try again ...
  65. //
  66. if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  67. {
  68. //
  69. // We were brought up well, so we'll clean stuff up
  70. //
  71. if ( dwSizeHint )
  72. {
  73. delete [] pMDR->pbMDData;
  74. }
  75. pMDR->pbMDData = new UCHAR[pMDR->dwMDDataLen];
  76. if ( !(pMDR->pbMDData) )
  77. {
  78. SetLastError(ERROR_OUTOFMEMORY);
  79. return FALSE;
  80. }
  81. fSuccess = pMB->GetData( pszKey,
  82. pMDR->dwMDIdentifier,
  83. pMDR->dwMDUserType,
  84. pMDR->dwMDDataType,
  85. (VOID *) pMDR->pbMDData,
  86. &(pMDR->dwMDDataLen),
  87. pMDR->dwMDAttributes );
  88. if ( !fSuccess )
  89. {
  90. //ah, sod it, can't do anymore
  91. delete [] pMDR->pbMDData;
  92. return FALSE;
  93. }
  94. }
  95. }
  96. if ( !fSuccess )
  97. {
  98. DBGPRINTF((DBG_CONTEXT,
  99. "RetrieveBlobFromMB failed, 0x%x\n", GetLastError()));
  100. }
  101. return fSuccess;
  102. } //RetrieveBlobFromMetabase
  103. BOOL CopyString( OUT LPTSTR *ppszDest,
  104. IN LPTSTR pszSrc )
  105. /*++
  106. Routine Description:
  107. String-copy that uses "new" for memory allocation
  108. Arguments:
  109. ppszDest - pointer to pointer to dest string
  110. pszSrc - pointer to source string
  111. --*/
  112. {
  113. if ( !pszSrc )
  114. {
  115. *ppszDest = NULL;
  116. return TRUE;
  117. }
  118. *ppszDest = new char[strlen(pszSrc) + 1];
  119. if ( !*ppszDest )
  120. {
  121. SetLastError( ERROR_OUTOFMEMORY );
  122. return FALSE;
  123. }
  124. memcpy( *ppszDest, pszSrc, strlen(pszSrc) + 1 );
  125. return TRUE;
  126. }
  127. OPEN_CERT_STORE_INFO* ReadCertStoreInfoFromMB( IN IMDCOM *pMDObject,
  128. IN LPTSTR pszMBPath,
  129. IN BOOL fCTL )
  130. /*++
  131. Routine Description:
  132. Read all the information necessary to open a CAPI store out of the metabase
  133. Arguments:
  134. pMDObject - pointer to metabase object
  135. pszMBPath - full path in metabase where cert store info is stored, starting from /
  136. fCTL - bool indicating whether info is to be used to reconstruct a CTL or a cert
  137. Returns:
  138. Pointer to filled out OPEN_CERT_STORE_INFO structure on success, NULL on failure.
  139. Note that only some of the OPEN_CERT_STORE_INFO fields are -required-; currently,
  140. only the store name is required.
  141. --*/
  142. {
  143. DBG_ASSERT( pMDObject );
  144. DBG_ASSERT( pszMBPath );
  145. MB mb( pMDObject );
  146. BOOL fSuccess = FALSE;
  147. OPEN_CERT_STORE_INFO *pCertStoreInfo = NULL;
  148. pCertStoreInfo = AllocateCertStoreInfo();
  149. if ( !pCertStoreInfo )
  150. {
  151. return NULL;
  152. }
  153. //
  154. // Try to open the key for reading
  155. //
  156. if ( mb.Open( pszMBPath,
  157. METADATA_PERMISSION_READ ))
  158. {
  159. DWORD dwReqDataLen = 0;
  160. METADATA_RECORD mdr;
  161. //
  162. //Try to retrieve container
  163. //
  164. MD_SET_DATA_RECORD(&mdr,
  165. (fCTL ? MD_SSL_CTL_CONTAINER : MD_SSL_CERT_CONTAINER),
  166. METADATA_NO_ATTRIBUTES,
  167. IIS_MD_UT_SERVER, STRING_METADATA,
  168. NULL,
  169. 0);
  170. if ( RetrieveBlobFromMetabase(&mb,
  171. NULL,
  172. &mdr) )
  173. {
  174. //
  175. // Metabase will return empty string if NULL string is stored
  176. //
  177. if ( !strcmp( (LPTSTR) mdr.pbMDData, TEXT("")) )
  178. {
  179. delete [] mdr.pbMDData;
  180. pCertStoreInfo->pszContainer = NULL;
  181. }
  182. else
  183. {
  184. pCertStoreInfo->pszContainer = (LPTSTR) mdr.pbMDData;
  185. }
  186. }
  187. //
  188. //Try to retrieve cert provider
  189. //
  190. MD_SET_DATA_RECORD(&mdr,
  191. (fCTL ? MD_SSL_CTL_PROVIDER : MD_SSL_CERT_PROVIDER),
  192. METADATA_NO_ATTRIBUTES,
  193. IIS_MD_UT_SERVER, STRING_METADATA,
  194. NULL,
  195. 0);
  196. if ( RetrieveBlobFromMetabase(&mb,
  197. NULL,
  198. &mdr) )
  199. {
  200. //
  201. // Metabase will return empty string if NULL string is stored
  202. //
  203. if ( !strcmp( (LPTSTR) mdr.pbMDData, TEXT("")) )
  204. {
  205. delete [] mdr.pbMDData;
  206. pCertStoreInfo->pszProvider = NULL;
  207. }
  208. else
  209. {
  210. pCertStoreInfo->pszProvider = (LPTSTR) mdr.pbMDData;
  211. }
  212. }
  213. //
  214. //Try to retrieve provider type
  215. //
  216. mb.GetDword( NULL,
  217. (fCTL ? MD_SSL_CTL_PROVIDER_TYPE : MD_SSL_CERT_PROVIDER_TYPE),
  218. IIS_MD_UT_SERVER,
  219. &(pCertStoreInfo->dwProvType),
  220. METADATA_NO_ATTRIBUTES );
  221. //
  222. //Retrieve open flags
  223. //
  224. mb.GetDword( NULL,
  225. (fCTL ? MD_SSL_CTL_OPEN_FLAGS : MD_SSL_CERT_OPEN_FLAGS),
  226. IIS_MD_UT_SERVER,
  227. &(pCertStoreInfo->dwFlags),
  228. METADATA_NO_ATTRIBUTES ) ;
  229. //
  230. //Try to retrieve store name
  231. //
  232. MD_SET_DATA_RECORD(&mdr,
  233. (fCTL ? MD_SSL_CTL_STORE_NAME : MD_SSL_CERT_STORE_NAME),
  234. METADATA_NO_ATTRIBUTES,
  235. IIS_MD_UT_SERVER, STRING_METADATA,
  236. NULL,
  237. 0);
  238. if ( !RetrieveBlobFromMetabase(&mb,
  239. NULL,
  240. &mdr) )
  241. {
  242. goto EndReadStoreInfo;
  243. }
  244. else
  245. {
  246. //
  247. // Metabase will return empty string if NULL string is stored, but
  248. // empty name is -NOT- valid !
  249. //
  250. if ( !strcmp( (LPTSTR) mdr.pbMDData, TEXT("")) )
  251. {
  252. delete [] mdr.pbMDData;
  253. goto EndReadStoreInfo;
  254. }
  255. else
  256. {
  257. pCertStoreInfo->pszStoreName = (LPTSTR) mdr.pbMDData;
  258. }
  259. }
  260. //
  261. // Everything succeeded
  262. //
  263. fSuccess = TRUE;
  264. }
  265. EndReadStoreInfo:
  266. if ( !fSuccess )
  267. {
  268. DeallocateCertStoreInfo( pCertStoreInfo );
  269. pCertStoreInfo = NULL;
  270. }
  271. return ( pCertStoreInfo );
  272. }
  273. OPEN_CERT_STORE_INFO* AllocateCertStoreInfo()
  274. /*++
  275. Routine Description:
  276. Allocate and initialize the structure used to hold info about cert stores
  277. Arguments:
  278. None
  279. Returns:
  280. Allocated and initialized structure that should be cleaned up with a call to
  281. DeallocateCertStoreInfo()
  282. --*/
  283. {
  284. OPEN_CERT_STORE_INFO *pStoreInfo = new OPEN_CERT_STORE_INFO;
  285. if ( pStoreInfo )
  286. {
  287. memset(pStoreInfo, 0, sizeof(OPEN_CERT_STORE_INFO));
  288. }
  289. return pStoreInfo;
  290. }
  291. VOID DeallocateCertStoreInfo( OPEN_CERT_STORE_INFO *pInfo )
  292. /*++
  293. Routine Description:
  294. Clean up the structure used to track information about a cert store
  295. Arguments:
  296. pInfo - pointer to OPEN_CERT_STORE_INFO structure to be cleaned up
  297. Returns:
  298. Nothing
  299. --*/
  300. {
  301. if ( !pInfo )
  302. {
  303. return ;
  304. }
  305. if ( pInfo->pszContainer )
  306. {
  307. delete [] pInfo->pszContainer;
  308. pInfo->pszContainer = NULL;
  309. }
  310. if ( pInfo->pszProvider )
  311. {
  312. delete pInfo->pszProvider;
  313. pInfo->pszProvider = NULL;
  314. }
  315. if ( pInfo->pszStoreName )
  316. {
  317. delete [] pInfo->pszStoreName;
  318. pInfo->pszStoreName = NULL;
  319. }
  320. if ( pInfo->hCertStore )
  321. {
  322. CertCloseStore( pInfo->hCertStore,
  323. 0 );
  324. pInfo->hCertStore = NULL;
  325. }
  326. delete pInfo;
  327. }
  328. BOOL
  329. DuplicateCertStoreInfo( OUT OPEN_CERT_STORE_INFO **ppDestStoreInfo,
  330. IN OPEN_CERT_STORE_INFO *pSrcStoreInfo )
  331. /*++
  332. Routine Description:
  333. Make a copy of cert store info
  334. Arguments:
  335. ppDestStoreInfo - pointer to where copy of pSrcStoreInfo is to be placed
  336. pSrcStoreInfo - information to be copied
  337. Returns:
  338. TRUE if copy was successful, FALSE if not
  339. --*/
  340. {
  341. *ppDestStoreInfo = NULL;
  342. OPEN_CERT_STORE_INFO *pNewStore = AllocateCertStoreInfo();
  343. if ( !pNewStore )
  344. {
  345. SetLastError( ERROR_OUTOFMEMORY);
  346. return (FALSE);
  347. }
  348. //
  349. // Copy the relevant items
  350. //
  351. if ( pSrcStoreInfo->pszContainer &&
  352. !CopyString( &pNewStore->pszContainer,
  353. pSrcStoreInfo->pszContainer ) )
  354. {
  355. goto EndDuplicateInfo;
  356. }
  357. if ( pSrcStoreInfo->pszProvider &&
  358. !CopyString( &pNewStore->pszProvider,
  359. pSrcStoreInfo->pszProvider ) )
  360. {
  361. goto EndDuplicateInfo;
  362. }
  363. //
  364. // Store name -cannot- be NULL
  365. //
  366. if ( !pSrcStoreInfo->pszStoreName )
  367. {
  368. DBGPRINTF((DBG_CONTEXT,
  369. "Null store name !\n"));
  370. goto EndDuplicateInfo;
  371. }
  372. else if ( !CopyString( &pNewStore->pszStoreName,
  373. pSrcStoreInfo->pszStoreName ) )
  374. {
  375. goto EndDuplicateInfo;
  376. }
  377. pNewStore->dwFlags = pSrcStoreInfo->dwFlags;
  378. pNewStore->dwProvType = pSrcStoreInfo->dwProvType;
  379. //
  380. // Duplicate the handle to the store
  381. //
  382. if ( !( pNewStore->hCertStore = CertDuplicateStore(pSrcStoreInfo->hCertStore) ))
  383. {
  384. goto EndDuplicateInfo;
  385. }
  386. //
  387. // Everything is happy, fill in the pointer
  388. //
  389. *ppDestStoreInfo = pNewStore;
  390. EndDuplicateInfo:
  391. if ( !(*ppDestStoreInfo) )
  392. {
  393. DeallocateCertStoreInfo( pNewStore );
  394. return FALSE;
  395. }
  396. else
  397. {
  398. return TRUE;
  399. }
  400. }
  401. BOOL ServerAddressHasCAPIInfo( IN MB *pMB,
  402. IN LPTSTR pszCredPath,
  403. IN DWORD *adwProperties,
  404. IN DWORD cProperties )
  405. /*++
  406. Routine Description:
  407. Checks whether the given MB path has info associated with it necessary to
  408. reconstruct a particular CAPI structure eg certificate context, CTL context
  409. Arguments:
  410. pMB - pointer to metabase object open for reading
  411. pszCredPath - path to where CAPI info would be stored, relative to pMB object
  412. adwProperties - array of metabase properties that must exist and be readable for the
  413. given CAPI object
  414. cProperties - number of elements in pdwProperties array [ = 2 * # of properties]
  415. Returns:
  416. TRUE if cert info exists, FALSE if not
  417. --*/
  418. {
  419. DBG_ASSERT( pMB );
  420. DBG_ASSERT( pszCredPath );
  421. BOOL fAllocated = FALSE;
  422. BOOL fAllData = TRUE;
  423. //
  424. // Iterate through each property, trying to retrieve it with a buffer size of zero;
  425. // If retrieving a property fails for any reason other than a buffer that's too
  426. // small, assume the property doesn't exist
  427. //
  428. for (DWORD i = 0; i < cProperties/2; i++)
  429. {
  430. DWORD dwSize = 0;
  431. pMB->GetData( pszCredPath,
  432. adwProperties[2*i],
  433. IIS_MD_UT_SERVER,
  434. adwProperties[2*i + 1],
  435. NULL,
  436. &dwSize,
  437. METADATA_NO_ATTRIBUTES );
  438. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  439. {
  440. fAllData = FALSE;
  441. break;
  442. }
  443. }
  444. return fAllData;
  445. }