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.

1351 lines
36 KiB

  1. ////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997 Microsoft Corporation
  4. //
  5. // Module Name: certmap.cpp
  6. //
  7. // Abstract: IIS privider cert mapper object methods
  8. //
  9. // Author: Philippe Choquier (phillich) 10-Apr-1997
  10. //
  11. // History: Zeyong Xu borrowed the source code from ADSI object
  12. // (created by Philippe Choquier at 10-Apr-1997) at 20-Oct-1999
  13. //
  14. ///////////////////////////////////////////////////
  15. #include "iisprov.h"
  16. #include "certmap.h"
  17. const DWORD MAX_CERT_KEY_LEN = METADATA_MAX_NAME_LEN + 1;
  18. const DWORD SHA1_HASH_SIZE = 20;
  19. //
  20. // CCertMapperMethod
  21. //
  22. CCertMapperMethod::CCertMapperMethod(LPCWSTR pszMetabasePathIn)
  23. {
  24. DBG_ASSERT(pszMetabasePathIn != NULL);
  25. m_hmd = NULL;
  26. HRESULT hr = CoCreateInstance(
  27. CLSID_MSAdminBase,
  28. NULL,
  29. CLSCTX_ALL,
  30. IID_IMSAdminBase,
  31. (void**)&m_pIABase
  32. );
  33. THROW_ON_ERROR(hr);
  34. hr = Init(pszMetabasePathIn);
  35. THROW_ON_ERROR(hr);
  36. }
  37. CCertMapperMethod::~CCertMapperMethod()
  38. {
  39. if ( m_pszMetabasePath )
  40. {
  41. free( m_pszMetabasePath );
  42. }
  43. if(m_pIABase)
  44. m_pIABase->Release();
  45. }
  46. HRESULT
  47. GetCertificateHashString(
  48. PBYTE pbCert,
  49. DWORD cbCert,
  50. WCHAR *pwszCertHash,
  51. DWORD cchCertHashBuffer)
  52. /*++
  53. Routine Description:
  54. verifies validity of cert blob by creating cert context
  55. and retrieves SHA1 hash and converts it to WCHAR *
  56. Arguments:
  57. pbCert - X.509 certificate blob
  58. cbCert - size of the cert blob in bytes
  59. pwszCertHash - buffer must be big enough to fit SHA1 hash in hex string form
  60. (2 * SHA1_HASH_SIZE + terminating 0 )
  61. cchCertHashBuffer - size of the CertHash buffer in WCHARs (includes trminating string)
  62. Returns:
  63. HRESULT
  64. --*/
  65. {
  66. HRESULT hr = E_FAIL;
  67. BYTE rgbHash[ SHA1_HASH_SIZE ];
  68. DWORD cbSize = SHA1_HASH_SIZE;
  69. #ifndef HEX_DIGIT
  70. #define HEX_DIGIT( nDigit ) \
  71. (WCHAR)((nDigit) > 9 ? \
  72. (nDigit) - 10 + L'a' \
  73. : (nDigit) + L'0')
  74. #endif
  75. PCCERT_CONTEXT pCertContext = NULL;
  76. pCertContext = CertCreateCertificateContext(
  77. X509_ASN_ENCODING,
  78. (const BYTE *)pbCert,
  79. cbCert );
  80. if ( pCertContext == NULL )
  81. {
  82. hr = HRESULT_FROM_WIN32( GetLastError() );
  83. return hr;
  84. }
  85. //
  86. // get hash of the certificate to be verified
  87. //
  88. if ( !CertGetCertificateContextProperty( pCertContext,
  89. CERT_SHA1_HASH_PROP_ID,
  90. rgbHash,
  91. &cbSize ) )
  92. {
  93. hr = HRESULT_FROM_WIN32( GetLastError() );
  94. CertFreeCertificateContext( pCertContext );
  95. pCertContext = NULL;
  96. return hr;
  97. }
  98. CertFreeCertificateContext( pCertContext );
  99. pCertContext = NULL;
  100. if ( cchCertHashBuffer < SHA1_HASH_SIZE * 2 + 1 )
  101. {
  102. // we don't have big enough buffer to store
  103. // hex string of the SHA1 hash each byte takes 2 chars + terminating 0
  104. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  105. return hr;
  106. }
  107. //
  108. // convert to text
  109. //
  110. for (int i = 0; i < sizeof(rgbHash); i ++ )
  111. {
  112. *(pwszCertHash++) = HEX_DIGIT( ( rgbHash[ i ] >> 4 ) );
  113. *(pwszCertHash++) = HEX_DIGIT( ( rgbHash[ i ] & 0x0F ) );
  114. }
  115. *(pwszCertHash) = L'\0';
  116. #undef HEX_DIGIT
  117. return S_OK;
  118. }
  119. //
  120. // CreateMapping(): Create a mapping entry
  121. //
  122. // Arguments:
  123. //
  124. // vCert - X.509 certificate
  125. // bstrNtAcct - NT acct to map to
  126. // bstrNtPwd - NT pwd
  127. // bstrName - friendly name for mapping entry
  128. // lEnabled - 1 to enable mapping entry, 0 to disable it
  129. //
  130. HRESULT
  131. CCertMapperMethod::CreateMapping(
  132. VARIANT vCert,
  133. BSTR bstrNtAcct,
  134. BSTR bstrNtPwd,
  135. BSTR bstrName,
  136. LONG lEnabled
  137. )
  138. {
  139. HRESULT hr;
  140. LPBYTE pbCert = NULL;
  141. DWORD cbCert;
  142. LPBYTE pRes;
  143. DWORD cRes;
  144. VARIANT vOldAcct;
  145. VARIANT vOldCert;
  146. VARIANT vOldPwd;
  147. VARIANT vOldName;
  148. VARIANT vOldEnabledFlag;
  149. PCCERT_CONTEXT pcCert = NULL;
  150. WCHAR wszCertHash[ 2*SHA1_HASH_SIZE + 1];
  151. BOOL fFoundExisting = FALSE;
  152. //
  153. // Do some sanity checks on the cert
  154. //
  155. if ( SUCCEEDED( hr = GetBlobFromVariant( &vCert,
  156. &pbCert,
  157. &cbCert ) ) )
  158. {
  159. //
  160. // verify validity of certificate blob
  161. // and retrieve certificate hash
  162. //
  163. if ( FAILED( hr = GetCertificateHashString(
  164. pbCert,
  165. cbCert,
  166. wszCertHash,
  167. sizeof( wszCertHash )/sizeof( WCHAR ) ) ) )
  168. {
  169. DBGPRINTF((DBG_CONTEXT,
  170. "Invalid cert passed to CreateMapping() 0x%x\n", hr));
  171. //
  172. // If the decoding fails, GetLastError() returns an ASN1 decoding
  173. // error that is obtained by subtracting CRYPT_E_OSS_ERROR from the returned
  174. // error and looking in file asn1code.h for the actual error. To avoid the
  175. // cryptic ASN1 errors, we'll just return a general "invalid arg" error
  176. //
  177. goto Exit;
  178. }
  179. }
  180. else
  181. {
  182. goto Exit;
  183. }
  184. //
  185. // check if we already have a mapping for this cert; if we do, we'll replace that mapping
  186. // with the new one
  187. //
  188. WCHAR achIndex[MAX_CERT_KEY_LEN];
  189. if ( SUCCEEDED( hr = OpenMd( L"Cert11/Mappings",
  190. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  191. {
  192. if ( SUCCEEDED(hr = Locate( IISMAPPER_LOCATE_BY_CERT,
  193. vCert,
  194. achIndex )) )
  195. {
  196. fFoundExisting = TRUE;
  197. DBGPRINTF((DBG_CONTEXT,
  198. "Replacing old 1-1 cert mapping with new mapping\n"));
  199. if ( FAILED( hr = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA,
  200. sizeof(DWORD), (LPBYTE)&lEnabled ) ) ||
  201. FAILED( hr = SetMdData( achIndex, MD_MAPNAME, STRING_METADATA,
  202. sizeof(WCHAR) * (SysStringLen(bstrName) + 1 ),
  203. (LPBYTE)bstrName ) ) ||
  204. FAILED( hr = SetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA,
  205. sizeof(WCHAR) * (SysStringLen(bstrNtPwd) + 1 ),
  206. (LPBYTE)bstrNtPwd ) ) ||
  207. FAILED( hr = SetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA,
  208. sizeof(WCHAR) * (SysStringLen(bstrNtAcct) + 1 ),
  209. (LPBYTE)bstrNtAcct ) ) ||
  210. FAILED( hr = SetMdData( achIndex, MD_MAPCERT, BINARY_METADATA,
  211. cbCert, (LPBYTE)pbCert ) ) )
  212. {
  213. //NOP - Something failed
  214. }
  215. }
  216. CloseMd( SUCCEEDED( hr ) );
  217. }
  218. //
  219. // New mapping
  220. //
  221. if ( !fFoundExisting )
  222. {
  223. //
  224. // check mapping exists, create if not
  225. //
  226. hr = OpenMd( L"Cert11/Mappings", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
  227. if ( hr == RETURNCODETOHRESULT( ERROR_PATH_NOT_FOUND ) )
  228. {
  229. if ( SUCCEEDED( hr = OpenMd( L"",
  230. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  231. {
  232. hr = CreateMdObject( L"Cert11/Mappings" );
  233. CloseMd( FALSE );
  234. // Reopen to the correct node.
  235. hr = OpenMd( L"Cert11/Mappings", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
  236. }
  237. }
  238. if ( FAILED( hr ) )
  239. {
  240. goto Exit;
  241. }
  242. //
  243. // adding the new mapping under it's CertHash node
  244. //
  245. if ( SUCCEEDED( hr = CreateMdObject( wszCertHash ) ) )
  246. {
  247. if ( FAILED( hr = SetMdData( wszCertHash, MD_MAPENABLED, DWORD_METADATA,
  248. sizeof(DWORD), (LPBYTE)&lEnabled ) ) ||
  249. FAILED( hr = SetMdData( wszCertHash, MD_MAPNAME, STRING_METADATA,
  250. sizeof(WCHAR) * (SysStringLen(bstrName) + 1 ),
  251. (LPBYTE)bstrName ) ) ||
  252. FAILED( hr = SetMdData( wszCertHash, MD_MAPNTPWD, STRING_METADATA,
  253. sizeof(WCHAR) * (SysStringLen(bstrNtPwd) + 1 ),
  254. (LPBYTE)bstrNtPwd ) ) ||
  255. FAILED( hr = SetMdData( wszCertHash, MD_MAPNTACCT, STRING_METADATA,
  256. sizeof(WCHAR) * (SysStringLen(bstrNtAcct) + 1 ),
  257. (LPBYTE)bstrNtAcct ) ) ||
  258. FAILED( hr = SetMdData( wszCertHash, MD_MAPCERT, BINARY_METADATA,
  259. cbCert, (LPBYTE)pbCert ) ) )
  260. {
  261. }
  262. }
  263. }
  264. Exit:
  265. if( pbCert != NULL )
  266. {
  267. free( pbCert );
  268. pbCert = NULL;
  269. }
  270. CloseMd( SUCCEEDED( hr ) );
  271. return hr;
  272. }
  273. //
  274. // GetMapping: Get a mapping entry using key
  275. //
  276. // Arguments:
  277. //
  278. // lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
  279. // vKey - key to use to locate mapping
  280. // pvCert - X.509 certificate
  281. // pbstrNtAcct - NT acct to map to
  282. // pbstrNtPwd - NT pwd
  283. // pbstrName - friendly name for mapping entry
  284. // plEnabled - 1 to enable mapping entry, 0 to disable it
  285. //
  286. HRESULT
  287. CCertMapperMethod::GetMapping(
  288. LONG lMethod,
  289. VARIANT vKey,
  290. VARIANT* pvCert,
  291. VARIANT* pbstrNtAcct,
  292. VARIANT* pbstrNtPwd,
  293. VARIANT* pbstrName,
  294. VARIANT* plEnabled
  295. )
  296. {
  297. WCHAR achIndex[MAX_CERT_KEY_LEN];
  298. HRESULT hr;
  299. DWORD dwLen;
  300. LPBYTE pbData = NULL;
  301. VariantInit( pvCert );
  302. VariantInit( pbstrNtAcct );
  303. VariantInit( pbstrNtPwd );
  304. VariantInit( pbstrName );
  305. VariantInit( plEnabled );
  306. if ( SUCCEEDED( hr = OpenMd( L"Cert11/Mappings",
  307. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  308. {
  309. if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
  310. {
  311. if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPCERT, BINARY_METADATA, &dwLen,
  312. &pbData ) ) )
  313. {
  314. if ( FAILED( hr = SetVariantAsByteArray( pvCert, dwLen, pbData ) ) )
  315. {
  316. goto Done;
  317. }
  318. free( pbData );
  319. pbData = NULL;
  320. }
  321. else
  322. {
  323. if ( hr != MD_ERROR_DATA_NOT_FOUND ||
  324. FAILED( hr = SetVariantAsByteArray( pvCert, 0, (PBYTE)"" ) ) )
  325. {
  326. goto Done;
  327. }
  328. }
  329. if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA, &dwLen,
  330. &pbData ) ) )
  331. {
  332. if ( FAILED( hr = SetVariantAsBSTR( pbstrNtAcct, dwLen, pbData ) ) )
  333. {
  334. goto Done;
  335. }
  336. free( pbData );
  337. pbData = NULL;
  338. }
  339. else
  340. {
  341. if ( hr != MD_ERROR_DATA_NOT_FOUND ||
  342. FAILED ( hr = SetVariantAsBSTR( pbstrNtAcct,
  343. sizeof(L""), (LPBYTE)L"" ) ) )
  344. {
  345. goto Done;
  346. }
  347. }
  348. if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA, &dwLen,
  349. &pbData ) ) )
  350. {
  351. if ( FAILED( hr = SetVariantAsBSTR( pbstrNtPwd, dwLen, pbData ) ) )
  352. {
  353. goto Done;
  354. }
  355. free( pbData );
  356. pbData = NULL;
  357. }
  358. else
  359. {
  360. if ( hr != MD_ERROR_DATA_NOT_FOUND ||
  361. FAILED( hr = SetVariantAsBSTR( pbstrNtPwd,
  362. sizeof(L""), (LPBYTE)L"" ) ) )
  363. {
  364. goto Done;
  365. }
  366. }
  367. if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPNAME, STRING_METADATA, &dwLen,
  368. &pbData ) ) )
  369. {
  370. if ( FAILED( hr = SetVariantAsBSTR( pbstrName, dwLen, pbData ) ) )
  371. {
  372. goto Done;
  373. }
  374. free( pbData );
  375. pbData = NULL;
  376. }
  377. else
  378. {
  379. if ( hr != MD_ERROR_DATA_NOT_FOUND ||
  380. FAILED( hr = SetVariantAsBSTR( pbstrName, sizeof(L""), (LPBYTE)L"" ) ) )
  381. {
  382. goto Done;
  383. }
  384. }
  385. if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA, &dwLen,
  386. &pbData ) ) )
  387. {
  388. if ( FAILED( hr = SetVariantAsLong( plEnabled, *(LPDWORD)pbData ) ) )
  389. {
  390. goto Done;
  391. }
  392. free( pbData );
  393. pbData = NULL;
  394. }
  395. else
  396. {
  397. if ( hr != MD_ERROR_DATA_NOT_FOUND ||
  398. FAILED( hr = SetVariantAsLong( plEnabled, FALSE ) ) )
  399. {
  400. goto Done;
  401. }
  402. hr = S_OK;
  403. }
  404. }
  405. Done:
  406. if ( pbData != NULL )
  407. {
  408. free( pbData );
  409. pbData = NULL;
  410. }
  411. CloseMd( FALSE );
  412. }
  413. return hr;
  414. }
  415. //
  416. // Delete a mapping entry using key
  417. //
  418. HRESULT
  419. CCertMapperMethod::DeleteMapping(
  420. LONG lMethod,
  421. VARIANT vKey
  422. )
  423. {
  424. WCHAR achIndex[MAX_CERT_KEY_LEN];
  425. HRESULT hr;
  426. if ( SUCCEEDED( hr = OpenMd( L"Cert11/Mappings",
  427. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  428. {
  429. if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
  430. {
  431. hr = DeleteMdObject( achIndex );
  432. }
  433. CloseMd( TRUE );
  434. }
  435. return hr;
  436. }
  437. //
  438. // Set the enable flag on a mapping entry using key
  439. //
  440. HRESULT
  441. CCertMapperMethod::SetEnabled(
  442. LONG lMethod,
  443. VARIANT vKey,
  444. LONG lEnabled
  445. )
  446. {
  447. WCHAR achIndex[MAX_CERT_KEY_LEN];
  448. HRESULT hr;
  449. if ( SUCCEEDED( hr = OpenMd( L"Cert11/Mappings",
  450. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  451. {
  452. if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
  453. {
  454. hr = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA, sizeof(DWORD), (LPBYTE)&lEnabled );
  455. }
  456. CloseMd( SUCCEEDED( hr ) );
  457. }
  458. return hr;
  459. }
  460. //
  461. // Set the Name on a mapping entry using key
  462. //
  463. HRESULT CCertMapperMethod::SetName(
  464. LONG lMethod,
  465. VARIANT vKey,
  466. BSTR bstrName
  467. )
  468. {
  469. return SetString( lMethod, vKey, bstrName, MD_MAPNAME );
  470. }
  471. //
  472. // Set a string property on a mapping entry using key
  473. //
  474. HRESULT CCertMapperMethod::SetString(
  475. LONG lMethod,
  476. VARIANT vKey,
  477. BSTR bstrName,
  478. DWORD dwProp
  479. )
  480. {
  481. WCHAR achIndex[MAX_CERT_KEY_LEN];
  482. LPSTR pszName = NULL;
  483. HRESULT hr;
  484. DWORD dwLen;
  485. if ( SUCCEEDED( hr = OpenMd( L"Cert11/Mappings",
  486. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  487. {
  488. if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
  489. {
  490. hr = SetMdData( achIndex, dwProp, STRING_METADATA,
  491. sizeof(WCHAR) * (SysStringLen(bstrName) + 1 ),
  492. (LPBYTE)bstrName );
  493. }
  494. CloseMd( SUCCEEDED( hr ) );
  495. }
  496. return hr;
  497. }
  498. //
  499. // Set the Password on a mapping entry using key
  500. //
  501. HRESULT
  502. CCertMapperMethod::SetPwd(
  503. LONG lMethod,
  504. VARIANT vKey,
  505. BSTR bstrPwd
  506. )
  507. {
  508. return SetString( lMethod, vKey, bstrPwd, MD_MAPNTPWD );
  509. }
  510. //
  511. // Set the NT account name on a mapping entry using key
  512. //
  513. HRESULT
  514. CCertMapperMethod::SetAcct(
  515. LONG lMethod,
  516. VARIANT vKey,
  517. BSTR bstrAcct
  518. )
  519. {
  520. return SetString( lMethod, vKey, bstrAcct, MD_MAPNTACCT );
  521. }
  522. HRESULT
  523. CCertMapperMethod::OpenMd(
  524. LPWSTR pszOpenPath,
  525. DWORD dwPermission
  526. )
  527. {
  528. HRESULT hr;
  529. LPWSTR pszPath;
  530. UINT cL = wcslen( m_pszMetabasePath );
  531. pszPath = (LPWSTR)malloc( (wcslen(pszOpenPath) + 1 + cL + 1)*sizeof(WCHAR) );
  532. if ( pszPath == NULL )
  533. {
  534. return E_OUTOFMEMORY;
  535. }
  536. memcpy( pszPath, m_pszMetabasePath, cL * sizeof(WCHAR) );
  537. if ( cL && m_pszMetabasePath[cL-1] != L'/' && *pszOpenPath && *pszOpenPath != L'/' )
  538. {
  539. pszPath[cL++] = L'/';
  540. }
  541. wcscpy( pszPath + cL, pszOpenPath );
  542. hr = OpenAdminBaseKey(
  543. pszPath,
  544. dwPermission
  545. );
  546. free( pszPath );
  547. return hr;
  548. }
  549. HRESULT
  550. CCertMapperMethod::CloseMd(
  551. BOOL fSave
  552. )
  553. {
  554. CloseAdminBaseKey();
  555. m_hmd = NULL;
  556. if ( m_pIABase && fSave )
  557. {
  558. m_pIABase->SaveData();
  559. }
  560. return S_OK;
  561. }
  562. HRESULT
  563. CCertMapperMethod::DeleteMdObject(
  564. LPWSTR pszKey
  565. )
  566. {
  567. return m_pIABase->DeleteKey( m_hmd, pszKey );
  568. }
  569. HRESULT
  570. CCertMapperMethod::CreateMdObject(
  571. LPWSTR pszKey
  572. )
  573. {
  574. return m_pIABase->AddKey( m_hmd, pszKey );
  575. }
  576. HRESULT
  577. CCertMapperMethod::SetMdData(
  578. LPWSTR achIndex,
  579. DWORD dwProp,
  580. DWORD dwDataType,
  581. DWORD dwDataLen,
  582. LPBYTE pbData
  583. )
  584. {
  585. METADATA_RECORD md;
  586. md.dwMDDataLen = dwDataLen;
  587. md.dwMDDataType = dwDataType;
  588. md.dwMDIdentifier = dwProp;
  589. md.dwMDAttributes = (dwProp == MD_MAPNTPWD) ? METADATA_SECURE : 0;
  590. md.pbMDData = pbData;
  591. return m_pIABase->SetData( m_hmd, achIndex, &md );
  592. }
  593. HRESULT
  594. CCertMapperMethod::GetMdData(
  595. LPWSTR achIndex,
  596. DWORD dwProp,
  597. DWORD dwDataType,
  598. LPDWORD pdwDataLen,
  599. LPBYTE* ppbData
  600. )
  601. {
  602. HRESULT hr;
  603. METADATA_RECORD md;
  604. DWORD dwRequired;
  605. md.dwMDDataLen = 0;
  606. md.dwMDDataType = dwDataType;
  607. md.dwMDIdentifier = dwProp;
  608. md.dwMDAttributes = 0;
  609. md.pbMDData = NULL;
  610. if ( FAILED(hr = m_pIABase->GetData( m_hmd, achIndex, &md, &dwRequired )) )
  611. {
  612. if ( hr == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER) )
  613. {
  614. if ( (*ppbData = (LPBYTE)malloc(dwRequired)) == NULL )
  615. {
  616. return E_OUTOFMEMORY;
  617. }
  618. md.pbMDData = *ppbData;
  619. md.dwMDDataLen = dwRequired;
  620. hr = m_pIABase->GetData( m_hmd, achIndex, &md, &dwRequired );
  621. *pdwDataLen = md.dwMDDataLen;
  622. }
  623. }
  624. else
  625. {
  626. *pdwDataLen = 0;
  627. *ppbData = NULL;
  628. }
  629. return hr;
  630. }
  631. //
  632. // Locate a mapping entry based on key
  633. // OpenMd() must be called 1st
  634. //
  635. HRESULT
  636. CCertMapperMethod::Locate(
  637. LONG lMethod,
  638. VARIANT vKey,
  639. LPWSTR pszResKey
  640. )
  641. {
  642. HRESULT hr;
  643. PBYTE pbKeyData = NULL;
  644. DWORD cbKeyData =0;
  645. PBYTE pbCert = NULL;
  646. DWORD cbCert =0;
  647. DWORD dwProp;
  648. LPSTR pRes;
  649. DWORD cRes;
  650. BOOL fAddDelim = TRUE;
  651. VARIANT vKeyUI4;
  652. VARIANT vKeyBSTR;
  653. WCHAR achIndex[ METADATA_MAX_NAME_LEN + 1 ];
  654. DWORD dwIndex = 0;
  655. DWORD cbData = 0;
  656. PBYTE pbData = NULL;
  657. VariantInit( &vKeyUI4 );
  658. VariantInit( &vKeyBSTR );
  659. if ( lMethod == IISMAPPER_LOCATE_BY_INDEX )
  660. {
  661. //
  662. // Convert index to numeric value VT_UI4 (within variant)
  663. //
  664. if ( FAILED( hr = VariantChangeType( &vKeyUI4, &vKey, 0, VT_UI4 ) ) )
  665. {
  666. goto Exit;
  667. }
  668. if ( V_UI4( &vKeyUI4 ) == 0 )
  669. {
  670. // Error PATH_NOT_FOUND chosen for backward compatibility
  671. // with version IIS5.1 and older
  672. //
  673. hr = HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND );
  674. goto Exit;
  675. }
  676. //
  677. // Index is 1 - based
  678. //
  679. hr = m_pIABase->EnumKeys( m_hmd,
  680. L"",
  681. achIndex,
  682. V_UI4( &vKeyUI4 ) - 1
  683. );
  684. if ( hr == HRESULT_FROM_WIN32( ERROR_NO_MORE_ITEMS ) )
  685. {
  686. // Error PATH_NOT_FOUND chosen for backward compatibility
  687. // with version IIS5.1 and older
  688. //
  689. hr = HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND );
  690. }
  691. goto Exit;
  692. }
  693. //
  694. // get ptr to data
  695. //
  696. if ( lMethod == IISMAPPER_LOCATE_BY_CERT )
  697. {
  698. // Now this is really wacky. Because of the legacy of the bad
  699. // decision in the past the CERT is not enforced to be byte array
  700. // It can be passed as string. That causes problems with
  701. // conversions between byte array and UNICODE and back
  702. // but we got to stick with it for compatibility with previous versions.
  703. //
  704. if ( FAILED( hr = GetBlobFromVariant( &vKey, &pbCert, &cbCert ) ) )
  705. {
  706. goto Exit;
  707. }
  708. pbKeyData = pbCert;
  709. cbKeyData = cbCert;
  710. }
  711. else
  712. {
  713. //
  714. // the rest of the lookups (by mapping, name or by account name)
  715. // assumes string
  716. //
  717. if ( FAILED( hr = VariantChangeType( &vKeyBSTR, &vKey, 0, VT_BSTR ) ) )
  718. {
  719. goto Exit;
  720. }
  721. pbKeyData = (PBYTE) V_BSTR( &vKeyBSTR );
  722. cbKeyData = ( SysStringLen(V_BSTR( &vKeyBSTR )) + 1 ) * sizeof(WCHAR);
  723. }
  724. //
  725. // enumerate all entries to find match
  726. // Now this is really slooow if many mappings are configured
  727. //
  728. for(;;)
  729. {
  730. hr = m_pIABase->EnumKeys( m_hmd,
  731. L"",
  732. achIndex,
  733. dwIndex
  734. );
  735. if ( FAILED( hr ) )
  736. {
  737. if ( hr == HRESULT_FROM_WIN32( ERROR_NO_MORE_ITEMS ) )
  738. {
  739. // Error PATH_NOT_FOUND chosen for backward compatibility
  740. // with version IIS5.1 and older
  741. //
  742. hr = HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND );
  743. }
  744. goto Exit;
  745. }
  746. switch ( lMethod )
  747. {
  748. case IISMAPPER_LOCATE_BY_CERT:
  749. hr = GetMdData( achIndex, MD_MAPCERT, BINARY_METADATA, &cbData,
  750. &pbData );
  751. if ( hr == MD_ERROR_DATA_NOT_FOUND )
  752. {
  753. cbData = 0;
  754. pbData = NULL;
  755. }
  756. else if ( FAILED( hr ) )
  757. {
  758. // goto next entry
  759. break;
  760. }
  761. //
  762. // compare if key is matching value read from metabase
  763. //
  764. if ( cbData == cbKeyData )
  765. {
  766. if ( ( cbData == 0 ) ||
  767. memcmp( pbKeyData, pbData, cbData ) == 0 )
  768. {
  769. // we found match
  770. hr = S_OK;
  771. goto Exit;
  772. }
  773. }
  774. break;
  775. case IISMAPPER_LOCATE_BY_ACCT:
  776. hr = GetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA, &cbData,
  777. &pbData );
  778. if ( hr == MD_ERROR_DATA_NOT_FOUND )
  779. {
  780. cbData = sizeof(L"");
  781. pbData = (PBYTE) L"";
  782. }
  783. else if ( FAILED( hr ) )
  784. {
  785. // goto next entry
  786. break;
  787. }
  788. if ( cbData == cbKeyData )
  789. {
  790. if ( _wcsicmp( (WCHAR *) pbKeyData, (WCHAR *) pbData ) == 0 )
  791. {
  792. // we found match
  793. hr = S_OK;
  794. goto Exit;
  795. }
  796. }
  797. break;
  798. case IISMAPPER_LOCATE_BY_NAME:
  799. hr = GetMdData( achIndex, MD_MAPNAME, STRING_METADATA, &cbData,
  800. &pbData );
  801. if ( hr == MD_ERROR_DATA_NOT_FOUND )
  802. {
  803. cbData = sizeof(L"");
  804. pbData = (PBYTE) L"";
  805. }
  806. else if ( FAILED( hr ) )
  807. {
  808. // goto next entry
  809. break;
  810. }
  811. if ( cbData == cbKeyData )
  812. {
  813. if ( _wcsicmp( (WCHAR *) pbKeyData, (WCHAR *) pbData ) == 0 )
  814. {
  815. // we found match
  816. hr = S_OK;
  817. goto Exit;
  818. }
  819. }
  820. break;
  821. }
  822. if ( pbData != NULL )
  823. {
  824. free( pbData );
  825. pbData = NULL;
  826. }
  827. dwIndex++;
  828. }
  829. Exit:
  830. if ( pbData != NULL )
  831. {
  832. free( pbData );
  833. pbData = NULL;
  834. }
  835. if ( pbCert != NULL )
  836. {
  837. free( pbCert );
  838. pbCert = NULL;
  839. }
  840. if ( SUCCEEDED( hr ) )
  841. {
  842. wcsncpy( pszResKey, achIndex, METADATA_MAX_NAME_LEN + 1 );
  843. pszResKey[ METADATA_MAX_NAME_LEN ] ='\0';
  844. }
  845. VariantClear( &vKeyUI4 );
  846. VariantClear( &vKeyBSTR );
  847. return hr;
  848. }
  849. //
  850. // GetStringFromBSTR: Allocate string buffer from BSTR
  851. //
  852. // Arguments:
  853. //
  854. // bstr - bstr to convert from
  855. // psz - updated with ptr to buffer, to be freed with free()
  856. // pdwLen - updated with strlen(string), incremented by 1 if fAddDelimInCount is TRUE
  857. // fAddDelimInCount - TRUE to increment *pdwLen
  858. //
  859. HRESULT CCertMapperMethod::GetStringAFromBSTR(
  860. BSTR bstr,
  861. LPSTR* psz,
  862. LPDWORD pdwLen,
  863. BOOL fAddDelimInCount
  864. )
  865. {
  866. UINT cch = SysStringLen(bstr);
  867. UINT cchT;
  868. // include NULL terminator
  869. *pdwLen = cch + (fAddDelimInCount ? 1 : 0);
  870. CHAR *szNew = (CHAR*)malloc((2 * cch) + 1); // * 2 for worst case DBCS string
  871. if (szNew == NULL)
  872. {
  873. return E_OUTOFMEMORY;
  874. }
  875. cchT = WideCharToMultiByte(CP_ACP, 0, bstr, cch + 1, szNew, (2 * cch) + 1, NULL, NULL);
  876. *psz = szNew;
  877. return NOERROR;
  878. }
  879. //
  880. // GetStringFromVariant: Allocate string buffer from BSTR
  881. //
  882. // Arguments:
  883. //
  884. // pVar - variant to convert from. Recognizes BSTR, VT_ARRAY|VT_UI1, ByRef or ByVal
  885. // psz - updated with ptr to buffer, to be freed with FreeString()
  886. // pdwLen - updated with size of input, incremented by 1 if fAddDelimInCount is TRUE
  887. // fAddDelimInCount - TRUE to increment *pdwLen
  888. //
  889. HRESULT CCertMapperMethod::GetBlobFromVariant(
  890. VARIANT* pVar,
  891. LPBYTE* ppbOut,
  892. LPDWORD pcbOut,
  893. BOOL fAddDelim
  894. )
  895. {
  896. LPBYTE pbV = NULL;
  897. UINT cV;
  898. HRESULT hr;
  899. WORD vt = V_VT(pVar);
  900. BOOL fByRef = FALSE;
  901. VARIANT vOut;
  902. // Set out params to 0
  903. *ppbOut = NULL;
  904. *pcbOut = 0;
  905. VariantInit( &vOut );
  906. if ( vt & VT_BYREF )
  907. {
  908. vt &= ~VT_BYREF;
  909. fByRef = TRUE;
  910. }
  911. // if pVar is BSTR, convert to multibytes
  912. if ( vt == VT_VARIANT )
  913. {
  914. pVar = (VARIANT*)V_BSTR(pVar);
  915. vt = V_VT(pVar);
  916. if ( fByRef = vt & VT_BYREF )
  917. {
  918. vt &= ~VT_BYREF;
  919. }
  920. }
  921. if ( vt == VT_BSTR )
  922. {
  923. hr = GetStringAFromBSTR( fByRef ?
  924. *(BSTR*)V_BSTR(pVar) :
  925. V_BSTR(pVar),
  926. (LPSTR *)ppbOut,
  927. pcbOut,
  928. FALSE );
  929. }
  930. else if( vt == (VT_ARRAY | VT_UI1) )
  931. {
  932. long lBound, uBound, lItem;
  933. BYTE bValue;
  934. SAFEARRAY* pSafeArray;
  935. // array of VT_UI1 (probably OctetString)
  936. pSafeArray = fByRef ? *(SAFEARRAY**)V_BSTR(pVar) : V_ARRAY( pVar );
  937. hr = SafeArrayGetLBound(pSafeArray, 1, &lBound);
  938. hr = SafeArrayGetUBound(pSafeArray, 1, &uBound);
  939. cV = uBound - lBound + 1;
  940. if ( !(pbV = (LPBYTE)malloc( cV )) )
  941. {
  942. hr = E_OUTOFMEMORY;
  943. goto Exit;
  944. }
  945. hr = S_OK;
  946. for( lItem = lBound; lItem <= uBound ; lItem++ )
  947. {
  948. hr = SafeArrayGetElement( pSafeArray, &lItem, &bValue );
  949. if( FAILED( hr ) )
  950. {
  951. break;
  952. }
  953. pbV[lItem-lBound] = bValue;
  954. }
  955. *ppbOut = pbV;
  956. *pcbOut = cV;
  957. }
  958. else if( vt == (VT_ARRAY | VT_VARIANT) )
  959. {
  960. long lBound, uBound, lItem;
  961. VARIANT vValue;
  962. BYTE bValue;
  963. SAFEARRAY* pSafeArray;
  964. // array of VT_VARIANT (probably VT_I4 )
  965. pSafeArray = fByRef ? *(SAFEARRAY**)V_BSTR(pVar) : V_ARRAY( pVar );
  966. hr = SafeArrayGetLBound(pSafeArray, 1, &lBound);
  967. hr = SafeArrayGetUBound(pSafeArray, 1, &uBound);
  968. cV = uBound - lBound + 1;
  969. if ( !(pbV = (LPBYTE)malloc( cV )) )
  970. {
  971. hr = E_OUTOFMEMORY;
  972. goto Exit;
  973. }
  974. hr = S_OK;
  975. for( lItem = lBound; lItem <= uBound ; lItem++ )
  976. {
  977. hr = SafeArrayGetElement( pSafeArray, &lItem, &vValue );
  978. if( FAILED( hr ) )
  979. {
  980. break;
  981. }
  982. if ( V_VT(&vValue) == VT_UI1 )
  983. {
  984. bValue = V_UI1(&vValue);
  985. }
  986. else if ( V_VT(&vValue) == VT_I2 )
  987. {
  988. bValue = (BYTE)V_I2(&vValue);
  989. }
  990. else if ( V_VT(&vValue) == VT_I4 )
  991. {
  992. bValue = (BYTE)V_I4(&vValue);
  993. }
  994. else
  995. {
  996. bValue = 0;
  997. }
  998. pbV[lItem-lBound] = bValue;
  999. }
  1000. *ppbOut = pbV;
  1001. *pcbOut = cV;
  1002. }
  1003. else
  1004. {
  1005. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1006. }
  1007. Exit:
  1008. VariantClear( &vOut );
  1009. return hr;
  1010. }
  1011. HRESULT CCertMapperMethod::SetBSTR(
  1012. BSTR* pbstrRet,
  1013. DWORD cch,
  1014. LPBYTE sz
  1015. )
  1016. {
  1017. BSTR bstrRet;
  1018. if (sz == NULL)
  1019. {
  1020. *pbstrRet = NULL;
  1021. return(NOERROR);
  1022. }
  1023. // Allocate a string of the desired length
  1024. // SysAllocStringLen allocates enough room for unicode characters plus a null
  1025. // Given a NULL string it will just allocate the space
  1026. bstrRet = SysAllocStringLen(NULL, cch);
  1027. if (bstrRet == NULL)
  1028. {
  1029. return(E_OUTOFMEMORY);
  1030. }
  1031. // If we were given "", we will have cch=0. return the empty bstr
  1032. // otherwise, really copy/convert the string
  1033. // NOTE we pass -1 as 4th parameter of MultiByteToWideChar for DBCS support
  1034. if (cch != 0)
  1035. {
  1036. UINT cchTemp = 0;
  1037. if (MultiByteToWideChar(CP_ACP, 0, (LPSTR)sz, -1, bstrRet, cch+1) == 0)
  1038. {
  1039. SysFreeString(bstrRet);
  1040. return(HRESULT_FROM_WIN32(GetLastError()));
  1041. }
  1042. // If there are some DBCS characters in the sz(Input), then, the character count of BSTR(DWORD) is
  1043. // already set to cch(strlen(sz)) in SysAllocStringLen(NULL, cch), we cannot change the count,
  1044. // and later call of SysStringLen(bstr) always returns the number of characters specified in the
  1045. // cch parameter at allocation time. Bad, because one DBCS character(2 bytes) will convert
  1046. // to one UNICODE character(2 bytes), not 2 UNICODE characters(4 bytes).
  1047. // Example: For input sz contains only one DBCS character, we want to see SysStringLen(bstr)
  1048. // = 1, not 2.
  1049. bstrRet[cch] = 0;
  1050. cchTemp = wcslen(bstrRet);
  1051. if (cchTemp < cch)
  1052. {
  1053. BSTR bstrTemp = SysAllocString(bstrRet);
  1054. SysFreeString(bstrRet);
  1055. if (NULL == bstrTemp)
  1056. {
  1057. return (E_OUTOFMEMORY);
  1058. }
  1059. bstrRet = bstrTemp;
  1060. cch = cchTemp;
  1061. }
  1062. }
  1063. bstrRet[cch] = 0;
  1064. *pbstrRet = bstrRet;
  1065. return(NOERROR);
  1066. }
  1067. HRESULT CCertMapperMethod::Init(
  1068. LPCWSTR pszMetabasePath
  1069. )
  1070. {
  1071. DBG_ASSERT(pszMetabasePath != NULL);
  1072. UINT cL;
  1073. cL = wcslen( pszMetabasePath );
  1074. while ( cL && pszMetabasePath[cL-1] != L'/' && pszMetabasePath[cL-1] != L'\\' )
  1075. {
  1076. --cL;
  1077. }
  1078. if ( m_pszMetabasePath = (LPWSTR)malloc( cL*sizeof(WCHAR) ) )
  1079. {
  1080. memcpy( m_pszMetabasePath, pszMetabasePath, cL * sizeof(WCHAR) );
  1081. }
  1082. else
  1083. {
  1084. return E_OUTOFMEMORY;
  1085. }
  1086. return S_OK;
  1087. }
  1088. HRESULT CCertMapperMethod::SetVariantAsByteArray(
  1089. VARIANT* pvarReturn,
  1090. DWORD cbLen,
  1091. LPBYTE pbIn
  1092. )
  1093. {
  1094. SAFEARRAYBOUND rgsabound[1];
  1095. BYTE * pbData = NULL;
  1096. // Set the variant type of the output parameter
  1097. V_VT(pvarReturn) = VT_ARRAY|VT_UI1;
  1098. V_ARRAY(pvarReturn) = NULL;
  1099. // Allocate a SafeArray for the data
  1100. rgsabound[0].lLbound = 0;
  1101. rgsabound[0].cElements = cbLen;
  1102. V_ARRAY(pvarReturn) = SafeArrayCreate(VT_UI1, 1, rgsabound);
  1103. if (V_ARRAY(pvarReturn) == NULL)
  1104. {
  1105. return E_OUTOFMEMORY;
  1106. }
  1107. if (FAILED(SafeArrayAccessData(V_ARRAY(pvarReturn), (void **) &pbData)))
  1108. {
  1109. return E_UNEXPECTED;
  1110. }
  1111. memcpy(pbData, pbIn, cbLen );
  1112. SafeArrayUnaccessData(V_ARRAY(pvarReturn));
  1113. return NOERROR;
  1114. }
  1115. HRESULT CCertMapperMethod::SetVariantAsBSTR(
  1116. VARIANT* pvarReturn,
  1117. DWORD cbLen,
  1118. LPBYTE pbIn
  1119. )
  1120. {
  1121. V_VT(pvarReturn) = VT_BSTR;
  1122. return SetBSTR( &V_BSTR(pvarReturn), cbLen, pbIn );
  1123. }
  1124. HRESULT CCertMapperMethod::SetVariantAsLong(
  1125. VARIANT* pvarReturn,
  1126. DWORD dwV
  1127. )
  1128. {
  1129. V_VT(pvarReturn) = VT_I4;
  1130. V_I4(pvarReturn) = dwV;
  1131. return S_OK;
  1132. }
  1133. HRESULT CCertMapperMethod::OpenAdminBaseKey(
  1134. LPWSTR pszPathName,
  1135. DWORD dwAccessType
  1136. )
  1137. {
  1138. if(m_hmd)
  1139. CloseAdminBaseKey();
  1140. HRESULT t_hr = m_pIABase->OpenKey(
  1141. METADATA_MASTER_ROOT_HANDLE,
  1142. pszPathName,
  1143. dwAccessType,
  1144. DEFAULT_TIMEOUT_VALUE, // 30 seconds
  1145. &m_hmd
  1146. );
  1147. if(FAILED(t_hr))
  1148. m_hmd = NULL;
  1149. return t_hr;
  1150. }
  1151. VOID CCertMapperMethod::CloseAdminBaseKey()
  1152. {
  1153. if(m_hmd && m_pIABase)
  1154. {
  1155. m_pIABase->CloseKey(m_hmd);
  1156. m_hmd = NULL;
  1157. }
  1158. }