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.

4950 lines
116 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. iismap.cxx
  5. Abstract:
  6. Classes implementing IIS 1to1 Client Certificate Mapping
  7. Author:
  8. Philippe Choquier (phillich) 17-may-1996
  9. --*/
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <wincrypt.h>
  17. #include <iis64.h>
  18. #include <buffer.hxx>
  19. #define DLL_IMPLEMENTATION
  20. #include <iismap.hxx>
  21. #include "iismaprc.h"
  22. #include "mapmsg.h"
  23. #include "iiscmr.hxx"
  24. #include <icrypt.hxx>
  25. #include "dbgutil.h"
  26. #define INITGUID
  27. #include <ole2.h>
  28. #include <iadmw.h>
  29. #include <iiscnfg.h>
  30. #include <iiscnfgp.h>
  31. #include "simplemb.hxx"
  32. #include <stringau.hxx>
  33. //
  34. // static vars
  35. //
  36. //
  37. // Guid that is part of the *.MP file name
  38. // MP file stores 1to1 mappings information
  39. //
  40. DWORD s_dwFileGuid = 0;
  41. //
  42. // Install path of IIS -> *.MP file is placed in the same directory
  43. // as IIS files
  44. //
  45. LPSTR s_pszIisInstallPath = NULL;
  46. DECLARE_DEBUG_PRINTS_OBJECT();
  47. //
  48. // global functions
  49. //
  50. HRESULT
  51. GetSecurityDescriptorForMetabaseExtensionFile(
  52. PSECURITY_DESCRIPTOR * ppsdStorage
  53. )
  54. /*++
  55. Routine Description:
  56. Build security descriptor that will be set for the extension file
  57. *.mp (includes Administrators and System )
  58. Arguments:
  59. ppsdStorage - Security Descriptor to be set for extension file
  60. Returns:
  61. HRESULT
  62. --*/
  63. {
  64. HRESULT hr = ERROR_SUCCESS;
  65. BOOL fRet = FALSE;
  66. DWORD dwDaclSize = 0;
  67. SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
  68. PSID psidSystem = NULL;
  69. PSID psidAdmin = NULL;
  70. PACL paclDiscretionary = NULL;
  71. DBG_ASSERT( ppsdStorage != NULL );
  72. *ppsdStorage = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
  73. if ( *ppsdStorage == NULL )
  74. {
  75. hr = HRESULT_FROM_WIN32(GetLastError());
  76. goto exit;
  77. }
  78. //
  79. // Initialize the security descriptor.
  80. //
  81. fRet = InitializeSecurityDescriptor(
  82. *ppsdStorage,
  83. SECURITY_DESCRIPTOR_REVISION
  84. );
  85. if( !fRet )
  86. {
  87. hr = HRESULT_FROM_WIN32(GetLastError());
  88. goto exit;
  89. }
  90. //
  91. // Create the SIDs for the local system and admin group.
  92. //
  93. fRet = AllocateAndInitializeSid(
  94. &ntAuthority,
  95. 1,
  96. SECURITY_LOCAL_SYSTEM_RID,
  97. 0,
  98. 0,
  99. 0,
  100. 0,
  101. 0,
  102. 0,
  103. 0,
  104. &psidSystem
  105. );
  106. if( !fRet )
  107. {
  108. hr = HRESULT_FROM_WIN32(GetLastError());
  109. goto exit;
  110. }
  111. fRet= AllocateAndInitializeSid(
  112. &ntAuthority,
  113. 2,
  114. SECURITY_BUILTIN_DOMAIN_RID,
  115. DOMAIN_ALIAS_RID_ADMINS,
  116. 0,
  117. 0,
  118. 0,
  119. 0,
  120. 0,
  121. 0,
  122. &psidAdmin
  123. );
  124. if( !fRet )
  125. {
  126. hr = HRESULT_FROM_WIN32(GetLastError());
  127. goto exit;
  128. }
  129. //
  130. // Create the DACL containing an access-allowed ACE
  131. // for the local system and admin SIDs.
  132. //
  133. dwDaclSize = sizeof(ACL)
  134. + sizeof(ACCESS_ALLOWED_ACE)
  135. + GetLengthSid(psidAdmin)
  136. + sizeof(ACCESS_ALLOWED_ACE)
  137. + GetLengthSid(psidSystem)
  138. - sizeof(DWORD);
  139. paclDiscretionary = (PACL)LocalAlloc(LPTR, dwDaclSize );
  140. if ( paclDiscretionary == NULL )
  141. {
  142. hr = HRESULT_FROM_WIN32(GetLastError());
  143. goto exit;
  144. }
  145. fRet = InitializeAcl(
  146. paclDiscretionary,
  147. dwDaclSize,
  148. ACL_REVISION
  149. );
  150. if( !fRet )
  151. {
  152. hr = HRESULT_FROM_WIN32(GetLastError());
  153. goto exit;
  154. }
  155. fRet = AddAccessAllowedAce(
  156. paclDiscretionary,
  157. ACL_REVISION,
  158. FILE_ALL_ACCESS,
  159. psidSystem
  160. );
  161. if ( !fRet )
  162. {
  163. hr = HRESULT_FROM_WIN32(GetLastError());
  164. goto exit;
  165. }
  166. fRet = AddAccessAllowedAce(
  167. paclDiscretionary,
  168. ACL_REVISION,
  169. FILE_ALL_ACCESS,
  170. psidAdmin
  171. );
  172. if ( !fRet )
  173. {
  174. hr = HRESULT_FROM_WIN32(GetLastError());
  175. goto exit;
  176. }
  177. //
  178. // Set the DACL into the security descriptor.
  179. //
  180. fRet = SetSecurityDescriptorDacl(
  181. *ppsdStorage,
  182. TRUE,
  183. paclDiscretionary,
  184. FALSE
  185. );
  186. if ( !fRet ) {
  187. hr = HRESULT_FROM_WIN32(GetLastError());
  188. goto exit;
  189. }
  190. hr = S_OK;
  191. exit:
  192. if ( psidAdmin != NULL )
  193. {
  194. FreeSid( psidAdmin );
  195. psidAdmin = NULL;
  196. }
  197. if ( psidSystem != NULL )
  198. {
  199. FreeSid( psidSystem );
  200. psidSystem = NULL;
  201. }
  202. if ( FAILED( hr ) ) {
  203. if ( paclDiscretionary != NULL )
  204. {
  205. LocalFree( paclDiscretionary );
  206. paclDiscretionary = NULL;
  207. }
  208. if ( *ppsdStorage != NULL )
  209. {
  210. LocalFree( *ppsdStorage );
  211. *ppsdStorage = NULL;
  212. }
  213. }
  214. return hr;
  215. }
  216. HRESULT
  217. FreeSecurityDescriptorForMetabaseExtensionFile(
  218. PSECURITY_DESCRIPTOR psdStorage
  219. )
  220. /*++
  221. Routine Description:
  222. Free security descriptor generated by
  223. GetSecurityDescriptorForMetabaseExtentionFile()
  224. Arguments:
  225. psdStorage - Security Descriptor to be freed
  226. Returns:
  227. HRESULT
  228. --*/
  229. {
  230. HRESULT hr = ERROR_SUCCESS;
  231. BOOL fRet = FALSE;
  232. BOOL fDaclPresent;
  233. PACL paclDiscretionary = NULL;
  234. BOOL fDaclDefaulted;
  235. //
  236. // Get the DACL from the security descriptor.
  237. //
  238. if ( psdStorage == NULL )
  239. {
  240. hr = S_OK;
  241. goto exit;
  242. }
  243. fRet = GetSecurityDescriptorDacl(
  244. psdStorage,
  245. &fDaclPresent,
  246. &paclDiscretionary,
  247. &fDaclDefaulted
  248. );
  249. if ( !fRet )
  250. {
  251. hr = HRESULT_FROM_WIN32(GetLastError());
  252. goto exit;
  253. }
  254. if ( fDaclPresent && paclDiscretionary != NULL )
  255. {
  256. LocalFree( paclDiscretionary );
  257. paclDiscretionary = NULL;
  258. }
  259. LocalFree( psdStorage );
  260. hr = S_OK;
  261. exit:
  262. return hr;
  263. }
  264. //
  265. // Fields for the Certificate 1:1 mapper
  266. //
  267. IISMDB_Fields IisCert11MappingFields[] = {
  268. // certificate blob
  269. {IISMDB_INDEX_CERT11_CERT, NULL, IDS_IISMAP11_FLDC, 40 },
  270. // NT account name
  271. {IISMDB_INDEX_CERT11_NT_ACCT, NULL, IDS_IISMAP11_FLDA, 40 },
  272. // mapping name
  273. {IISMDB_INDEX_CERT11_NAME, NULL, IDS_IISMAP11_FLDN, 40 },
  274. // mapping enabled
  275. {IISMDB_INDEX_CERT11_ENABLED, NULL, IDS_IISMAP11_FLDE, 40 },
  276. // NT account password
  277. {IISMDB_INDEX_CERT11_NT_PWD, NULL, IDS_IISMAP11_FLDP, 40 },
  278. } ;
  279. //
  280. // default hierarchy for the Certificate 1:1 mapper
  281. // This is basically list of fields that are used for
  282. // mapping comparison
  283. // 1 to 1 mapper uses only CERTIFICATE BLOB
  284. //
  285. IISMDB_HEntry IisCert11MappingHierarchy[] = {
  286. {IISMDB_INDEX_CERT11_CERT, TRUE},
  287. } ;
  288. HINSTANCE s_hIISMapDll = (HINSTANCE)INVALID_HANDLE_VALUE;
  289. // CIisAcctMapper
  290. CIisAcctMapper::CIisAcctMapper(
  291. )
  292. /*++
  293. Routine Description:
  294. Constructor for CIisAcctMapper
  295. Arguments:
  296. None
  297. Returns:
  298. Nothing
  299. --*/
  300. {
  301. m_cInit = -1;
  302. m_pMapping = NULL;
  303. m_cMapping = 0;
  304. m_pAltMapping = NULL;
  305. m_cAltMapping = 0;
  306. m_pHierarchy = NULL;
  307. m_cHierarchy = 0;
  308. m_achFileName[0] = '\0';
  309. m_pClasses = NULL;
  310. m_pSesKey = NULL;
  311. m_dwSesKey = 0;
  312. m_hNotifyEvent = NULL;
  313. m_fRequestTerminate = FALSE;
  314. INITIALIZE_CRITICAL_SECTION( &csLock );
  315. }
  316. CIisAcctMapper::~CIisAcctMapper(
  317. )
  318. /*++
  319. Routine Description:
  320. Destructor for CIisAcctMapper
  321. Arguments:
  322. None
  323. Returns:
  324. Nothing
  325. --*/
  326. {
  327. Reset();
  328. if ( m_pHierarchy != NULL )
  329. {
  330. LocalFree( m_pHierarchy );
  331. }
  332. if ( m_pSesKey != NULL )
  333. {
  334. LocalFree( m_pSesKey );
  335. }
  336. DeleteCriticalSection( &csLock );
  337. }
  338. BOOL
  339. CIisAcctMapper::Create(
  340. VOID
  341. )
  342. /*++
  343. Routine Description:
  344. Create file for CIisAcctMapper with proper SD
  345. Arguments:
  346. None
  347. Returns:
  348. TRUE if success, FALSE if error
  349. --*/
  350. {
  351. // create file name, store in m_achFileName
  352. // from s_dwFileGuid
  353. // and s_pszIisInstallPath
  354. UINT cLen;
  355. HANDLE hF;
  356. HRESULT hr = E_FAIL;
  357. BOOL fRet = FALSE;
  358. PSECURITY_DESCRIPTOR psdForMetabaseExtensionFile = NULL;
  359. SECURITY_ATTRIBUTES saStorage;
  360. // calculate the max # of characters that m_achFileName can take
  361. DWORD cchMaxFileName = sizeof ( m_achFileName ) / sizeof (CHAR) - 1;
  362. Reset();
  363. if ( s_pszIisInstallPath )
  364. {
  365. cLen = (DWORD) strlen(s_pszIisInstallPath);
  366. if ( cchMaxFileName < cLen )
  367. {
  368. return FALSE;
  369. }
  370. memcpy( m_achFileName, s_pszIisInstallPath, cLen );
  371. // if path is not terminated by "\" then add one
  372. if ( cLen && m_achFileName[cLen-1] != '\\' )
  373. {
  374. if ( cchMaxFileName < cLen + 1 )
  375. {
  376. return FALSE;
  377. }
  378. m_achFileName[cLen++] = '\\';
  379. }
  380. }
  381. else
  382. {
  383. cLen = 0;
  384. }
  385. if( sizeof(m_achFileName) - cLen > 8 + 3 /*%08x.mp*/ )
  386. {
  387. wsprintf( m_achFileName+cLen,
  388. "%08x.mp",
  389. s_dwFileGuid );
  390. }
  391. else
  392. {
  393. //
  394. // buffer m_achFileName is not sufficiently big
  395. //
  396. return FALSE;
  397. }
  398. //
  399. // build security descriptor (Administrators and SYSTEM)
  400. // to be set on metabase extension file
  401. //
  402. hr = GetSecurityDescriptorForMetabaseExtensionFile(
  403. &psdForMetabaseExtensionFile );
  404. if ( SUCCEEDED(hr) && psdForMetabaseExtensionFile != NULL )
  405. {
  406. saStorage.nLength = sizeof(SECURITY_ATTRIBUTES);
  407. saStorage.lpSecurityDescriptor = psdForMetabaseExtensionFile;
  408. saStorage.bInheritHandle = FALSE;
  409. }
  410. else
  411. {
  412. return FALSE;
  413. }
  414. //
  415. // Open file and close it right away
  416. // If file didn't exist, then empty file with good SD (Security Descriptor)
  417. // will be created. That will later be opened using C runtime (fopen)
  418. // in Save() method and good SD will persist.
  419. // Ideally Save() should be using Win32 CreateFile()
  420. // instead fopen and it could set SD itself. But since this is legacy
  421. // source file and rather unsafe for making too many changes, pragmatic
  422. // approach was chosen to set SD here in Create() method
  423. //
  424. if ( (hF = CreateFile( m_achFileName,
  425. GENERIC_READ,
  426. FILE_SHARE_READ|FILE_SHARE_WRITE,
  427. &saStorage,
  428. OPEN_ALWAYS,
  429. FILE_ATTRIBUTE_NORMAL,
  430. NULL ) ) != INVALID_HANDLE_VALUE )
  431. {
  432. CloseHandle( hF );
  433. fRet = TRUE;
  434. }
  435. else
  436. {
  437. fRet = FALSE;
  438. }
  439. if ( psdForMetabaseExtensionFile != NULL )
  440. {
  441. FreeSecurityDescriptorForMetabaseExtensionFile(
  442. psdForMetabaseExtensionFile );
  443. psdForMetabaseExtensionFile = NULL;
  444. }
  445. return fRet;
  446. }
  447. BOOL
  448. CIisAcctMapper::Delete(
  449. VOID
  450. )
  451. /*++
  452. Routine Description:
  453. Delete external storage used by this mapper ( i.e. file )
  454. Arguments:
  455. None
  456. Returns:
  457. TRUE if success, FALSE if error
  458. --*/
  459. {
  460. BOOL fSt = TRUE;
  461. Lock();
  462. if ( m_achFileName[0] )
  463. {
  464. fSt = DeleteFile( m_achFileName );
  465. m_achFileName[0] = '\0';
  466. }
  467. Unlock();
  468. return fSt;
  469. }
  470. BOOL
  471. CIisAcctMapper::Serialize(
  472. CStoreXBF* pXbf
  473. )
  474. /*++
  475. Routine Description:
  476. Serialize mapper reference ( NOT mapping info ) to buffer
  477. Save() must be called to save mapping info before calling Serialize()
  478. Arguments:
  479. pXbf - ptr to extensible buffer to serialize to
  480. Returns:
  481. TRUE if success, FALSE if error
  482. --*/
  483. {
  484. return pXbf->Append( (DWORD)strlen(m_achFileName) ) &&
  485. pXbf->Append( (LPBYTE)m_achFileName, (DWORD)strlen(m_achFileName) ) &&
  486. pXbf->Append( (LPBYTE)m_md5.digest, (DWORD)sizeof(m_md5.digest) ) &&
  487. pXbf->Append( (DWORD)m_dwSesKey ) &&
  488. pXbf->Append( (LPBYTE)m_pSesKey, (DWORD)m_dwSesKey ) ;
  489. }
  490. BOOL
  491. CIisAcctMapper::Unserialize(
  492. CStoreXBF* pXBF
  493. )
  494. /*++
  495. Routine Description:
  496. Unserialize mapper reference ( NOT mapping info ) from extensible buffer
  497. Load() must be called to load mapping info
  498. Arguments:
  499. pXBF - ptr to extensible buffer
  500. Returns:
  501. TRUE if success, FALSE if error
  502. --*/
  503. {
  504. LPBYTE pb = pXBF->GetBuff();
  505. DWORD c = pXBF->GetUsed();
  506. return Unserialize( &pb, &c );
  507. }
  508. BOOL
  509. CIisAcctMapper::Unserialize(
  510. LPBYTE* ppb,
  511. LPDWORD pc
  512. )
  513. /*++
  514. Routine Description:
  515. Unserialize mapper reference ( NOT mapping info ) from buffer
  516. Load() must be called to load mapping info
  517. Arguments:
  518. ppb - ptr to buffer
  519. pc - ptr to buffer length
  520. Returns:
  521. TRUE if success, FALSE if error
  522. --*/
  523. {
  524. DWORD cName;
  525. if ( ::Unserialize( ppb, pc, &cName ) &&
  526. cName <= *pc )
  527. {
  528. // calculate the max # of characters that m_achFileName can take
  529. DWORD cchMaxFileName = sizeof ( m_achFileName ) / sizeof (CHAR) - 1;
  530. if ( cchMaxFileName < cName )
  531. {
  532. return FALSE;
  533. }
  534. memcpy( m_achFileName, *ppb, cName );
  535. m_achFileName[ cName ] = '\0';
  536. *ppb += cName;
  537. *pc -= cName;
  538. if ( sizeof(m_md5.digest) <= *pc )
  539. {
  540. memcpy( m_md5.digest, *ppb, sizeof(m_md5.digest) );
  541. *ppb += sizeof(m_md5.digest);
  542. *pc -= sizeof(m_md5.digest);
  543. if ( ::Unserialize( ppb, pc, &m_dwSesKey ) &&
  544. cName <= *pc )
  545. {
  546. if ( m_pSesKey != NULL )
  547. {
  548. LocalFree( m_pSesKey );
  549. }
  550. if ( (m_pSesKey = (LPBYTE)LocalAlloc( LMEM_FIXED, m_dwSesKey )) == NULL )
  551. {
  552. m_dwSesKey = 0;
  553. return FALSE;
  554. }
  555. memcpy( m_pSesKey, *ppb, m_dwSesKey );
  556. *ppb += m_dwSesKey;
  557. *pc -= m_dwSesKey;
  558. return TRUE;
  559. }
  560. }
  561. }
  562. return FALSE;
  563. }
  564. BOOL
  565. CIisAcctMapper::Serialize(
  566. VOID
  567. )
  568. /*++
  569. Routine Description:
  570. Serialize mapper reference ( NOT mapping info ) to registry
  571. Save() must be called to save mapping info before calling Serialize()
  572. Warning : this allow only 1 instance
  573. Arguments:
  574. None
  575. Returns:
  576. TRUE if success, FALSE if error
  577. --*/
  578. {
  579. BOOL fSt = TRUE;
  580. HKEY hKey;
  581. LONG st;
  582. if ( (st = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  583. GetRegKeyName(),
  584. 0,
  585. KEY_WRITE,
  586. &hKey )) != ERROR_SUCCESS )
  587. {
  588. SetLastError( st );
  589. return FALSE;
  590. }
  591. if ( RegSetValueEx( hKey,
  592. FILE_VALIDATOR,
  593. NULL,
  594. REG_BINARY,
  595. (LPBYTE)m_md5.digest,
  596. sizeof(m_md5.digest) ) != ERROR_SUCCESS ||
  597. RegSetValueEx( hKey,
  598. FILE_LOCATION,
  599. NULL,
  600. REG_SZ,
  601. (LPBYTE)m_achFileName,
  602. (DWORD) strlen(m_achFileName) ) != ERROR_SUCCESS )
  603. {
  604. fSt = FALSE;
  605. }
  606. RegCloseKey( hKey );
  607. return fSt;
  608. }
  609. BOOL
  610. CIisAcctMapper::Unserialize(
  611. VOID
  612. )
  613. /*++
  614. Routine Description:
  615. Unserialize mapper reference ( NOT mapping info ) From registry
  616. Load() must be called to load mapping info
  617. Warning : this allow only 1 instance
  618. Arguments:
  619. None
  620. Returns:
  621. TRUE if success, FALSE if error
  622. --*/
  623. {
  624. BOOL fSt = FALSE;
  625. HKEY hKey;
  626. DWORD dwLen;
  627. DWORD dwType;
  628. LONG st;
  629. // Check registry
  630. if ( (st = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  631. GetRegKeyName(),
  632. 0,
  633. KEY_READ,
  634. &hKey )) != ERROR_SUCCESS )
  635. {
  636. SetLastError( st );
  637. return FALSE;
  638. }
  639. dwLen = sizeof(m_md5.digest);
  640. if ( RegQueryValueEx( hKey,
  641. FILE_VALIDATOR,
  642. NULL,
  643. &dwType,
  644. (LPBYTE)m_md5.digest,
  645. &dwLen ) == ERROR_SUCCESS &&
  646. dwType == REG_BINARY &&
  647. (( dwLen = sizeof(m_achFileName) ), TRUE ) &&
  648. RegQueryValueEx( hKey,
  649. FILE_LOCATION,
  650. NULL,
  651. &dwType,
  652. (LPBYTE)m_achFileName,
  653. &dwLen ) == ERROR_SUCCESS &&
  654. dwType == REG_SZ )
  655. {
  656. fSt = TRUE;
  657. }
  658. RegCloseKey( hKey );
  659. return fSt;
  660. }
  661. BOOL
  662. CIisAcctMapper::UpdateClasses(
  663. BOOL fComputeMask
  664. )
  665. /*++
  666. Routine Description:
  667. Constructor for CIisAcctMapper
  668. Arguments:
  669. fComputeMask -- TRUE if mask to be recomputed
  670. Returns:
  671. TRUE if success, FALSE if error
  672. --*/
  673. {
  674. UINT x;
  675. UINT mx = 1 << m_cHierarchy;
  676. if ( fComputeMask )
  677. {
  678. for ( x = 0 ; x < m_cMapping ; ++x )
  679. {
  680. m_pMapping[x]->UpdateMask( m_pHierarchy, m_cHierarchy );
  681. }
  682. }
  683. SortMappings();
  684. if ( m_pClasses == NULL )
  685. {
  686. m_pClasses = (MappingClass*)LocalAlloc(
  687. LMEM_FIXED,
  688. sizeof(MappingClass)*(mx+1) );
  689. if ( m_pClasses == NULL )
  690. {
  691. return FALSE;
  692. }
  693. }
  694. DWORD dwN = 0; // current class index in m_pClasses
  695. DWORD dwLastClass = 0;
  696. DWORD dwFirst = 0; // first entry for current dwLastClass
  697. for ( x = 0 ; x <= m_cMapping ; ++x )
  698. {
  699. DWORD dwCur;
  700. dwCur = (x==m_cMapping) ? dwLastClass+1: m_pMapping[x]->GetMask();
  701. if ( dwCur > dwLastClass )
  702. {
  703. if ( x > dwFirst )
  704. {
  705. m_pClasses[dwN].dwClass = dwLastClass;
  706. m_pClasses[dwN].dwFirst = dwFirst;
  707. m_pClasses[dwN].dwLast = x - 1;
  708. ++dwN;
  709. }
  710. dwLastClass = dwCur;
  711. dwFirst = x;
  712. }
  713. }
  714. m_pClasses[dwN].dwClass = 0xffffffff;
  715. return TRUE;
  716. }
  717. //static
  718. int __cdecl
  719. CIisAcctMapper::QsortIisMappingCmp(
  720. const void *pA,
  721. const void *pB )
  722. /*++
  723. Routine Description:
  724. Compare function for 2 CIisMapping entries
  725. compare using mask, then all fields as defined in
  726. the linked CIisAcctMapper hierarchy
  727. Arguments:
  728. pA -- ptr to 1st element
  729. pB -- ptr tp 2nd elemet
  730. Returns:
  731. -1 if *pA < *pB, 0 if *pA == *pB, 1 if *pA > *pB
  732. --*/
  733. {
  734. return (*(CIisMapping**)pA)->Cmp( *(CIisMapping**)pB, FALSE );
  735. }
  736. BOOL
  737. CIisAcctMapper::SortMappings(
  738. )
  739. /*++
  740. Routine Description:
  741. Sort the mappings. Masks for mapping objects are assumed
  742. to be already computed.
  743. Arguments:
  744. None
  745. Returns:
  746. TRUE if success, FALSE if error
  747. --*/
  748. {
  749. qsort( (LPVOID)m_pMapping,
  750. m_cMapping,
  751. sizeof(CIisMapping*),
  752. QsortIisMappingCmp
  753. );
  754. return TRUE;
  755. }
  756. //static
  757. int __cdecl
  758. CIisAcctMapper::MatchIisMappingCmp(
  759. const void *pA,
  760. const void *pB
  761. )
  762. /*++
  763. Routine Description:
  764. Compare function for 2 CIisMapping entries
  765. do not uses mask, uses all fields as defined in
  766. the linked CIisAcctMapper hierarchy
  767. (used by CIisAcctMapper::FindMatch() )
  768. Arguments:
  769. pA -- ptr to 1st element
  770. pB -- ptr tp 2nd elemet
  771. Returns:
  772. -1 if *pA < *pB, 0 if *pA == *pB, 1 if *pA > *pB
  773. --*/
  774. {
  775. return ( *(CIisMapping**)pA)->Cmp( *(CIisMapping**)pB, TRUE );
  776. }
  777. BOOL
  778. CIisAcctMapper::FindMatch(
  779. CIisMapping* pQuery,
  780. CIisMapping** pResult,
  781. LPDWORD piResult
  782. )
  783. /*++
  784. Routine Description:
  785. Find a match base on field contents in CIisMapping
  786. Arguments:
  787. pQuery -- describe fields to consider for mapping
  788. pResult -- updated with result if found mapping
  789. Returns:
  790. TRUE if mapping found, else FALSE
  791. Lock:
  792. mapper must be locked for ptr to remain valid
  793. --*/
  794. {
  795. // iterate through classes, do bsearch on each
  796. MappingClass *pH = m_pClasses;
  797. if ( pH == NULL )
  798. {
  799. return FALSE;
  800. }
  801. while ( pH->dwClass != 0xffffffff )
  802. {
  803. CIisMapping **pRes = (CIisMapping **)bsearch( (LPVOID)&pQuery,
  804. (LPVOID)(m_pMapping+pH->dwFirst),
  805. pH->dwLast - pH->dwFirst + 1,
  806. sizeof(CIisMapping*),
  807. MatchIisMappingCmp );
  808. if ( piResult != NULL )
  809. {
  810. *piResult = (DWORD) DIFF(pRes - m_pMapping);
  811. }
  812. if ( pRes != NULL )
  813. {
  814. *pResult = *pRes;
  815. return TRUE;
  816. }
  817. ++pH;
  818. }
  819. return FALSE;
  820. }
  821. void
  822. CIisAcctMapper::Lock(
  823. )
  824. /*++
  825. Routine Description:
  826. Prevent access to mapper from other threads
  827. Arguments:
  828. None
  829. Returns:
  830. Nothing
  831. --*/
  832. {
  833. EnterCriticalSection( &csLock );
  834. }
  835. void
  836. CIisAcctMapper::Unlock(
  837. )
  838. /*++
  839. Routine Description:
  840. Re-enabled access to mapper from other threads
  841. Arguments:
  842. None
  843. Returns:
  844. Nothing
  845. --*/
  846. {
  847. LeaveCriticalSection( &csLock );
  848. }
  849. BOOL
  850. CIisAcctMapper::FlushAlternate(
  851. BOOL fApply
  852. )
  853. /*++
  854. Routine Description:
  855. Flush alternate list, optionaly commiting it to the main list
  856. Arguments:
  857. fApply -- TRUE to commit changes made in alternate list
  858. Returns:
  859. TRUE if success, otherwise FALSE
  860. --*/
  861. {
  862. UINT i;
  863. UINT iM;
  864. BOOL fSt = TRUE;
  865. if ( m_pAltMapping )
  866. {
  867. if ( fApply )
  868. {
  869. //
  870. // Transfer non existing objects from regular to alternate list
  871. //
  872. iM = min( m_cMapping, m_cAltMapping );
  873. for ( i = 0 ; i < iM ; ++ i )
  874. {
  875. if ( m_pAltMapping[i] == NULL )
  876. {
  877. m_pAltMapping[i] = m_pMapping[i];
  878. }
  879. else
  880. {
  881. delete m_pMapping[i];
  882. }
  883. }
  884. //
  885. // delete extra objects
  886. //
  887. if ( m_cMapping > m_cAltMapping )
  888. {
  889. for ( i = m_cAltMapping ; i < m_cMapping ; ++i )
  890. {
  891. delete m_pMapping[i];
  892. }
  893. }
  894. if ( m_pMapping )
  895. {
  896. LocalFree( m_pMapping );
  897. }
  898. m_pMapping = m_pAltMapping;
  899. m_cMapping = m_cAltMapping;
  900. fSt = UpdateClasses( TRUE );
  901. }
  902. else
  903. {
  904. for ( i = 0 ; i < m_cAltMapping ; ++i )
  905. {
  906. if ( m_pAltMapping[i] )
  907. {
  908. delete m_pAltMapping[i];
  909. }
  910. }
  911. LocalFree( m_pAltMapping );
  912. }
  913. }
  914. m_pAltMapping = NULL;
  915. m_cAltMapping = 0;
  916. return fSt;
  917. }
  918. BOOL
  919. CIisAcctMapper::GetMapping(
  920. DWORD iIndex,
  921. CIisMapping** pM,
  922. BOOL fGetFromAlternate,
  923. BOOL fPutOnAlternate
  924. )
  925. /*++
  926. Routine Description:
  927. Get mapping entry based on index
  928. Arguments:
  929. iIndex -- index in mapping array
  930. pM -- updated with pointer to mapping. mapping object
  931. still owned by the mapper object.
  932. fGetFromAlternate -- TRUE if retrieve from alternate list
  933. fPutOnAlternate -- TRUE if put returned mapping on alternate list
  934. Returns:
  935. TRUE if success, FALSE if error
  936. --*/
  937. {
  938. if ( fPutOnAlternate )
  939. {
  940. // create alternate list if not exist
  941. if ( !m_pAltMapping && m_cMapping )
  942. {
  943. m_pAltMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*(m_cMapping) );
  944. if ( m_pAltMapping == NULL )
  945. {
  946. return FALSE;
  947. }
  948. ZeroMemory( m_pAltMapping, sizeof(CIisMapping*) * m_cMapping );
  949. m_cAltMapping = m_cMapping;
  950. }
  951. if ( iIndex < m_cAltMapping )
  952. {
  953. if ( m_pAltMapping[iIndex] == NULL &&
  954. m_pMapping != NULL ) // work-around for compiler bug
  955. {
  956. // duplicate mapping to alternate list if not exist
  957. if ( m_pMapping[iIndex]->Clone( pM ) )
  958. {
  959. m_pAltMapping[iIndex] = *pM;
  960. }
  961. else
  962. {
  963. return FALSE;
  964. }
  965. }
  966. else
  967. {
  968. *pM = m_pAltMapping[iIndex];
  969. }
  970. return TRUE;
  971. }
  972. return FALSE;
  973. }
  974. if ( fGetFromAlternate &&
  975. m_pAltMapping &&
  976. iIndex < m_cAltMapping )
  977. {
  978. if ( m_pAltMapping[iIndex] )
  979. {
  980. *pM = m_pAltMapping[iIndex];
  981. }
  982. else
  983. {
  984. *pM = m_pMapping[iIndex];
  985. }
  986. return TRUE;
  987. }
  988. if ( iIndex < m_cMapping )
  989. {
  990. *pM = m_pMapping[iIndex];
  991. return TRUE;
  992. }
  993. return FALSE;
  994. }
  995. BOOL
  996. CIisAcctMapper::Update(
  997. DWORD iIndex,
  998. CIisMapping* pM
  999. )
  1000. /*++
  1001. Routine Description:
  1002. Update a mapping
  1003. Arguments:
  1004. iIndex -- index in mapping array
  1005. pM -- pointer to mapping.
  1006. Returns:
  1007. TRUE if success, FALSE if error
  1008. --*/
  1009. {
  1010. if ( iIndex < m_cMapping )
  1011. {
  1012. pM->UpdateMask( m_pHierarchy, m_cHierarchy);
  1013. return m_pMapping[iIndex]->Copy( pM ) && UpdateClasses( FALSE );
  1014. }
  1015. return FALSE;
  1016. }
  1017. BOOL
  1018. CIisAcctMapper::Update(
  1019. DWORD iIndex
  1020. )
  1021. /*++
  1022. Routine Description:
  1023. Update a mapping
  1024. Arguments:
  1025. iIndex -- index in mapping array
  1026. Returns:
  1027. TRUE if success, FALSE if error
  1028. --*/
  1029. {
  1030. if ( iIndex < m_cMapping )
  1031. {
  1032. return m_pMapping[iIndex]->UpdateMask( m_pHierarchy, m_cHierarchy);
  1033. }
  1034. return FALSE;
  1035. }
  1036. BOOL
  1037. CIisAcctMapper::Add(
  1038. CIisMapping* pM,
  1039. BOOL fAlternate
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. Add a mapping entry to mapping array
  1044. Transfer ownership of mapping object to mapper
  1045. Arguments:
  1046. pM -- pointer to mapping to be added to mapper
  1047. fAlternate - TRUE if add to alternate list
  1048. Returns:
  1049. TRUE if success, FALSE if error
  1050. --*/
  1051. {
  1052. CIisMapping **pMapping;
  1053. if ( fAlternate )
  1054. {
  1055. DWORD dwC = m_pAltMapping ? m_cAltMapping : m_cMapping;
  1056. CIisMapping** pMap = m_pAltMapping ? m_pAltMapping : m_pMapping;
  1057. pMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*(dwC+1) );
  1058. if ( pMapping == NULL )
  1059. {
  1060. return FALSE;
  1061. }
  1062. if ( m_pAltMapping )
  1063. {
  1064. memcpy( pMapping, pMap, sizeof(CIisMapping*) * dwC );
  1065. LocalFree( m_pAltMapping );
  1066. }
  1067. else
  1068. {
  1069. ZeroMemory( pMapping, sizeof(CIisMapping*)*(dwC+1) );
  1070. }
  1071. m_pAltMapping = pMapping;
  1072. m_pAltMapping[dwC] = pM;
  1073. m_cAltMapping = dwC + 1;
  1074. return TRUE;
  1075. }
  1076. else
  1077. {
  1078. pMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*(m_cMapping+1) );
  1079. if ( pMapping == NULL )
  1080. {
  1081. return FALSE;
  1082. }
  1083. if ( m_pMapping )
  1084. {
  1085. memcpy( pMapping, m_pMapping, sizeof(CIisMapping*) * m_cMapping );
  1086. LocalFree( m_pMapping );
  1087. }
  1088. m_pMapping = pMapping;
  1089. pM->UpdateMask( m_pHierarchy, m_cHierarchy );
  1090. m_pMapping[m_cMapping] = pM;
  1091. ++m_cMapping;
  1092. SortMappings();
  1093. return UpdateClasses( FALSE );
  1094. }
  1095. }
  1096. DWORD
  1097. CIisAcctMapper::AddEx(
  1098. CIisMapping* pM
  1099. )
  1100. /*++
  1101. Routine Description:
  1102. Add a mapping entry to mapping array
  1103. Transfer ownership of mapping object to mapper
  1104. Arguments:
  1105. pM -- pointer to mapping to be added to mapper
  1106. Returns:
  1107. Index of entry if success, otherwise 0xffffffff
  1108. --*/
  1109. {
  1110. CIisMapping **pMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*(m_cMapping+1) );
  1111. if ( pMapping == NULL )
  1112. {
  1113. return 0xffffffff;
  1114. }
  1115. if ( m_pMapping )
  1116. {
  1117. memcpy( pMapping, m_pMapping, sizeof(CIisMapping*) * m_cMapping );
  1118. LocalFree( m_pMapping );
  1119. }
  1120. m_pMapping = pMapping;
  1121. pM->UpdateMask( m_pHierarchy, m_cHierarchy );
  1122. m_pMapping[m_cMapping] = pM;
  1123. ++m_cMapping;
  1124. SortMappings();
  1125. if ( UpdateClasses( FALSE ) )
  1126. {
  1127. return m_cMapping-1;
  1128. }
  1129. return 0xffffffff;
  1130. }
  1131. BOOL
  1132. CIisAcctMapper::Delete(
  1133. DWORD dwIndex,
  1134. BOOL fUseAlternate
  1135. )
  1136. /*++
  1137. Routine Description:
  1138. Delete a mapping entry based on index
  1139. Arguments:
  1140. iIndex -- index in mapping array
  1141. fUseAlternate -- TRUE if update alternate list
  1142. Returns:
  1143. TRUE if success, FALSE if error
  1144. --*/
  1145. {
  1146. UINT i;
  1147. UINT iM;
  1148. if ( fUseAlternate )
  1149. {
  1150. //
  1151. // clone all entries from main to alternate list
  1152. //
  1153. if ( !m_pAltMapping )
  1154. {
  1155. m_pAltMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*(m_cMapping) );
  1156. if ( m_pAltMapping == NULL )
  1157. {
  1158. return FALSE;
  1159. }
  1160. ZeroMemory( m_pAltMapping, sizeof(CIisMapping*) * m_cMapping );
  1161. m_cAltMapping = m_cMapping;
  1162. }
  1163. iM = min( m_cMapping, m_cAltMapping );
  1164. for ( i = 0 ; i < iM ; ++i )
  1165. {
  1166. if ( m_pAltMapping[i] == NULL )
  1167. {
  1168. if ( !m_pMapping[i]->Clone( &m_pAltMapping[i] ) )
  1169. {
  1170. return FALSE;
  1171. }
  1172. }
  1173. }
  1174. if ( dwIndex < m_cAltMapping )
  1175. {
  1176. delete m_pAltMapping[dwIndex];
  1177. memmove( m_pAltMapping+dwIndex,
  1178. m_pAltMapping+dwIndex+1,
  1179. (m_cAltMapping - dwIndex - 1) * sizeof(CIisMapping*) );
  1180. --m_cAltMapping;
  1181. return TRUE;
  1182. }
  1183. return FALSE;
  1184. }
  1185. if ( dwIndex < m_cMapping )
  1186. {
  1187. delete m_pMapping[dwIndex];
  1188. memmove( m_pMapping+dwIndex,
  1189. m_pMapping+dwIndex+1,
  1190. (m_cMapping - dwIndex - 1) * sizeof(CIisMapping*) );
  1191. --m_cMapping;
  1192. return UpdateClasses( FALSE );
  1193. }
  1194. return FALSE;
  1195. }
  1196. BOOL
  1197. CIisAcctMapper::Save(
  1198. )
  1199. /*++
  1200. Routine Description:
  1201. Save mapper ( mappings, hierarchy, derived class private data )
  1202. to a file, updating registry entry with MD5 signature
  1203. Arguments:
  1204. None
  1205. Returns:
  1206. TRUE if success, FALSE if error
  1207. --*/
  1208. {
  1209. UINT x;
  1210. FILE * fOut = NULL;
  1211. BOOL fSt = TRUE;
  1212. DWORD dwVal;
  1213. IIS_CRYPTO_STORAGE storage;
  1214. PIIS_CRYPTO_BLOB blob;
  1215. Lock();
  1216. MD5Init( &m_md5 );
  1217. if ( FAILED(storage.Initialize()) )
  1218. {
  1219. fSt = FALSE;
  1220. goto cleanup;
  1221. }
  1222. if ( m_pSesKey != NULL )
  1223. {
  1224. LocalFree( m_pSesKey );
  1225. m_pSesKey = NULL;
  1226. m_dwSesKey = 0;
  1227. }
  1228. if ( FAILED( storage.GetSessionKeyBlob( &blob ) ) ||
  1229. blob == NULL )
  1230. {
  1231. fSt = FALSE;
  1232. goto cleanup;
  1233. }
  1234. m_dwSesKey = IISCryptoGetBlobLength( blob );
  1235. if ( (m_pSesKey = (LPBYTE)LocalAlloc( LMEM_FIXED, m_dwSesKey)) == NULL )
  1236. {
  1237. m_dwSesKey = 0;
  1238. fSt = FALSE;
  1239. goto cleanup;
  1240. }
  1241. memcpy( m_pSesKey, (LPBYTE)blob, m_dwSesKey );
  1242. if ( (fOut = fopen( m_achFileName, "wb" )) == NULL )
  1243. {
  1244. fSt = FALSE;
  1245. goto cleanup;
  1246. }
  1247. // magic value & version
  1248. dwVal = IISMDB_FILE_MAGIC_VALUE;
  1249. if( fwrite( (LPVOID)&dwVal, sizeof(dwVal), 1, fOut ) != 1 )
  1250. {
  1251. fSt = FALSE;
  1252. goto cleanup;
  1253. }
  1254. MD5Update( &m_md5, (LPBYTE)&dwVal, sizeof(dwVal) );
  1255. dwVal = IISMDB_CURRENT_VERSION;
  1256. if( fwrite( (LPVOID)&dwVal, sizeof(dwVal), 1, fOut ) != 1 )
  1257. {
  1258. fSt = FALSE;
  1259. goto cleanup;
  1260. }
  1261. MD5Update( &m_md5, (LPBYTE)&dwVal, sizeof(dwVal) );
  1262. // mappings
  1263. if( fwrite( (LPVOID)&m_cMapping, sizeof(m_cMapping), 1, fOut ) != 1 )
  1264. {
  1265. fSt = FALSE;
  1266. goto cleanup;
  1267. }
  1268. MD5Update( &m_md5, (LPBYTE)&m_cMapping, sizeof(m_cMapping) );
  1269. for ( x = 0 ; x < m_cMapping ; ++x )
  1270. {
  1271. if ( !m_pMapping[x]->Serialize( fOut ,(VALID_CTX)&m_md5, (LPVOID)&storage) )
  1272. {
  1273. fSt = FALSE;
  1274. goto cleanup;
  1275. }
  1276. }
  1277. // save hierarchy
  1278. if( fwrite( (LPVOID)&m_cHierarchy, sizeof(m_cHierarchy), 1, fOut ) != 1 )
  1279. {
  1280. fSt = FALSE;
  1281. goto cleanup;
  1282. }
  1283. MD5Update( &m_md5, (LPBYTE)&m_cHierarchy, sizeof(m_cHierarchy) );
  1284. if( fwrite( (LPVOID)m_pHierarchy, sizeof(IISMDB_HEntry), m_cHierarchy, fOut ) != m_cHierarchy )
  1285. {
  1286. fSt = FALSE;
  1287. goto cleanup;
  1288. }
  1289. MD5Update( &m_md5, (LPBYTE)m_pHierarchy, sizeof(IISMDB_HEntry)*m_cHierarchy );
  1290. // save private data
  1291. fSt = SavePrivate( fOut, (VALID_CTX)&m_md5 );
  1292. MD5Final( &m_md5 );
  1293. cleanup:
  1294. if ( fOut != NULL )
  1295. {
  1296. fclose( fOut );
  1297. }
  1298. // update registry
  1299. if ( !fSt )
  1300. {
  1301. ZeroMemory( m_md5.digest, sizeof(m_md5.digest) );
  1302. }
  1303. Unlock();
  1304. return fSt;
  1305. }
  1306. BOOL
  1307. CIisAcctMapper::Reset(
  1308. )
  1309. /*++
  1310. Routine Description:
  1311. Reset mapper to empty state
  1312. Arguments:
  1313. None
  1314. Returns:
  1315. TRUE if success, FALSE if error
  1316. --*/
  1317. {
  1318. UINT x;
  1319. // free all mapping
  1320. if ( m_pMapping != NULL )
  1321. {
  1322. for ( x = 0 ; x < m_cMapping ; ++x )
  1323. {
  1324. delete m_pMapping[x];
  1325. }
  1326. LocalFree( m_pMapping );
  1327. m_pMapping = NULL;
  1328. }
  1329. m_cMapping = 0;
  1330. if ( m_pClasses != NULL )
  1331. {
  1332. LocalFree( m_pClasses );
  1333. m_pClasses = NULL;
  1334. }
  1335. // default hierarchy
  1336. if ( m_pHierarchy == NULL )
  1337. {
  1338. IISMDB_HEntry *pH = GetDefaultHierarchy( &m_cHierarchy );
  1339. m_pHierarchy = (IISMDB_HEntry*)LocalAlloc( LMEM_FIXED, sizeof(IISMDB_HEntry)*m_cHierarchy );
  1340. if ( m_pHierarchy == NULL )
  1341. {
  1342. return FALSE;
  1343. }
  1344. memcpy( m_pHierarchy, pH, m_cHierarchy * sizeof(IISMDB_HEntry) );
  1345. }
  1346. return ResetPrivate();
  1347. }
  1348. BOOL
  1349. CIisAcctMapper::Load(
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. Load mapper ( mappings, hierarchy, derived class private data )
  1354. from a file, checking registry entry for MD5 signature
  1355. Arguments:
  1356. None
  1357. Returns:
  1358. TRUE if success, FALSE if error
  1359. --*/
  1360. {
  1361. UINT x;
  1362. MD5_CTX md5Check;
  1363. FILE * fIn;
  1364. BOOL fSt = TRUE;
  1365. DWORD dwVal;
  1366. IIS_CRYPTO_STORAGE storage;
  1367. Reset();
  1368. MD5Init( &md5Check );
  1369. if ( FAILED( storage.Initialize( (PIIS_CRYPTO_BLOB)m_pSesKey ) ) )
  1370. {
  1371. return FALSE;
  1372. }
  1373. if ( (fIn = fopen( m_achFileName, "rb" )) == NULL )
  1374. {
  1375. return FALSE;
  1376. }
  1377. // magic value & version
  1378. if( fread( (LPVOID)&dwVal, sizeof(dwVal), 1, fIn ) != 1 )
  1379. {
  1380. fSt = FALSE;
  1381. goto cleanup;
  1382. }
  1383. if ( dwVal != IISMDB_FILE_MAGIC_VALUE )
  1384. {
  1385. SetLastError( ERROR_BAD_FORMAT );
  1386. fSt = FALSE;
  1387. goto cleanup;
  1388. }
  1389. MD5Update( &md5Check, (LPBYTE)&dwVal, sizeof(dwVal) );
  1390. if( fread( (LPVOID)&dwVal, sizeof(dwVal), 1, fIn ) != 1 )
  1391. {
  1392. fSt = FALSE;
  1393. goto cleanup;
  1394. }
  1395. MD5Update( &md5Check, (LPBYTE)&dwVal, sizeof(dwVal) );
  1396. // mappings
  1397. if( fread( (LPVOID)&m_cMapping, sizeof(m_cMapping), 1, fIn ) != 1 )
  1398. {
  1399. fSt = FALSE;
  1400. goto cleanup;
  1401. }
  1402. MD5Update( &md5Check, (LPBYTE)&m_cMapping, sizeof(m_cMapping) );
  1403. m_pMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*m_cMapping );
  1404. if ( m_pMapping == NULL )
  1405. {
  1406. fSt = FALSE;
  1407. goto cleanup;
  1408. }
  1409. for ( x = 0 ; x < m_cMapping ; ++x )
  1410. {
  1411. if ( (m_pMapping[x] = CreateNewMapping()) == NULL )
  1412. {
  1413. m_cMapping = x;
  1414. fSt = FALSE;
  1415. goto cleanup;
  1416. }
  1417. if ( !m_pMapping[x]->Deserialize( fIn ,(VALID_CTX)&md5Check, (LPVOID)&storage ) )
  1418. {
  1419. m_cMapping = x;
  1420. fSt = FALSE;
  1421. goto cleanup;
  1422. }
  1423. }
  1424. // load hierarchy
  1425. if( fread( (LPVOID)&m_cHierarchy, sizeof(m_cHierarchy), 1, fIn ) != 1 )
  1426. {
  1427. fSt = FALSE;
  1428. goto cleanup;
  1429. }
  1430. MD5Update( &md5Check, (LPBYTE)&m_cHierarchy, sizeof(m_cHierarchy) );
  1431. m_pHierarchy = (IISMDB_HEntry*)LocalAlloc( LMEM_FIXED, sizeof(IISMDB_HEntry)*m_cHierarchy );
  1432. if ( m_pHierarchy == NULL )
  1433. {
  1434. fSt = FALSE;
  1435. goto cleanup;
  1436. }
  1437. if( fread( (LPVOID)m_pHierarchy, sizeof(IISMDB_HEntry), m_cHierarchy, fIn ) != m_cHierarchy )
  1438. {
  1439. fSt = FALSE;
  1440. goto cleanup;
  1441. }
  1442. //
  1443. // insure hierarchy correct
  1444. //
  1445. for ( x = 0 ; x < m_cHierarchy; ++x )
  1446. {
  1447. if ( m_pHierarchy[x].m_dwIndex >= m_cFields )
  1448. {
  1449. fSt = FALSE;
  1450. goto cleanup;
  1451. }
  1452. }
  1453. MD5Update( &md5Check, (LPBYTE)m_pHierarchy, sizeof(IISMDB_HEntry)*m_cHierarchy );
  1454. // load private data
  1455. fSt = LoadPrivate( fIn, (VALID_CTX)&md5Check );
  1456. MD5Final( &md5Check );
  1457. #if 0
  1458. //
  1459. // Don't use signature for now - a metabase Restore operation
  1460. // may have restored another signature, so metabase and
  1461. // file won't match
  1462. //
  1463. if ( !(fSt = !memcmp( m_md5.digest,
  1464. md5Check.digest,
  1465. sizeof(md5Check.digest) )) )
  1466. {
  1467. SetLastError( ERROR_INVALID_ACCESS );
  1468. }
  1469. #endif
  1470. cleanup:
  1471. fclose( fIn );
  1472. if ( !fSt && GetLastError() != ERROR_INVALID_ACCESS )
  1473. {
  1474. Reset();
  1475. }
  1476. else
  1477. {
  1478. UpdateClasses();
  1479. }
  1480. if ( !fSt )
  1481. {
  1482. char achErr[32];
  1483. LPCTSTR pA[2];
  1484. pA[0] = m_achFileName;
  1485. pA[1] = achErr;
  1486. _itoa( GetLastError(), achErr, 10 );
  1487. ReportIisMapEvent( EVENTLOG_ERROR_TYPE,
  1488. IISMAP_EVENT_LOAD_ERROR,
  1489. 2,
  1490. pA );
  1491. }
  1492. return fSt;
  1493. }
  1494. // CIisCert11Mapper
  1495. CIisCert11Mapper::CIisCert11Mapper(
  1496. )
  1497. /*++
  1498. Routine Description:
  1499. Constructor for CIisCert11Mapper
  1500. Arguments:
  1501. None
  1502. Returns:
  1503. Nothing
  1504. --*/
  1505. {
  1506. m_pIssuers = NULL;
  1507. m_cIssuers = 0;
  1508. m_pFields = IisCert11MappingFields;
  1509. m_cFields = sizeof(IisCert11MappingFields)/sizeof(IISMDB_Fields);
  1510. m_dwOptions = IISMDB_CERT11_OPTIONS;
  1511. }
  1512. CIisCert11Mapper::~CIisCert11Mapper(
  1513. )
  1514. /*++
  1515. Routine Description:
  1516. Destructor for CIisCert11Mapper
  1517. Arguments:
  1518. None
  1519. Returns:
  1520. Nothing
  1521. --*/
  1522. {
  1523. }
  1524. BOOL
  1525. CIisCert11Mapper::Add(
  1526. CIisMapping* pM
  1527. )
  1528. /*++
  1529. Routine Description:
  1530. Add a mapping entry to mapping array
  1531. Transfer ownership of mapping object to mapper
  1532. Check is mapping to same NT account does not already exist.
  1533. Arguments:
  1534. pM -- pointer to mapping to be added to mapper
  1535. Returns:
  1536. TRUE if success, FALSE if error
  1537. --*/
  1538. {
  1539. UINT x;
  1540. // check if NT acct not already present.
  1541. // if so, return FALSE, SetLastError( ERROR_INVALID_PARAMETER );
  1542. if ( pM == NULL )
  1543. {
  1544. return FALSE;
  1545. }
  1546. LPSTR pCe;
  1547. DWORD dwCe;
  1548. LPSTR pCeIter;
  1549. DWORD dwCeIter;
  1550. if ( !pM->MappingGetField( IISMDB_INDEX_CERT11_CERT, (PBYTE *) &pCe, &dwCe, FALSE )
  1551. || pCe == NULL )
  1552. {
  1553. dwCe = 0;
  1554. }
  1555. for ( x = 0 ; x < m_cMapping ; ++x )
  1556. {
  1557. if ( !m_pMapping[x]->MappingGetField( IISMDB_INDEX_CERT11_CERT, (PBYTE *) &pCeIter, &dwCeIter, FALSE )
  1558. || pCeIter == NULL )
  1559. {
  1560. dwCeIter = 0;
  1561. }
  1562. if ( dwCe == dwCeIter && !memcmp( pCe, pCeIter, dwCe ) )
  1563. {
  1564. SetLastError( ERROR_INVALID_PARAMETER );
  1565. return FALSE;
  1566. }
  1567. }
  1568. return CIisAcctMapper::Add( pM );
  1569. }
  1570. IISMDB_HEntry*
  1571. CIisCert11Mapper::GetDefaultHierarchy(
  1572. LPDWORD pdwN
  1573. )
  1574. /*++
  1575. Routine Description:
  1576. return ptr to default hierarchy for certificates mapping
  1577. Arguments:
  1578. pdwN -- updated with hierarchy entries count
  1579. Returns:
  1580. ptr to hierarchy entries or NULL if error
  1581. --*/
  1582. {
  1583. *pdwN = sizeof(IisCert11MappingHierarchy) / sizeof(IISMDB_HEntry);
  1584. return IisCert11MappingHierarchy;
  1585. }
  1586. CIisMapping*
  1587. CIisCert11Mapper::CreateNewMapping(
  1588. LPBYTE pC,
  1589. DWORD dwC
  1590. )
  1591. /*++
  1592. Routine Description:
  1593. Create a new mapping from a certificate
  1594. Arguments:
  1595. pC -- cert ( ASN.1 format )
  1596. dwC -- length of cert
  1597. Returns:
  1598. ptr to mapping. ownership of this object is transfered to caller.
  1599. NULL if error
  1600. --*/
  1601. {
  1602. CCert11Mapping *pCM = new CCert11Mapping( this );
  1603. if ( pCM == NULL )
  1604. {
  1605. return NULL;
  1606. }
  1607. if ( pCM->Init( pC, dwC, m_pHierarchy, m_cHierarchy ) )
  1608. {
  1609. return (CIisMapping*)pCM;
  1610. }
  1611. delete pCM;
  1612. return NULL;
  1613. }
  1614. BOOL
  1615. CIisCert11Mapper::ResetPrivate(
  1616. )
  1617. /*++
  1618. Routine Description:
  1619. Reset CIisCert11Mapper issuer list
  1620. Arguments:
  1621. None
  1622. Returns:
  1623. TRUE if success, FALSE if error
  1624. --*/
  1625. {
  1626. // free issuer list
  1627. if ( m_pIssuers != NULL )
  1628. {
  1629. for ( UINT x = 0 ; x < m_cIssuers ; ++x )
  1630. {
  1631. LocalFree( m_pIssuers[x].pbIssuer );
  1632. }
  1633. LocalFree( m_pIssuers );
  1634. m_pIssuers = NULL;
  1635. }
  1636. m_cIssuers = 0;
  1637. return TRUE;
  1638. }
  1639. BOOL
  1640. CIisCert11Mapper::LoadPrivate(
  1641. FILE* fIn,
  1642. VALID_CTX pMD5
  1643. )
  1644. /*++
  1645. Routine Description:
  1646. Load issuer list
  1647. Arguments:
  1648. fIn -- file to read from
  1649. pMD5 -- MD5 to update with signature from input byte stream
  1650. Returns:
  1651. TRUE if success, FALSE if error
  1652. --*/
  1653. {
  1654. BOOL fSt = TRUE;
  1655. UINT x;
  1656. UINT cLen;
  1657. CHAR achBuf[64];
  1658. if( fread( (LPVOID)&m_cIssuers, sizeof(m_cIssuers), 1, fIn ) != 1 )
  1659. {
  1660. fSt = FALSE;
  1661. goto cleanup;
  1662. }
  1663. MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_cIssuers, sizeof(m_cIssuers) );
  1664. m_pIssuers = (IssuerAccepted*)LocalAlloc( LMEM_FIXED, sizeof(IssuerAccepted)*m_cIssuers );
  1665. if ( m_pIssuers == NULL )
  1666. {
  1667. fSt = FALSE;
  1668. goto cleanup;
  1669. }
  1670. for ( x = 0 ; x < m_cIssuers ; ++x )
  1671. {
  1672. if ( fread( (LPVOID)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen), 1, fIn ) != 1 )
  1673. {
  1674. m_cIssuers = x;
  1675. fSt = FALSE;
  1676. goto cleanup;
  1677. }
  1678. MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen) );
  1679. if ( (m_pIssuers[x].pbIssuer = (LPBYTE)LocalAlloc( LMEM_FIXED, m_pIssuers[x].cbIssuerLen )) == NULL )
  1680. {
  1681. m_cIssuers = x;
  1682. fSt = FALSE;
  1683. goto cleanup;
  1684. }
  1685. if ( fread( m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen, 1, fIn ) != 1 )
  1686. {
  1687. m_cIssuers = x;
  1688. fSt = FALSE;
  1689. goto cleanup;
  1690. }
  1691. MD5Update( (MD5_CTX*)pMD5, m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen );
  1692. }
  1693. //
  1694. // Read subject source (read to comply with legacy format)
  1695. //
  1696. if( Iisfgets( achBuf, sizeof(achBuf), fIn ) == NULL )
  1697. {
  1698. fSt = FALSE;
  1699. goto cleanup;
  1700. }
  1701. cLen = (DWORD) strlen(achBuf);
  1702. MD5Update( (MD5_CTX*)pMD5, (LPBYTE)achBuf, cLen );
  1703. //
  1704. // We don't save the "subject source"
  1705. // It is legacy value not used anywhere
  1706. //
  1707. //
  1708. // Read default domain (read to comply with legacy format)
  1709. //
  1710. if( Iisfgets( achBuf, sizeof(achBuf), fIn ) == NULL )
  1711. {
  1712. fSt = FALSE;
  1713. goto cleanup;
  1714. }
  1715. cLen = (DWORD) strlen(achBuf);
  1716. MD5Update( (MD5_CTX*)pMD5, (LPBYTE)achBuf, cLen );
  1717. //
  1718. // We don't save the "default domain"
  1719. // It is legacy value not used anywhere
  1720. //
  1721. cleanup:
  1722. return fSt;
  1723. }
  1724. BOOL
  1725. CIisCert11Mapper::SavePrivate(
  1726. FILE* fOut,
  1727. VALID_CTX pMD5
  1728. )
  1729. /*++
  1730. Routine Description:
  1731. Save issuer list
  1732. Arguments:
  1733. fOut -- file to write to
  1734. pMD5 -- MD5 to update with signature of output byte stream
  1735. Returns:
  1736. TRUE if success, FALSE if error
  1737. --*/
  1738. {
  1739. BOOL fSt = TRUE;
  1740. UINT x;
  1741. if( fwrite( (LPVOID)&m_cIssuers, sizeof(m_cIssuers), 1, fOut ) != 1 )
  1742. {
  1743. fSt = FALSE;
  1744. goto cleanup;
  1745. }
  1746. MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_cIssuers, sizeof(m_cIssuers) );
  1747. for ( x = 0 ; x < m_cIssuers ; ++x )
  1748. {
  1749. if ( fwrite( (LPVOID)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen), 1, fOut ) != 1 )
  1750. {
  1751. fSt = FALSE;
  1752. goto cleanup;
  1753. }
  1754. MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen) );
  1755. if ( fwrite( m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen, 1, fOut ) != 1 )
  1756. {
  1757. fSt = FALSE;
  1758. goto cleanup;
  1759. }
  1760. MD5Update( (MD5_CTX*)pMD5, m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen );
  1761. }
  1762. //
  1763. // Write subject source
  1764. // legacy value, we don't write it out any more
  1765. // write empty string to avoid potential compatibility issues
  1766. //
  1767. Iisfputs( "", fOut );
  1768. //
  1769. // Write default domain
  1770. // legacy value, we don't write it out any more
  1771. // write empty string to avoid potential compatibility issues
  1772. //
  1773. Iisfputs( "", fOut );
  1774. cleanup:
  1775. return fSt;
  1776. }
  1777. //static
  1778. INT
  1779. CIisCert11Mapper::Iisfputs(
  1780. const char* pBuf,
  1781. FILE* fOut
  1782. )
  1783. /*++
  1784. Routine Description:
  1785. write string to the output file
  1786. string will be terminated by new line
  1787. Arguments:
  1788. Returns:
  1789. TRUE if success, FALSE if error
  1790. --*/
  1791. {
  1792. return (fputs( pBuf, fOut ) == EOF || fputc( '\n', fOut ) == EOF)
  1793. ? EOF
  1794. : 0;
  1795. }
  1796. //static
  1797. LPSTR
  1798. CIisCert11Mapper::Iisfgets(
  1799. LPSTR pBuf,
  1800. INT cMax,
  1801. FILE* fIn
  1802. )
  1803. /*++
  1804. Routine Description:
  1805. Read string from the output file
  1806. string is terminated by new line
  1807. Arguments:
  1808. Returns:
  1809. TRUE if success, FALSE if error
  1810. --*/
  1811. {
  1812. LPSTR pszWas = pBuf;
  1813. INT ch = 0;
  1814. while ( cMax > 1 && (ch=fgetc(fIn))!= EOF && ch != '\n' )
  1815. {
  1816. *pBuf++ = (CHAR)ch;
  1817. --cMax;
  1818. }
  1819. if ( ch != EOF )
  1820. {
  1821. *pBuf = '\0';
  1822. return pszWas;
  1823. }
  1824. return NULL;
  1825. }
  1826. // CCert11Mapping
  1827. CCert11Mapping::CCert11Mapping(
  1828. CIisAcctMapper* pMap
  1829. )
  1830. /*++
  1831. Routine Description:
  1832. Constructor for CCert11Mapping
  1833. Arguments:
  1834. pMap -- ptr to mapper object linked to this mapping
  1835. Returns:
  1836. Nothing
  1837. --*/
  1838. {
  1839. m_pMapper = (CIisAcctMapper*)pMap;
  1840. for ( int x = 0 ; x < sizeof(m_pFields)/sizeof(LPSTR) ; ++x )
  1841. {
  1842. m_pFields[x] = NULL;
  1843. }
  1844. for ( x = 0 ; x < sizeof(m_pFields)/sizeof(LPSTR) ; ++x )
  1845. {
  1846. m_cFields[x] = 0;
  1847. }
  1848. }
  1849. CCert11Mapping::~CCert11Mapping(
  1850. )
  1851. /*++
  1852. Routine Description:
  1853. Destructor for CCert11Mapping
  1854. Arguments:
  1855. None
  1856. Returns:
  1857. Nothing
  1858. --*/
  1859. {
  1860. }
  1861. BOOL
  1862. CCert11Mapping::Init(
  1863. LPBYTE pC,
  1864. DWORD dwC,
  1865. IISMDB_HEntry *pH,
  1866. DWORD dwH
  1867. )
  1868. /*++
  1869. Routine Description:
  1870. Constructor for CCert11Mapping
  1871. Arguments:
  1872. pC -- cert ( ASN.1 format )
  1873. dwC -- length of cert
  1874. pH -- ptr to hierarchy info
  1875. dwH -- number of hierarchy entries
  1876. Returns:
  1877. TRUE if success, FALSE if error
  1878. --*/
  1879. {
  1880. StoreFieldRef( IISMDB_INDEX_CERT11_CERT, (LPSTR)pC, dwC );
  1881. UpdateMask( pH, dwH );
  1882. return TRUE;
  1883. }
  1884. BOOL
  1885. CCert11Mapping::MappingSetField(
  1886. DWORD dwIndex,
  1887. LPSTR pszNew
  1888. )
  1889. /*++
  1890. Routine Description:
  1891. Set field in mapping entry to specified content
  1892. data pointed by pszNew is copied inside mapping entry
  1893. Arguments:
  1894. dwIndex -- index of field
  1895. pszNew -- data to copy inside field
  1896. Returns:
  1897. TRUE if success, FALSE if error
  1898. Lock:
  1899. mapper must be locked for ptr to remain valid
  1900. --*/
  1901. {
  1902. LPSTR *pFields;
  1903. LPDWORD pcFields;
  1904. DWORD iMax = GetNbField( &pFields, &pcFields );
  1905. if ( dwIndex >= iMax )
  1906. {
  1907. return FALSE;
  1908. }
  1909. return StoreField( pFields, pcFields, dwIndex, iMax, pszNew, (DWORD) strlen(pszNew)+1, FALSE );
  1910. }
  1911. // CIisMapping
  1912. CIisMapping::CIisMapping(
  1913. )
  1914. /*++
  1915. Routine Description:
  1916. Constructor for CIisMapping
  1917. Arguments:
  1918. None
  1919. Returns:
  1920. Nothing
  1921. --*/
  1922. {
  1923. m_pBuff = NULL;
  1924. m_cUsedBuff = m_cAllocBuff = 0;
  1925. m_dwMask = 0;
  1926. }
  1927. BOOL
  1928. CIisMapping::CloneEx(
  1929. CIisMapping** ppM,
  1930. LPSTR* ppTargetS,
  1931. LPSTR* ppS,
  1932. LPDWORD pTargetC,
  1933. LPDWORD pC,
  1934. UINT cF
  1935. )
  1936. /*++
  1937. Routine Description:
  1938. Clone a mapping entry
  1939. Arguments:
  1940. Returns:
  1941. TRUE if success, otherwise FALSE
  1942. --*/
  1943. {
  1944. CIisMapping* pM = *ppM;
  1945. UINT i;
  1946. if ( ppTargetS && ppS )
  1947. {
  1948. //
  1949. // ppTargetS is already allocated by caller and has cF entries
  1950. //
  1951. memcpy( ppTargetS, ppS, sizeof(LPSTR*) * cF );
  1952. }
  1953. if ( pTargetC && pC )
  1954. {
  1955. //
  1956. // pTargetC is already allocated by caller and has cF entries
  1957. //
  1958. memcpy( pTargetC, pC, sizeof(DWORD) * cF );
  1959. }
  1960. if ( ( pM->m_pBuff = (LPBYTE)LocalAlloc( LMEM_FIXED, m_cAllocBuff ) ) == NULL )
  1961. {
  1962. delete pM;
  1963. *ppM = NULL;
  1964. return FALSE;
  1965. }
  1966. DBG_ASSERT( m_cAllocBuff >= m_cUsedBuff );
  1967. memcpy( pM->m_pBuff, m_pBuff, m_cUsedBuff );
  1968. pM->m_cUsedBuff = m_cUsedBuff;
  1969. pM->m_cAllocBuff = m_cAllocBuff;
  1970. pM->m_pMapper = m_pMapper;
  1971. pM->m_dwMask = m_dwMask;
  1972. //
  1973. // Adjust ptr to point to new buffer
  1974. //
  1975. for ( i = 0 ; i < cF ; ++i )
  1976. {
  1977. if ( ppTargetS[i] )
  1978. {
  1979. ppTargetS[i] += pM->m_pBuff - m_pBuff;
  1980. }
  1981. }
  1982. return TRUE;
  1983. }
  1984. BOOL
  1985. CIisMapping::UpdateMask(
  1986. IISMDB_HEntry* pH,
  1987. DWORD dwI
  1988. )
  1989. /*++
  1990. Routine Description:
  1991. Update mask of significant fields for a mapping object
  1992. Field is significant if not containing "*"
  1993. mask if bitmask of n bits where n is # of hierarchy entries
  1994. bit of rank m == 0 means field pointed by hierarchy entry n - 1 - m
  1995. is significant. ( i.e. MSB is hierarchy entry 0, the most significant )
  1996. Arguments:
  1997. pH -- ptr to hierarchy info
  1998. dwI -- number of hierarchy entries
  1999. Returns:
  2000. TRUE if success, FALSE if error
  2001. --*/
  2002. {
  2003. LPSTR *pFields;
  2004. LPDWORD pcFields;
  2005. LPSTR pF;
  2006. DWORD dwC;
  2007. int iMax;
  2008. m_dwMask = (1u << dwI)-1;
  2009. iMax = GetNbField( &pFields, &pcFields );
  2010. if ( pcFields )
  2011. {
  2012. for ( UINT x = 0 ; x < dwI ; ++x )
  2013. {
  2014. MappingGetField( pH[x].m_dwIndex, (PBYTE *) &pF, &dwC, FALSE );
  2015. if ( !pF || dwC != 1 || *pF != '*' )
  2016. {
  2017. m_dwMask &= ~(1u << (dwI - 1 - x) );
  2018. }
  2019. }
  2020. }
  2021. else
  2022. {
  2023. for ( UINT x = 0 ; x < dwI ; ++x )
  2024. {
  2025. MappingGetField( pH[x].m_dwIndex, &pF );
  2026. if ( !pF || strcmp( pF, "*" ) )
  2027. {
  2028. m_dwMask &= ~(1u << (dwI - 1 - x) );
  2029. }
  2030. }
  2031. }
  2032. return TRUE;
  2033. }
  2034. BOOL
  2035. CIisMapping::Copy(
  2036. CIisMapping* pM
  2037. )
  2038. /*++
  2039. Routine Description:
  2040. Copy the specified mapping in this
  2041. Arguments:
  2042. pM - ptr to mapping to duplicate
  2043. Returns:
  2044. TRUE if success, FALSE if error
  2045. --*/
  2046. {
  2047. LPSTR *pFields;
  2048. LPSTR pF;
  2049. UINT iMax = GetNbField( &pFields );
  2050. for ( UINT x = 0 ; x < iMax ; ++x )
  2051. {
  2052. if ( pM->MappingGetField( x, &pF ) && *pF )
  2053. {
  2054. if ( !MappingSetField( x, pF ) )
  2055. {
  2056. return FALSE;
  2057. }
  2058. }
  2059. }
  2060. return TRUE;
  2061. }
  2062. int
  2063. CIisMapping::Cmp(
  2064. CIisMapping* pM,
  2065. BOOL fCmpForMatch
  2066. )
  2067. /*++
  2068. Routine Description:
  2069. Compare 2 mappings, return -1, 0 or 1 as suitable for qsort or bsearch
  2070. Can compare either for full sort order ( using mask & significant fields )
  2071. or for a match ( not using mask )
  2072. Arguments:
  2073. pM -- ptr to mapping to compare to. This is to be used as the 2nd
  2074. entry for purpose of lexicographical order.
  2075. fCmpForMatch -- TRUE if comparing for a match inside a given mask class
  2076. Returns:
  2077. -1 if *this < *pM, 0 if *this == *pM, 1 if *this > *pM
  2078. --*/
  2079. {
  2080. DWORD dwCmpMask = 0xffffffff;
  2081. // if not compare for match, consider mask
  2082. if ( !fCmpForMatch )
  2083. {
  2084. if ( m_dwMask < pM->GetMask() )
  2085. {
  2086. return -1;
  2087. }
  2088. else if ( m_dwMask > pM->GetMask() )
  2089. {
  2090. return 1;
  2091. }
  2092. // mask are identical, have to consider fields
  2093. }
  2094. // compute common significant fields : bit is 1 if significant
  2095. dwCmpMask = (~m_dwMask) & (~pM->GetMask());
  2096. DWORD dwH;
  2097. IISMDB_HEntry* pH = m_pMapper->GetHierarchy( &dwH );
  2098. UINT x;
  2099. LPSTR *pFL;
  2100. LPDWORD pcFL;
  2101. GetNbField( &pFL, &pcFL );
  2102. for ( x = 0 ; x < dwH ; ++x )
  2103. {
  2104. if( ! (dwCmpMask & (1u << (dwH - 1 - x) )) )
  2105. {
  2106. continue;
  2107. }
  2108. LPSTR pA;
  2109. LPSTR pB;
  2110. DWORD dwA;
  2111. DWORD dwB;
  2112. int fC;
  2113. if ( pcFL ) // check if length available
  2114. {
  2115. MappingGetField( pH[x].m_dwIndex, (PBYTE *) &pA, &dwA, FALSE );
  2116. pM->MappingGetField( pH[x].m_dwIndex, (PBYTE *) &pB, &dwB, FALSE );
  2117. if ( pA == NULL )
  2118. {
  2119. dwA = 0;
  2120. }
  2121. if ( pB == NULL )
  2122. {
  2123. dwB = 0;
  2124. }
  2125. if ( dwA != dwB )
  2126. {
  2127. return dwA < dwB ? -1 : 1;
  2128. }
  2129. fC = memcmp( pA, pB, dwA );
  2130. }
  2131. else
  2132. {
  2133. MappingGetField( pH[x].m_dwIndex, &pA );
  2134. pM->MappingGetField( pH[x].m_dwIndex, &pB );
  2135. if ( pA == NULL )
  2136. {
  2137. pA = "";
  2138. }
  2139. if ( pB == NULL )
  2140. {
  2141. pB = "";
  2142. }
  2143. fC = strcmp( pA, pB );
  2144. }
  2145. if ( fC )
  2146. {
  2147. return fC;
  2148. }
  2149. }
  2150. return 0;
  2151. }
  2152. BOOL
  2153. CIisMapping::MappingGetField(
  2154. DWORD dwIndex,
  2155. LPSTR *pF
  2156. )
  2157. /*++
  2158. Routine Description:
  2159. Get ptr to field in mapping entry
  2160. ownership of field remains with mapping entry
  2161. Arguments:
  2162. dwIndex -- index of field
  2163. pF -- updated with ptr to field entry. can be NULL if
  2164. field empty.
  2165. Returns:
  2166. TRUE if success, FALSE if error
  2167. Lock:
  2168. mapper must be locked for ptr to remain valid
  2169. --*/
  2170. {
  2171. LPSTR *pFields;
  2172. DWORD iMax = GetNbField( &pFields );
  2173. if ( dwIndex >= iMax )
  2174. {
  2175. return FALSE;
  2176. }
  2177. *pF = pFields[dwIndex];
  2178. return TRUE;
  2179. }
  2180. BOOL
  2181. CIisMapping::MappingGetField(
  2182. DWORD dwIndex,
  2183. PBYTE *ppbF,
  2184. LPDWORD pcbF,
  2185. BOOL fUuEncode
  2186. )
  2187. /*++
  2188. Routine Description:
  2189. Get ptr to field in mapping entry
  2190. ownership of field remains with mapping entry
  2191. Arguments:
  2192. dwIndex -- index of field
  2193. ppbF -- updated with ptr to field entry. can be NULL if
  2194. field empty.
  2195. pcbF -- updated with length of fields, 0 if empty
  2196. fUuEncode -- TRUE if result is to be uuencoded.
  2197. if TRUE, caller must LocalFree( *pF )
  2198. Returns:
  2199. TRUE if success, FALSE if error
  2200. Lock:
  2201. mapper must be locked for ptr to remain valid
  2202. --*/
  2203. {
  2204. LPSTR *pFields;
  2205. LPDWORD pcFields;
  2206. DWORD iMax = GetNbField( &pFields, &pcFields );
  2207. if ( dwIndex >= iMax )
  2208. {
  2209. return FALSE;
  2210. }
  2211. if ( fUuEncode )
  2212. {
  2213. LPSTR pU = (LPSTR)LocalAlloc( LMEM_FIXED, ((pcFields[dwIndex]+3)*4)/3+1 );
  2214. if ( pU == NULL )
  2215. {
  2216. return FALSE;
  2217. }
  2218. IISuuencode( (LPBYTE)pFields[dwIndex], pcFields[dwIndex], (LPBYTE)pU, FALSE );
  2219. *ppbF = (PBYTE) pU;
  2220. *pcbF = (DWORD) strlen(pU);
  2221. }
  2222. else
  2223. {
  2224. *ppbF = (PBYTE) pFields[dwIndex];
  2225. *pcbF = pcFields[dwIndex];
  2226. }
  2227. return TRUE;
  2228. }
  2229. BOOL
  2230. CIisMapping::MappingSetField(
  2231. DWORD dwIndex,
  2232. LPSTR pszNew
  2233. )
  2234. /*++
  2235. Routine Description:
  2236. Set field in mapping entry to specified content
  2237. data pointed by pszNew is copied inside mapping entry
  2238. Arguments:
  2239. dwIndex -- index of field
  2240. pszNew -- data to copy inside field
  2241. Returns:
  2242. TRUE if success, FALSE if error
  2243. Lock:
  2244. mapper must be locked for ptr to remain valid
  2245. --*/
  2246. {
  2247. LPSTR *pFields;
  2248. DWORD iMax = GetNbField( &pFields );
  2249. if ( dwIndex >= iMax )
  2250. {
  2251. return FALSE;
  2252. }
  2253. return StoreField( pFields, dwIndex, iMax, pszNew );
  2254. }
  2255. BOOL
  2256. CIisMapping::MappingSetField(
  2257. DWORD dwIndex,
  2258. PBYTE pbNew,
  2259. DWORD cbNew,
  2260. BOOL fIsUuEncoded
  2261. )
  2262. /*++
  2263. Routine Description:
  2264. Set field in mapping entry to specified content
  2265. data pointed by pszNew is copied inside mapping entry
  2266. Arguments:
  2267. dwIndex -- index of field
  2268. pbNew -- data to copy inside field
  2269. cbNew -- length of data
  2270. fIsUuEncoded -- TRUE if pszNew is UUEncoded
  2271. Returns:
  2272. TRUE if success, FALSE if error
  2273. Lock:
  2274. mapper must be locked for ptr to remain valid
  2275. --*/
  2276. {
  2277. LPSTR *pFields;
  2278. LPDWORD pcFields;
  2279. DWORD iMax = GetNbField( &pFields, &pcFields );
  2280. if ( dwIndex >= iMax )
  2281. {
  2282. return FALSE;
  2283. }
  2284. return StoreField( pFields, pcFields, dwIndex, iMax, (LPSTR) pbNew, cbNew, fIsUuEncoded );
  2285. }
  2286. BOOL
  2287. CIisMapping::StoreField(
  2288. LPSTR* ppszFields,
  2289. DWORD dwIndex,
  2290. DWORD dwNbIndex,
  2291. LPSTR pszNew
  2292. )
  2293. /*++
  2294. Routine Description:
  2295. Update field array in mapping entry with new field
  2296. data pointed by pszNew is copied inside mapping entry
  2297. Arguments:
  2298. ppszFields -- array of field pointers to be updated
  2299. dwIndex -- index of field
  2300. dwNbIndex -- number of fields in array
  2301. pszNew -- data to copy inside field
  2302. Returns:
  2303. TRUE if success, FALSE if error
  2304. --*/
  2305. {
  2306. UINT x;
  2307. // pszOld is assumed to point inside m_pBuff if non NULL
  2308. // is has to be removed
  2309. LPSTR pszOld = ppszFields[dwIndex];
  2310. if ( pszOld && m_pBuff && (LPBYTE)pszOld > m_pBuff && (LPBYTE)pszOld < m_pBuff+m_cUsedBuff )
  2311. {
  2312. DWORD lO = (DWORD) strlen( pszOld ) + 1;
  2313. DWORD lM = (DWORD) DIFF((m_pBuff + m_cUsedBuff) - (LPBYTE)pszOld) - lO;
  2314. if ( lM )
  2315. {
  2316. // remove the old field from the middle of the m_pBuff
  2317. // new value will be then appended to the end to the m_pBuff
  2318. memmove( pszOld, pszOld + lO, lM );
  2319. for ( x = 0 ; x < dwNbIndex ; ++x )
  2320. {
  2321. if ( x != dwIndex && ppszFields[x] > pszOld )
  2322. {
  2323. ppszFields[x] -= lO;
  2324. }
  2325. }
  2326. }
  2327. ppszFields[ dwIndex ] = NULL;
  2328. m_cUsedBuff -= lO;
  2329. }
  2330. // pszNew is to appended to m_pBuff
  2331. DWORD lN = (DWORD) strlen( pszNew ) + 1;
  2332. if ( m_cUsedBuff + lN > m_cAllocBuff )
  2333. {
  2334. UINT cNewBuff = (( m_cUsedBuff + lN + IIS_MAP_BUFF_GRAN ) / IIS_MAP_BUFF_GRAN) * IIS_MAP_BUFF_GRAN;
  2335. LPSTR pNewBuff = (LPSTR)LocalAlloc( LMEM_FIXED, cNewBuff );
  2336. if ( pNewBuff == NULL )
  2337. {
  2338. return FALSE;
  2339. }
  2340. if ( m_pBuff )
  2341. {
  2342. DBG_ASSERT( m_cUsedBuff <= cNewBuff );
  2343. memcpy( pNewBuff, m_pBuff, m_cUsedBuff );
  2344. LocalFree( m_pBuff );
  2345. }
  2346. m_cAllocBuff = cNewBuff;
  2347. // adjust pointers
  2348. for ( x = 0 ; x < dwNbIndex ; ++x )
  2349. {
  2350. if ( x != dwIndex )
  2351. {
  2352. if ( ppszFields[x] != NULL )
  2353. {
  2354. ppszFields[x] += ((LPBYTE)pNewBuff - m_pBuff);
  2355. }
  2356. }
  2357. }
  2358. m_pBuff = (LPBYTE)pNewBuff;
  2359. }
  2360. DBG_ASSERT( m_cAllocBuff - m_cUsedBuff >= lN );
  2361. memcpy( m_pBuff + m_cUsedBuff, pszNew, lN );
  2362. ppszFields[dwIndex] = (LPSTR)(m_pBuff + m_cUsedBuff);
  2363. m_cUsedBuff += lN;
  2364. return TRUE;
  2365. }
  2366. BOOL
  2367. CIisMapping::StoreField(
  2368. LPSTR* ppszFields,
  2369. LPDWORD ppdwFields,
  2370. DWORD dwIndex,
  2371. DWORD dwNbIndex,
  2372. LPSTR pbNew,
  2373. DWORD cNew,
  2374. BOOL fIsUuEncoded
  2375. )
  2376. /*++
  2377. Routine Description:
  2378. Update field array in mapping entry with new field
  2379. data pointed by pszNew is copied inside mapping entry
  2380. Arguments:
  2381. ppszFields -- array of field pointers to be updated
  2382. ppdwFields -- array of field length to be updated
  2383. dwIndex -- index of field
  2384. dwNbIndex -- number of fields in array
  2385. pbNew -- data to copy inside field
  2386. cNew -- length of data
  2387. fIsUuEncoded -- TRUE if pbNew is UUEncoded
  2388. Returns:
  2389. TRUE if success, FALSE if error
  2390. --*/
  2391. {
  2392. UINT x;
  2393. // pszOld is assumed to point inside m_pBuff if non NULL
  2394. // it has to be removed
  2395. LPSTR pszOld = ppszFields[dwIndex];
  2396. if ( pszOld && m_pBuff && (LPBYTE)pszOld > m_pBuff && (LPBYTE)pszOld < m_pBuff+m_cUsedBuff )
  2397. {
  2398. DWORD lO = ppdwFields[dwIndex];
  2399. DWORD lM = (DWORD) DIFF((m_pBuff + m_cUsedBuff) - (LPBYTE)pszOld) - lO;
  2400. if ( lM )
  2401. {
  2402. // remove the old field from the middle of the m_pBuff
  2403. // new value will be then appended to the end of m_pBuff
  2404. //
  2405. memmove( pszOld, pszOld + lO, lM );
  2406. for ( x = 0 ; x < dwNbIndex ; ++x )
  2407. {
  2408. if ( x != dwIndex && ppszFields[x] > pszOld )
  2409. {
  2410. ppszFields[x] -= lO;
  2411. }
  2412. }
  2413. }
  2414. ppszFields[ dwIndex ] = NULL;
  2415. m_cUsedBuff -= lO;
  2416. }
  2417. // pszNew is to appended to m_pBuff
  2418. UINT lN = cNew;
  2419. if ( fIsUuEncoded )
  2420. {
  2421. LPSTR pU = (LPSTR)LocalAlloc( LMEM_FIXED, lN + 3);
  2422. if ( pU == NULL )
  2423. {
  2424. return FALSE;
  2425. }
  2426. DWORD cO;
  2427. IISuudecode( pbNew, (LPBYTE)pU, &cO, FALSE );
  2428. pbNew = pU;
  2429. cNew = lN = cO;
  2430. }
  2431. if ( m_cUsedBuff + lN > m_cAllocBuff )
  2432. {
  2433. UINT cNewBuff = (( m_cUsedBuff + lN + IIS_MAP_BUFF_GRAN ) / IIS_MAP_BUFF_GRAN) * IIS_MAP_BUFF_GRAN;
  2434. LPSTR pNewBuff = (LPSTR)LocalAlloc( LMEM_FIXED, cNewBuff );
  2435. if ( pNewBuff == NULL )
  2436. {
  2437. if ( fIsUuEncoded )
  2438. {
  2439. LocalFree( pbNew );
  2440. }
  2441. return FALSE;
  2442. }
  2443. if ( m_pBuff )
  2444. {
  2445. DBG_ASSERT( cNewBuff >= m_cUsedBuff );
  2446. memcpy( pNewBuff, m_pBuff, m_cUsedBuff );
  2447. LocalFree( m_pBuff );
  2448. }
  2449. m_cAllocBuff = cNewBuff;
  2450. // adjust pointers
  2451. for ( x = 0 ; x < dwNbIndex ; ++x )
  2452. {
  2453. if ( x != dwIndex )
  2454. {
  2455. if ( ppszFields[x] != NULL )
  2456. {
  2457. ppszFields[x] += ((LPBYTE)pNewBuff - m_pBuff);
  2458. }
  2459. }
  2460. }
  2461. m_pBuff = (LPBYTE)pNewBuff;
  2462. }
  2463. DBG_ASSERT( m_cAllocBuff - m_cUsedBuff >= lN );
  2464. memcpy( m_pBuff + m_cUsedBuff, pbNew, lN );
  2465. ppszFields[dwIndex] = (LPSTR)(m_pBuff + m_cUsedBuff);
  2466. if ( ppdwFields )
  2467. {
  2468. ppdwFields[dwIndex] = cNew;
  2469. }
  2470. m_cUsedBuff += lN;
  2471. if ( fIsUuEncoded )
  2472. {
  2473. LocalFree( pbNew );
  2474. }
  2475. return TRUE;
  2476. }
  2477. BOOL
  2478. CIisMapping::Serialize(
  2479. FILE* pFile,
  2480. VALID_CTX pMD5,
  2481. LPVOID pStorage
  2482. )
  2483. /*++
  2484. Routine Description:
  2485. Serialize a mapping entry
  2486. Arguments:
  2487. pFile -- file to write to
  2488. pMD5 -- MD5 to update with signature of written bytes
  2489. Returns:
  2490. TRUE if success, FALSE if error
  2491. Lock:
  2492. mapper must be locked while serializing
  2493. --*/
  2494. {
  2495. LPSTR *pFields;
  2496. LPDWORD pcFields;
  2497. LPSTR pO = NULL;
  2498. DWORD dwO = 0;
  2499. UINT iMax = GetNbField( &pFields, &pcFields );
  2500. UINT x;
  2501. LPBYTE pB = NULL;
  2502. BOOL fMustFree = FALSE;
  2503. for ( x = 0 ; x < iMax ; ++x )
  2504. {
  2505. LPSTR pF;
  2506. DWORD dwF;
  2507. fMustFree = FALSE;
  2508. if ( pcFields )
  2509. {
  2510. MappingGetField( x, (PBYTE *) &pF, &dwF, FALSE );
  2511. MD5Update( (MD5_CTX*)pMD5, (LPBYTE)pF, dwF );
  2512. store_as_binary:
  2513. if ( IsCrypt( x ) && dwF )
  2514. {
  2515. if ( FAILED(((IIS_CRYPTO_STORAGE*)pStorage)->EncryptData(
  2516. (PIIS_CRYPTO_BLOB*)&pB,
  2517. pF,
  2518. dwF,
  2519. REG_BINARY )) )
  2520. {
  2521. return FALSE;
  2522. }
  2523. pF = (LPSTR)pB;
  2524. dwF = IISCryptoGetBlobLength( (PIIS_CRYPTO_BLOB)pB );
  2525. fMustFree = TRUE;
  2526. }
  2527. if ( dwF )
  2528. {
  2529. DWORD dwNeed = ((dwF+2)*4)/3 + 1;
  2530. if ( dwNeed > dwO )
  2531. {
  2532. if ( pO != NULL )
  2533. {
  2534. LocalFree( pO );
  2535. }
  2536. dwNeed += 100; // alloc more than needed
  2537. // to minimize # of allocation
  2538. if ( (pO = (LPSTR)LocalAlloc( LMEM_FIXED, dwNeed )) == NULL )
  2539. {
  2540. return FALSE;
  2541. }
  2542. dwO = dwNeed;
  2543. }
  2544. /* INTRINSA suppress = null */
  2545. IISuuencode( (LPBYTE)pF, dwF, (LPBYTE)pO, FALSE );
  2546. fputs( pO, pFile );
  2547. }
  2548. if ( fMustFree )
  2549. {
  2550. IISCryptoFreeBlob( (PIIS_CRYPTO_BLOB)pB );
  2551. }
  2552. }
  2553. else
  2554. {
  2555. MappingGetField( x, &pF );
  2556. if ( pF != NULL )
  2557. {
  2558. MD5Update( (MD5_CTX*)pMD5, (LPBYTE)pF, (DWORD)strlen(pF) );
  2559. if ( IsCrypt( x ) )
  2560. {
  2561. dwF = (DWORD)strlen( pF ) + 1;
  2562. goto store_as_binary;
  2563. }
  2564. fputs( pF, pFile );
  2565. }
  2566. }
  2567. fputs( "|", pFile );
  2568. }
  2569. fputs( "\r\n", pFile );
  2570. if ( pO != NULL )
  2571. {
  2572. LocalFree( pO );
  2573. }
  2574. return TRUE;
  2575. }
  2576. BOOL
  2577. CIisMapping::Deserialize(
  2578. FILE* pFile,
  2579. VALID_CTX pMD5,
  2580. LPVOID pStorage
  2581. )
  2582. /*++
  2583. Routine Description:
  2584. Deserialize a mapping entry
  2585. Arguments:
  2586. pFile -- file to read from
  2587. pMD5 -- MD5 to update with signature of read bytes
  2588. Returns:
  2589. TRUE if success, FALSE if error
  2590. Lock:
  2591. mapper must be locked while serializing
  2592. --*/
  2593. {
  2594. LPSTR *pFields;
  2595. LPDWORD pcFields;
  2596. UINT iMax;
  2597. UINT x;
  2598. int c;
  2599. CHAR achBuf[4096]; // seems to be hardcoded limit on mapping saved
  2600. DWORD dwType;
  2601. LPBYTE pB;
  2602. iMax = GetNbField( &pFields, &pcFields );
  2603. for ( x = 0 ; x < iMax ; ++x )
  2604. {
  2605. StoreFieldRef( x, NULL );
  2606. }
  2607. for ( x = 0 ; x < sizeof(achBuf) && (c=fgetc(pFile))!= EOF ; )
  2608. {
  2609. achBuf[x++] = (CHAR)c;
  2610. if ( c == '\n' )
  2611. {
  2612. break;
  2613. }
  2614. }
  2615. if ( x == sizeof(achBuf ) )
  2616. {
  2617. return FALSE;
  2618. }
  2619. if ( x > 1 )
  2620. {
  2621. achBuf[x-2] = '\0';
  2622. m_cUsedBuff = m_cAllocBuff = x - 1;
  2623. if ( (m_pBuff = (LPBYTE)LocalAlloc( LMEM_FIXED, m_cAllocBuff )) == NULL )
  2624. {
  2625. m_cAllocBuff = m_cUsedBuff = 0;
  2626. return FALSE;
  2627. }
  2628. DBG_ASSERT( m_cAllocBuff >= m_cUsedBuff );
  2629. memcpy( m_pBuff, achBuf, m_cUsedBuff );
  2630. LPSTR pCur = (LPSTR)m_pBuff;
  2631. LPSTR pNext;
  2632. LPSTR pStore = (LPSTR)m_pBuff;
  2633. DWORD dwDec;
  2634. if ( pcFields )
  2635. {
  2636. for ( x = 0 ; x < iMax ; ++x )
  2637. {
  2638. pNext = strchr( pCur, '|' );
  2639. if ( pNext != NULL )
  2640. {
  2641. *pNext = '\0';
  2642. ++pNext;
  2643. }
  2644. else
  2645. {
  2646. pNext = NULL;
  2647. }
  2648. IISuudecode( pCur, (PBYTE)pStore, &dwDec, FALSE );
  2649. if ( IsCrypt( x ) && dwDec )
  2650. {
  2651. if ( FAILED(((IIS_CRYPTO_STORAGE*)pStorage)->DecryptData(
  2652. (PVOID*)&pB,
  2653. &dwDec,
  2654. &dwType,
  2655. (PIIS_CRYPTO_BLOB)pStore )) )
  2656. {
  2657. return FALSE;
  2658. }
  2659. DBG_ASSERT( m_cAllocBuff >= dwDec );
  2660. memmove( pStore, pB, dwDec );
  2661. }
  2662. MD5Update( (MD5_CTX*)pMD5, (LPBYTE)pStore, dwDec );
  2663. StoreFieldRef( x, pStore, dwDec );
  2664. pCur = pNext;
  2665. pStore += dwDec;
  2666. }
  2667. }
  2668. else
  2669. {
  2670. for ( x = 0 ; x < iMax ; ++x )
  2671. {
  2672. pNext = strchr( pCur, '|' );
  2673. if ( pNext != NULL )
  2674. {
  2675. *pNext = '\0';
  2676. ++pNext;
  2677. }
  2678. if ( *pCur && IsCrypt( x ) )
  2679. {
  2680. IISuudecode( pCur, (PBYTE)pCur, &dwDec, FALSE );
  2681. if ( FAILED(((IIS_CRYPTO_STORAGE*)pStorage)->DecryptData(
  2682. (PVOID*)&pB,
  2683. &dwDec,
  2684. &dwType,
  2685. (PIIS_CRYPTO_BLOB)pCur )) )
  2686. {
  2687. return FALSE;
  2688. }
  2689. MD5Update( (MD5_CTX*)pMD5, (LPBYTE)pB, dwDec );
  2690. StoreFieldRef( x, (LPSTR)pB );
  2691. pCur = pNext;
  2692. }
  2693. else
  2694. {
  2695. MD5Update( (MD5_CTX*)pMD5, (LPBYTE)pCur, (DWORD) strlen(pCur) );
  2696. StoreFieldRef( x, pCur );
  2697. pCur = pNext;
  2698. }
  2699. }
  2700. }
  2701. return TRUE;
  2702. }
  2703. return FALSE;
  2704. }
  2705. //
  2706. extern "C" BOOL WINAPI
  2707. DllMain(
  2708. HANDLE hModule,
  2709. DWORD dwReason,
  2710. LPVOID /*pV*/
  2711. )
  2712. /*++
  2713. Routine Description:
  2714. DLL init/terminate notification function
  2715. Arguments:
  2716. hModule - DLL handle
  2717. dwReason - notification type
  2718. LPVOID - not used
  2719. Returns:
  2720. TRUE if success, FALSE if failure
  2721. --*/
  2722. {
  2723. switch ( dwReason )
  2724. {
  2725. case DLL_PROCESS_ATTACH:
  2726. #ifdef _NO_TRACING_
  2727. CREATE_DEBUG_PRINT_OBJECT( "IISMAP" );
  2728. #endif
  2729. // record the module handle to access module info later
  2730. s_hIISMapDll = (HINSTANCE)hModule;
  2731. InitializeWildcardMapping( hModule );
  2732. InitializeMapping( hModule );
  2733. if ( IISCryptoInitialize() != NO_ERROR )
  2734. {
  2735. return FALSE;
  2736. }
  2737. return TRUE;
  2738. case DLL_PROCESS_DETACH:
  2739. IISCryptoTerminate();
  2740. TerminateWildcardMapping();
  2741. TerminateMapping();
  2742. #ifdef _NO_TRACING_
  2743. DELETE_DEBUG_PRINT_OBJECT( );
  2744. #endif
  2745. break;
  2746. }
  2747. return TRUE;
  2748. }
  2749. static
  2750. BOOL
  2751. LoadFieldNames(
  2752. IISMDB_Fields* pFields,
  2753. UINT cFields
  2754. )
  2755. /*++
  2756. Routine Description:
  2757. Load fields names from resource
  2758. - helper function for InitializeMapping()
  2759. Arguments:
  2760. pFields - ptr to array where to store reference to names
  2761. cFields - count of element in array
  2762. Return Value:
  2763. TRUE if success, otherwise FALSE
  2764. --*/
  2765. {
  2766. UINT x;
  2767. BOOL fSt = TRUE;
  2768. for ( x = 0 ;
  2769. x < cFields ;
  2770. ++x )
  2771. {
  2772. char achTmp[128];
  2773. if ( LoadString( s_hIISMapDll,
  2774. pFields[x].m_dwResID,
  2775. achTmp,
  2776. sizeof( achTmp ) ) != 0 )
  2777. {
  2778. DWORD lN = (DWORD) strlen( achTmp ) + sizeof(CHAR);
  2779. if ( (pFields[x].m_pszDisplayName = (LPSTR)LocalAlloc( LMEM_FIXED, lN )) == NULL )
  2780. {
  2781. fSt = FALSE;
  2782. break;
  2783. }
  2784. memcpy( pFields[x].m_pszDisplayName, achTmp, lN );
  2785. }
  2786. else
  2787. {
  2788. fSt = FALSE;
  2789. break;
  2790. }
  2791. }
  2792. return fSt;
  2793. }
  2794. static
  2795. VOID
  2796. FreeFieldNames(
  2797. IISMDB_Fields* pFields,
  2798. UINT cFields
  2799. )
  2800. /*++
  2801. Routine Description:
  2802. Free fields names loaded from resource
  2803. - helper function for TerminateMapping()
  2804. Arguments:
  2805. pFields - ptr to array where reference to names are stored
  2806. cFields - count of element in array
  2807. Return Value:
  2808. Nothing
  2809. --*/
  2810. {
  2811. UINT x;
  2812. for ( x = 0 ;
  2813. x < cFields ;
  2814. ++x )
  2815. {
  2816. if ( pFields[x].m_pszDisplayName )
  2817. {
  2818. LocalFree( pFields[x].m_pszDisplayName );
  2819. }
  2820. }
  2821. }
  2822. BOOL
  2823. InitializeMapping(
  2824. HANDLE /*hModule*/
  2825. )
  2826. /*++
  2827. Routine Description:
  2828. Initialize mapping
  2829. Arguments:
  2830. hModule - module handle of this DLL (not used)
  2831. Return Value:
  2832. Nothing
  2833. --*/
  2834. {
  2835. HKEY hKey = NULL;
  2836. // get install path
  2837. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  2838. W3_PARAMS,
  2839. 0,
  2840. KEY_READ|KEY_SET_VALUE,
  2841. &hKey ) == ERROR_SUCCESS )
  2842. {
  2843. DWORD dwLen = 0;
  2844. DWORD dwType;
  2845. if ( RegQueryValueEx( hKey,
  2846. INSTALL_PATH,
  2847. NULL,
  2848. &dwType,
  2849. NULL,
  2850. &dwLen ) != ERROR_SUCCESS ||
  2851. dwType != REG_SZ )
  2852. {
  2853. //
  2854. // Read next value
  2855. //
  2856. goto ReadNext;
  2857. }
  2858. //
  2859. // allocate space for extra terminator
  2860. //
  2861. if ( ( s_pszIisInstallPath = (LPSTR)LocalAlloc(
  2862. LMEM_FIXED,
  2863. dwLen +
  2864. sizeof( s_pszIisInstallPath[0] ) ) )
  2865. == NULL )
  2866. {
  2867. //
  2868. // Read next value
  2869. //
  2870. goto ReadNext;
  2871. }
  2872. if ( RegQueryValueEx( hKey,
  2873. INSTALL_PATH,
  2874. NULL,
  2875. &dwType,
  2876. (LPBYTE)s_pszIisInstallPath,
  2877. &dwLen ) != ERROR_SUCCESS )
  2878. {
  2879. if ( s_pszIisInstallPath )
  2880. {
  2881. LocalFree( s_pszIisInstallPath );
  2882. s_pszIisInstallPath = NULL;
  2883. }
  2884. //
  2885. // Read next value
  2886. //
  2887. goto ReadNext;
  2888. }
  2889. //
  2890. // RegQueryValueEx may not return NULL terminated string
  2891. // To be sure let's add termination (extra space was allocated already)
  2892. //
  2893. s_pszIisInstallPath[ dwLen ] = '\0';
  2894. ReadNext:
  2895. dwLen = sizeof( s_dwFileGuid );
  2896. if ( RegQueryValueEx( hKey,
  2897. MAPPER_GUID,
  2898. NULL,
  2899. &dwType,
  2900. (LPBYTE)&s_dwFileGuid,
  2901. &dwLen ) != ERROR_SUCCESS ||
  2902. dwType != REG_DWORD )
  2903. {
  2904. s_dwFileGuid = 0;
  2905. }
  2906. RegCloseKey( hKey );
  2907. return LoadFieldNames( IisCert11MappingFields,
  2908. sizeof(IisCert11MappingFields)/sizeof(IISMDB_Fields) );
  2909. }
  2910. else
  2911. {
  2912. hKey = NULL;
  2913. }
  2914. return FALSE;
  2915. }
  2916. VOID
  2917. TerminateMapping(
  2918. )
  2919. /*++
  2920. Routine Description:
  2921. Terminate mapping
  2922. Arguments:
  2923. None
  2924. Return Value:
  2925. Nothing
  2926. --*/
  2927. {
  2928. if ( s_pszIisInstallPath )
  2929. {
  2930. LocalFree( s_pszIisInstallPath );
  2931. }
  2932. FreeFieldNames( IisCert11MappingFields,
  2933. sizeof(IisCert11MappingFields)/sizeof(IISMDB_Fields) );
  2934. }
  2935. //
  2936. dllexp
  2937. BOOL
  2938. ReportIisMapEvent(
  2939. WORD wType,
  2940. DWORD dwEventId,
  2941. WORD cNbStr,
  2942. LPCTSTR* pStr
  2943. )
  2944. /*++
  2945. Routine Description:
  2946. Log an event based on type, ID and insertion strings
  2947. Arguments:
  2948. wType -- event type ( error, warning, information )
  2949. dwEventId -- event ID ( as defined by the .mc file )
  2950. cNbStr -- nbr of LPSTR in the pStr array
  2951. pStr -- insertion strings
  2952. Returns:
  2953. TRUE if success, FALSE if failure
  2954. --*/
  2955. {
  2956. BOOL fSt = TRUE;
  2957. HANDLE hEventLog = NULL;
  2958. hEventLog = RegisterEventSource(NULL,"IISMAP");
  2959. if ( hEventLog != NULL )
  2960. {
  2961. if (!ReportEvent(hEventLog, // event log handle
  2962. wType, // event type
  2963. 0, // category zero
  2964. (DWORD) dwEventId, // event identifier
  2965. NULL, // no user security identifier
  2966. cNbStr, // count of substitution strings (may be no strings)
  2967. // less ProgName (argv[0]) and Event ID (argv[1])
  2968. 0, // no data
  2969. (LPCTSTR *) pStr, // address of string array
  2970. NULL)) // address of data
  2971. {
  2972. fSt = FALSE;
  2973. }
  2974. DeregisterEventSource( hEventLog );
  2975. }
  2976. else
  2977. {
  2978. fSt = FALSE;
  2979. }
  2980. return fSt;
  2981. }
  2982. dllexp
  2983. BOOL
  2984. ReportIisMapEventW(
  2985. WORD wType,
  2986. DWORD dwEventId,
  2987. WORD cNbStr,
  2988. LPCWSTR* pStr
  2989. )
  2990. /*++
  2991. Routine Description:
  2992. Log an event based on type, ID and insertion strings
  2993. Arguments:
  2994. wType -- event type ( error, warning, information )
  2995. dwEventId -- event ID ( as defined by the .mc file )
  2996. cNbStr -- nbr of LPSTR in the pStr array
  2997. pStr -- insertion strings
  2998. Returns:
  2999. TRUE if success, FALSE if failure
  3000. --*/
  3001. {
  3002. BOOL fSt = TRUE;
  3003. HANDLE hEventLog = NULL;
  3004. hEventLog = RegisterEventSource(NULL,"IISMAP");
  3005. if ( hEventLog != NULL )
  3006. {
  3007. if (!ReportEventW(hEventLog, // event log handle
  3008. wType, // event type
  3009. 0, // category zero
  3010. (DWORD) dwEventId, // event identifier
  3011. NULL, // no user security identifier
  3012. cNbStr, // count of substitution strings (may be no strings)
  3013. // less ProgName (argv[0]) and Event ID (argv[1])
  3014. 0, // no data
  3015. (LPCWSTR *) pStr, // address of string array
  3016. NULL)) // address of data
  3017. {
  3018. fSt = FALSE;
  3019. }
  3020. DeregisterEventSource( hEventLog );
  3021. }
  3022. else
  3023. {
  3024. fSt = FALSE;
  3025. }
  3026. return fSt;
  3027. }
  3028. /////////////////////////////////////////
  3029. ///////////////////////
  3030. //
  3031. // Taken from NCSA HTTP and wwwlib.
  3032. //
  3033. // NOTE: These conform to RFC1113, which is slightly different then the Unix
  3034. // uuencode and uudecode!
  3035. //
  3036. const int _pr2six[256]={
  3037. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3038. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
  3039. 52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,
  3040. 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
  3041. 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
  3042. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3043. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3044. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3045. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3046. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3047. 64,64,64,64,64,64,64,64,64,64,64,64,64
  3048. };
  3049. char _six2pr[64] = {
  3050. 'A','B','C','D','E','F','G','H','I','J','K','L','M',
  3051. 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  3052. 'a','b','c','d','e','f','g','h','i','j','k','l','m',
  3053. 'n','o','p','q','r','s','t','u','v','w','x','y','z',
  3054. '0','1','2','3','4','5','6','7','8','9','+','/'
  3055. };
  3056. const int _pr2six64[256]={
  3057. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3058. 64,64,64,64,64,64,64,64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
  3059. 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,
  3060. 40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
  3061. 0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3062. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3063. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3064. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3065. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3066. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  3067. 64,64,64,64,64,64,64,64,64,64,64,64,64
  3068. };
  3069. char _six2pr64[64] = {
  3070. '`','!','"','#','$','%','&','\'','(',')','*','+',',',
  3071. '-','.','/','0','1','2','3','4','5','6','7','8','9',
  3072. ':',';','<','=','>','?','@','A','B','C','D','E','F',
  3073. 'G','H','I','J','K','L','M','N','O','P','Q','R','S',
  3074. 'T','U','V','W','X','Y','Z','[','\\',']','^','_'
  3075. };
  3076. BOOL IISuudecode(char * bufcoded,
  3077. BYTE * bufout,
  3078. DWORD * pcbDecoded,
  3079. BOOL fBase64
  3080. )
  3081. {
  3082. int nbytesdecoded;
  3083. char *bufin = bufcoded;
  3084. int nprbytes;
  3085. int *pr2six = (int*)(fBase64 ? _pr2six64 : _pr2six);
  3086. int chL = 0;
  3087. /* Strip leading whitespace. */
  3088. while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
  3089. /* Figure out how many characters are in the input buffer.
  3090. * If this would decode into more bytes than would fit into
  3091. * the output buffer, adjust the number of input bytes downwards.
  3092. */
  3093. bufin = bufcoded;
  3094. while(pr2six[*(bufin++)] <= 63);
  3095. nprbytes = (DWORD) DIFF(bufin - bufcoded) - 1;
  3096. nbytesdecoded = ((nprbytes+3)/4) * 3;
  3097. bufin = bufcoded;
  3098. while (nprbytes > 0) {
  3099. chL = bufin[2];
  3100. *(bufout++) =
  3101. (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
  3102. *(bufout++) =
  3103. (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
  3104. *(bufout++) =
  3105. (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
  3106. bufin += 4;
  3107. nprbytes -= 4;
  3108. }
  3109. if(nprbytes & 03) {
  3110. if(pr2six[chL] > 63)
  3111. nbytesdecoded -= 2;
  3112. else
  3113. nbytesdecoded -= 1;
  3114. }
  3115. if ( pcbDecoded )
  3116. *pcbDecoded = nbytesdecoded;
  3117. return TRUE;
  3118. }
  3119. //
  3120. // NOTE NOTE NOTE
  3121. // If the buffer length isn't a multiple of 3, we encode one extra byte beyond the
  3122. // end of the buffer. This garbage byte is stripped off by the uudecode code, but
  3123. // -IT HAS TO BE THERE- for uudecode to work. This applies not only our uudecode, but
  3124. // to every uudecode() function that is based on the lib-www distribution [probably
  3125. // a fairly large percentage of the code that's floating around out there].
  3126. //
  3127. BOOL IISuuencode( BYTE * bufin,
  3128. DWORD nbytes,
  3129. BYTE * outptr,
  3130. BOOL fBase64 )
  3131. {
  3132. unsigned int i;
  3133. unsigned int iRemainder = 0;
  3134. unsigned int iClosestMultOfThree = 0;
  3135. char *six2pr = fBase64 ? _six2pr64 : _six2pr;
  3136. BOOL fOneByteDiff = FALSE;
  3137. BOOL fTwoByteDiff = FALSE;
  3138. iRemainder = nbytes % 3; //also works for nbytes == 1, 2
  3139. fOneByteDiff = (iRemainder == 1 ? TRUE : FALSE);
  3140. fTwoByteDiff = (iRemainder == 2 ? TRUE : FALSE);
  3141. iClosestMultOfThree = ((nbytes - iRemainder)/3) * 3 ;
  3142. //
  3143. // Encode bytes in buffer up to multiple of 3 that is closest to nbytes.
  3144. //
  3145. for (i=0; i< iClosestMultOfThree ; i += 3) {
  3146. *(outptr++) = six2pr[*bufin >> 2]; /* c1 */
  3147. *(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; /*c2*/
  3148. *(outptr++) = six2pr[((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)];/*c3*/
  3149. *(outptr++) = six2pr[bufin[2] & 077]; /* c4 */
  3150. bufin += 3;
  3151. }
  3152. //
  3153. // We deal with trailing bytes by pretending that the input buffer has been padded with
  3154. // zeros. Expressions are thus the same as above, but the second half drops off b'cos
  3155. // ( a | ( b & 0) ) = ( a | 0 ) = a
  3156. //
  3157. if (fOneByteDiff)
  3158. {
  3159. *(outptr++) = six2pr[*bufin >> 2]; /* c1 */
  3160. *(outptr++) = six2pr[((*bufin << 4) & 060)]; /* c2 */
  3161. //pad with '='
  3162. *(outptr++) = '='; /* c3 */
  3163. *(outptr++) = '='; /* c4 */
  3164. }
  3165. else if (fTwoByteDiff)
  3166. {
  3167. *(outptr++) = six2pr[*bufin >> 2]; /* c1 */
  3168. *(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; /*c2*/
  3169. *(outptr++) = six2pr[((bufin[1] << 2) & 074)];/*c3*/
  3170. //pad with '='
  3171. *(outptr++) = '='; /* c4 */
  3172. }
  3173. //encoded buffer must be zero-terminated
  3174. *outptr = '\0';
  3175. return TRUE;
  3176. }
  3177. const int SHA1_HASH_SIZE = 20;
  3178. HRESULT
  3179. GetCertificateHashString(
  3180. PBYTE pbCert,
  3181. DWORD cbCert,
  3182. WCHAR *pwszCertHash,
  3183. DWORD cchCertHashBuffer)
  3184. /*++
  3185. Routine Description:
  3186. verifies validity of cert blob by creating cert context
  3187. and retrieves SHA1 hash and converts it to WCHAR *
  3188. Arguments:
  3189. pbCert - X.509 certificate blob
  3190. cbCert - size of the cert blob in bytes
  3191. pwszCertHash - buffer must be big enough to fit SHA1 hash in hex string form
  3192. (40 WCHAR + terminating 0 )
  3193. cchCertHashBuffer - size of the CertHash buffer in WCHARS (including terminating 0)
  3194. Returns:
  3195. HRESULT
  3196. --*/
  3197. {
  3198. HRESULT hr = E_FAIL;
  3199. BYTE rgbHash[ SHA1_HASH_SIZE ];
  3200. DWORD cbSize = SHA1_HASH_SIZE;
  3201. PCCERT_CONTEXT pCertContext = NULL;
  3202. #ifndef HEX_DIGIT
  3203. #define HEX_DIGIT( nDigit ) \
  3204. (WCHAR)((nDigit) > 9 ? \
  3205. (nDigit) - 10 + L'a' \
  3206. : (nDigit) + L'0')
  3207. #endif
  3208. pCertContext = CertCreateCertificateContext(
  3209. X509_ASN_ENCODING,
  3210. (const BYTE *)pbCert,
  3211. cbCert );
  3212. if ( pCertContext == NULL )
  3213. {
  3214. hr = HRESULT_FROM_WIN32( GetLastError() );
  3215. goto ExitPoint;
  3216. }
  3217. //
  3218. // get hash of the certificate to be verified
  3219. //
  3220. if ( !CertGetCertificateContextProperty( pCertContext,
  3221. CERT_SHA1_HASH_PROP_ID,
  3222. rgbHash,
  3223. &cbSize ) )
  3224. {
  3225. hr = HRESULT_FROM_WIN32( GetLastError() );
  3226. goto ExitPoint;
  3227. }
  3228. CertFreeCertificateContext( pCertContext );
  3229. pCertContext = NULL;
  3230. if ( cchCertHashBuffer < SHA1_HASH_SIZE * 2 + 1 )
  3231. {
  3232. // we don't have big enough buffer to store
  3233. // hex string of the SHA1 hash each byte takes 2 chars + terminating 0
  3234. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3235. DBG_ASSERT( cchCertHashBuffer < SHA1_HASH_SIZE * 2 + 1 );
  3236. goto ExitPoint;
  3237. }
  3238. //
  3239. // convert to text
  3240. //
  3241. for (int i = 0; i < sizeof(rgbHash); i ++ )
  3242. {
  3243. *(pwszCertHash++) = HEX_DIGIT( ( rgbHash[ i ] >> 4 ) );
  3244. *(pwszCertHash++) = HEX_DIGIT( ( rgbHash[ i ] & 0x0F ) );
  3245. }
  3246. *(pwszCertHash) = L'\0';
  3247. #undef HEX_DIGIT
  3248. ExitPoint:
  3249. if ( pCertContext != NULL )
  3250. {
  3251. CertFreeCertificateContext( pCertContext );
  3252. pCertContext = NULL;
  3253. }
  3254. return S_OK;
  3255. }
  3256. VOID
  3257. ReportImportProblem(
  3258. HRESULT hr
  3259. )
  3260. /*++
  3261. Routine Description:
  3262. Utility function for ImportIISCertMappingsToIIS6()
  3263. that reports first problem occured with import to eventlog
  3264. Arguments:
  3265. hr - hresult to report
  3266. Returns:
  3267. VOID
  3268. --*/
  3269. {
  3270. static BOOL fWasReported = FALSE;
  3271. if ( fWasReported == FALSE )
  3272. {
  3273. fWasReported = TRUE;
  3274. char achErr[ 40 ];
  3275. LPCTSTR pA[ 1 ];
  3276. pA[ 0 ] = achErr;
  3277. _ultoa( hr, achErr, 16 );
  3278. ReportIisMapEvent( EVENTLOG_ERROR_TYPE,
  3279. IISMAP_EVENT_ERROR_IMPORT,
  3280. 1,
  3281. pA );
  3282. }
  3283. }
  3284. dllexp
  3285. VOID
  3286. ImportIISCertMappingsToIIS6(
  3287. VOID
  3288. )
  3289. /*++
  3290. Routine Description:
  3291. IIS6 stores 1to1 certificate in the metabase
  3292. IIS5 used to store MD_SERIAL_CERT11 reference info in the metabase
  3293. but actual mapping details were stored in metabase extension file
  3294. *.mp
  3295. This routine will load old (IIS5) style mapping for each site
  3296. into memory, then save it in the metabase and delete old reference
  3297. info from metabase
  3298. This function should be called only once
  3299. Arguments:
  3300. None
  3301. Returns:
  3302. HRESULT
  3303. --*/
  3304. {
  3305. IMSAdminBase * pMetabase = NULL;
  3306. HRESULT hr = E_FAIL;
  3307. HKEY hKey = NULL;
  3308. DWORD dwLen = 0;
  3309. DWORD dwType;
  3310. DWORD dwError;
  3311. BOOL fCoInitialized = FALSE;
  3312. BOOL fMBSaved = FALSE;
  3313. if ( ( dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  3314. W3_PARAMS,
  3315. 0,
  3316. KEY_READ|KEY_SET_VALUE,
  3317. &hKey ) ) != ERROR_SUCCESS )
  3318. {
  3319. if ( dwError != ERROR_FILE_NOT_FOUND &&
  3320. dwError != ERROR_PATH_NOT_FOUND )
  3321. {
  3322. hr = HRESULT_FROM_WIN32( dwError );
  3323. ReportImportProblem( hr );
  3324. DBGPRINTF(( DBG_CONTEXT,
  3325. "Error in Opening registry(). hr = %x\n",
  3326. hr ));
  3327. }
  3328. goto Finished;
  3329. }
  3330. dwLen = sizeof( s_dwFileGuid );
  3331. if ( RegQueryValueEx( hKey,
  3332. MAPPER_GUID,
  3333. NULL,
  3334. &dwType,
  3335. (LPBYTE)&s_dwFileGuid,
  3336. &dwLen ) != ERROR_SUCCESS ||
  3337. dwType != REG_DWORD )
  3338. {
  3339. //
  3340. // If MapperGuid Value doesn't exist
  3341. // then it means that IIS Cert Mappings
  3342. // in old format are not present
  3343. //
  3344. goto Finished;
  3345. }
  3346. if ( s_dwFileGuid == 0xffffffff )
  3347. {
  3348. // This flags that import has been already attempted
  3349. // It is valid to run Import only once
  3350. // If Import needs to be rerun then
  3351. // MAPPER_GUID should be reset to value different from MAX_DWORD
  3352. goto Finished;
  3353. }
  3354. //
  3355. // Write to registry that import of 1to1 certmapping info
  3356. // was invoked (we will do it only once)
  3357. //
  3358. s_dwFileGuid = 0xffffffff;
  3359. if( ( dwError = RegSetValueEx( hKey,
  3360. MAPPER_GUID,
  3361. NULL,
  3362. REG_DWORD,
  3363. (LPBYTE)&s_dwFileGuid,
  3364. sizeof(s_dwFileGuid) ) ) != ERROR_SUCCESS )
  3365. {
  3366. hr = HRESULT_FROM_WIN32( dwError );
  3367. ReportImportProblem( hr );
  3368. DBGPRINTF(( DBG_CONTEXT,
  3369. "Error in Opening registry(). hr = %x\n",
  3370. hr ));
  3371. goto Finished;
  3372. }
  3373. RegCloseKey( hKey );
  3374. hKey = NULL;
  3375. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  3376. if ( hr == RPC_E_CHANGED_MODE )
  3377. {
  3378. // If you get RPC_E_MODE_CHANGE the thread is coinited
  3379. // but don't couninit
  3380. }
  3381. else if ( FAILED(hr) )
  3382. {
  3383. ReportImportProblem( hr );
  3384. DBGPRINTF(( DBG_CONTEXT,
  3385. "Error in CoInitializeEx(). hr = %x\n",
  3386. hr ));
  3387. goto Finished;
  3388. }
  3389. else
  3390. {
  3391. fCoInitialized = TRUE;
  3392. // we will have to couninit
  3393. }
  3394. //
  3395. // Initialize the metabase access (ABO)
  3396. //
  3397. hr = CoCreateInstance( CLSID_MSAdminBase,
  3398. NULL,
  3399. CLSCTX_SERVER,
  3400. IID_IMSAdminBase,
  3401. (LPVOID *) &pMetabase
  3402. );
  3403. if( FAILED(hr) )
  3404. {
  3405. ReportImportProblem( hr );
  3406. DBGPRINTF(( DBG_CONTEXT,
  3407. "Error creating ABO object. hr = %x\n",
  3408. hr ));
  3409. goto Finished;
  3410. }
  3411. //
  3412. // Instances of 2 services could be using 1to1 certificate mappings
  3413. // one is W3SVC and another one is NNTP
  3414. for ( DWORD dwServiceType = 0; dwServiceType < 2; dwServiceType ++ )
  3415. {
  3416. SimpleMB mb( pMetabase );
  3417. CIisCert11Mapper AcctMapper;
  3418. DWORD dwIndex = 0;
  3419. WCHAR * pszServicePath = NULL;
  3420. WCHAR achServiceInstance[ ADMINDATA_MAX_NAME_LEN + 1 ];
  3421. STRAU strObjectPath;
  3422. BUFFER buffSerializedCert11Info;
  3423. DWORD cbSerializedCert11Info;
  3424. switch( dwServiceType)
  3425. {
  3426. case 0:
  3427. pszServicePath = L"/LM/W3SVC";
  3428. break;
  3429. case 1:
  3430. pszServicePath = L"/LM/NNTPSVC";
  3431. break;
  3432. }
  3433. // We need access to ServicePath in the metabase
  3434. if ( ! mb.Open( pszServicePath,
  3435. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ) )
  3436. {
  3437. hr = HRESULT_FROM_WIN32( GetLastError() );
  3438. if ( hr != HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) )
  3439. {
  3440. //
  3441. // Report error if other than ERROR_PATH_NOT_FOUND
  3442. // ERROR_PATH_NOT_FOUND indicates that service (such as w3svc or nntp)
  3443. // is not installed
  3444. //
  3445. ReportImportProblem( hr );
  3446. DBGPRINTF(( DBG_CONTEXT,
  3447. "Failed to open metabase path %s (import of 1to1 cert mappings will fail). hr = %x\n",
  3448. pszServicePath, hr ));
  3449. // still try another service if there is any left
  3450. }
  3451. continue;
  3452. }
  3453. //
  3454. // Enumerate service instances (such as w3svc/1, w3svc/2 etc)
  3455. // and upgrade 1to1 mapping info to new format for all of them
  3456. //
  3457. for ( dwIndex = 0; ; dwIndex++ )
  3458. {
  3459. if ( !mb.EnumObjects( L"",
  3460. achServiceInstance,
  3461. dwIndex ) )
  3462. {
  3463. hr = HRESULT_FROM_WIN32( GetLastError() );
  3464. if ( hr != HRESULT_FROM_WIN32( ERROR_NO_MORE_ITEMS ) &&
  3465. hr != HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) )
  3466. {
  3467. ReportImportProblem( hr );
  3468. DBGPRINTF(( DBG_CONTEXT,
  3469. "Failed to enum metabase nodes. hr = %x\n",
  3470. hr ));
  3471. }
  3472. else
  3473. {
  3474. // done enumerating all instances of the service
  3475. hr = S_OK;
  3476. }
  3477. // Done with enumeration
  3478. // Exit the for loop
  3479. break;
  3480. }
  3481. //
  3482. // Read 1to1 certificate mapping serialized reference info
  3483. // from metabase
  3484. //
  3485. if ( !mb.GetBuffer( achServiceInstance,
  3486. MD_SERIAL_CERT11,
  3487. IIS_MD_UT_SERVER,
  3488. &buffSerializedCert11Info,
  3489. &cbSerializedCert11Info
  3490. ) )
  3491. {
  3492. hr = HRESULT_FROM_WIN32( GetLastError() );
  3493. if ( hr != MD_ERROR_DATA_NOT_FOUND )
  3494. {
  3495. // this service instance may have
  3496. // and 1to1 certificate mappings configured
  3497. ReportImportProblem( hr );
  3498. DBGPRINTF(( DBG_CONTEXT,
  3499. "Failed to read MD_SERIAL_CERT11 for %s/%s. hr = %x\n",
  3500. pszServicePath, achServiceInstance, hr ));
  3501. }
  3502. // don't take error as fatal move on to another service
  3503. // instance
  3504. goto EnumNext;
  3505. }
  3506. //
  3507. // Unserialize 1to1 Certificate mapping info
  3508. //
  3509. PBYTE pbSerializedCert11Info = (PBYTE) buffSerializedCert11Info.QueryPtr();
  3510. if ( !AcctMapper.Unserialize( &pbSerializedCert11Info,
  3511. &cbSerializedCert11Info ) ||
  3512. !AcctMapper.Load() )
  3513. {
  3514. hr = HRESULT_FROM_WIN32( GetLastError() );
  3515. ReportImportProblem( hr );
  3516. DBGPRINTF(( DBG_CONTEXT,
  3517. "Failed to unserialize mapper for %s/%s. hr = %x\n",
  3518. pszServicePath, achServiceInstance, hr ));
  3519. goto EnumNext;
  3520. }
  3521. // walk all the mappings and save them to metabase
  3522. // in the new format
  3523. //
  3524. for ( DWORD dwMappingIndex = 0;
  3525. dwMappingIndex < AcctMapper.GetMappingCount();
  3526. dwMappingIndex ++ )
  3527. {
  3528. PBYTE pbCert = NULL;
  3529. DWORD cbCert = 0;
  3530. CHAR * pszPassword;
  3531. DWORD cbPassword;
  3532. STRAU strPassword;
  3533. CHAR * pszAcctName;
  3534. DWORD cbAcctName;
  3535. STRAU strAcctName;
  3536. CHAR * pszMappingName;
  3537. DWORD cbMappingName;
  3538. STRAU strMappingName;
  3539. DWORD * pdwEnabled;
  3540. DWORD cbEnabled;
  3541. STRAU strObjectPath;
  3542. WCHAR achCertHash[ 2*SHA1_HASH_SIZE + 1];
  3543. CIisMapping* pCurrentMapping;
  3544. if ( !AcctMapper.GetMapping(
  3545. dwMappingIndex,
  3546. &pCurrentMapping ) )
  3547. {
  3548. hr = E_FAIL;
  3549. ReportImportProblem( hr );
  3550. DBGPRINTF((DBG_CONTEXT,
  3551. "Failed to read mapping for %s/%s/%d. 0x%x\n",
  3552. pszServicePath, achServiceInstance,
  3553. dwMappingIndex, hr));
  3554. // There must be some inconsistency in data
  3555. // or low memory condition
  3556. // No hope to process mappings for this Service Site.
  3557. // Move on to next Service site
  3558. break;
  3559. }
  3560. if ( !pCurrentMapping->MappingGetField(
  3561. IISMDB_INDEX_CERT11_CERT,
  3562. (PBYTE *)&pbCert,
  3563. &cbCert,
  3564. FALSE ) )
  3565. {
  3566. hr = E_FAIL;
  3567. ReportImportProblem( hr );
  3568. DBGPRINTF((DBG_CONTEXT,
  3569. "Failed to read mapping for %s/%s/%d. 0x%x\n",
  3570. pszServicePath, achServiceInstance,
  3571. dwMappingIndex, hr));
  3572. // Move on to next Service site
  3573. break;
  3574. }
  3575. if ( !pCurrentMapping->MappingGetField(
  3576. IISMDB_INDEX_CERT11_NT_ACCT,
  3577. (PBYTE *)&pszAcctName,
  3578. &cbAcctName,
  3579. FALSE ) )
  3580. {
  3581. hr = E_FAIL;
  3582. ReportImportProblem( hr );
  3583. DBGPRINTF((DBG_CONTEXT,
  3584. "Failed to read mapping for %s/%s/%d. 0x%x\n",
  3585. pszServicePath, achServiceInstance,
  3586. dwMappingIndex, hr));
  3587. // Move on to next Service site
  3588. break;
  3589. }
  3590. if ( !pCurrentMapping->MappingGetField(
  3591. IISMDB_INDEX_CERT11_NT_PWD,
  3592. (PBYTE *)&pszPassword,
  3593. &cbPassword,
  3594. FALSE ) )
  3595. {
  3596. hr = E_FAIL;
  3597. ReportImportProblem( hr );
  3598. DBGPRINTF((DBG_CONTEXT,
  3599. "Failed to read mapping for %s/%s/%d. 0x%x\n",
  3600. pszServicePath, achServiceInstance,
  3601. dwMappingIndex, hr));
  3602. // Move on to next Service site
  3603. break;
  3604. }
  3605. if ( !pCurrentMapping->MappingGetField(
  3606. IISMDB_INDEX_CERT11_NAME,
  3607. (PBYTE *)&pszMappingName,
  3608. &cbMappingName,
  3609. FALSE ) )
  3610. {
  3611. hr = E_FAIL;
  3612. ReportImportProblem( hr );
  3613. DBGPRINTF((DBG_CONTEXT,
  3614. "Failed to read mapping for %s/%s/%d. 0x%x\n",
  3615. pszServicePath, achServiceInstance,
  3616. dwMappingIndex, hr));
  3617. // Move on to next Service site
  3618. break;
  3619. }
  3620. if ( !pCurrentMapping->MappingGetField(
  3621. IISMDB_INDEX_CERT11_ENABLED,
  3622. (PBYTE *)&pdwEnabled,
  3623. &cbEnabled,
  3624. FALSE ) ||
  3625. cbEnabled != sizeof( DWORD ) )
  3626. {
  3627. hr = E_FAIL;
  3628. ReportImportProblem( hr );
  3629. DBGPRINTF((DBG_CONTEXT,
  3630. "Failed to read mapping for %s/%s/%d. 0x%x\n",
  3631. pszServicePath, achServiceInstance,
  3632. dwMappingIndex, hr));
  3633. // Move on to next Service site
  3634. break;
  3635. }
  3636. //
  3637. // Finished reading current mapping details
  3638. // Now convert Mapping Name, AcctName and Password
  3639. // from ANSI to Unicode (the actual conversion may happen later
  3640. // - STRAU class will take care of it)
  3641. if ( !strMappingName.Copy( pszMappingName,
  3642. cbMappingName - sizeof(CHAR) ) ||
  3643. !strPassword.Copy( pszPassword,
  3644. cbPassword - sizeof(CHAR) ) ||
  3645. !strAcctName.Copy( pszAcctName,
  3646. cbAcctName - sizeof(CHAR) ) )
  3647. {
  3648. hr = HRESULT_FROM_WIN32( GetLastError() );
  3649. ReportImportProblem( hr );
  3650. DBGPRINTF((DBG_CONTEXT,
  3651. "Failed to read mapping for %s/%s/%d. 0x%x\n",
  3652. pszServicePath, achServiceInstance,
  3653. dwMappingIndex, hr));
  3654. break;
  3655. }
  3656. // Now calculate hex string with current cert's hash
  3657. // it will be used as a unique name for the mapping
  3658. // object in the metabase
  3659. if ( FAILED( hr = GetCertificateHashString(
  3660. pbCert,
  3661. cbCert,
  3662. achCertHash,
  3663. sizeof( achCertHash )/sizeof(WCHAR) ) ) )
  3664. {
  3665. ReportImportProblem( hr );
  3666. DBGPRINTF((DBG_CONTEXT,
  3667. "Invalid cert passed to CreateMapping() 0x%x\n", hr));
  3668. // goto next mapping
  3669. goto NextMapping;
  3670. }
  3671. if ( ! strObjectPath.Copy( achServiceInstance ) )
  3672. {
  3673. ReportImportProblem( hr );
  3674. hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  3675. DBGPRINTF((DBG_CONTEXT,
  3676. "Failed to import mapping. 0x%x\n", hr));
  3677. goto NextMapping;
  3678. }
  3679. if ( ! strObjectPath.Append( "/Cert11/Mappings/" ) )
  3680. {
  3681. ReportImportProblem( hr );
  3682. hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  3683. DBGPRINTF((DBG_CONTEXT,
  3684. "Failed to import mapping. 0x%x\n", hr));
  3685. goto NextMapping;
  3686. }
  3687. if ( ! strObjectPath.Append( achCertHash ) )
  3688. {
  3689. ReportImportProblem( hr );
  3690. hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  3691. DBGPRINTF((DBG_CONTEXT,
  3692. "Failed to import mapping. 0x%x\n", hr));
  3693. goto NextMapping;
  3694. }
  3695. //
  3696. // Add new node for the mapping
  3697. //
  3698. if ( !mb.AddObject( strObjectPath.QueryStrW() ) )
  3699. {
  3700. // Don't report problem here
  3701. // Just fall through
  3702. // Next SetData will fail and report problem
  3703. // if there is one.
  3704. }
  3705. //
  3706. // Save 1to1 Certificate mapping info
  3707. // directly to metabase in the new format
  3708. //
  3709. // save the certificate
  3710. if ( !mb.SetData( strObjectPath.QueryStrW(), MD_MAPCERT,
  3711. IIS_MD_UT_SERVER, BINARY_METADATA,
  3712. pbCert, cbCert, 0 ) )
  3713. {
  3714. ReportImportProblem( hr );
  3715. hr = HRESULT_FROM_WIN32( GetLastError() );
  3716. DBGPRINTF(( DBG_CONTEXT,
  3717. "Failed to write MD_MAPCERT. hr = %x\n",
  3718. hr ));
  3719. // Don't consider fatal. Move on
  3720. }
  3721. // save the NTAccount
  3722. if ( !mb.SetString( strObjectPath.QueryStrW(),
  3723. MD_MAPNTACCT,
  3724. IIS_MD_UT_SERVER,
  3725. strAcctName.QueryStrW(),
  3726. 0 ) )
  3727. {
  3728. ReportImportProblem( hr );
  3729. hr = HRESULT_FROM_WIN32( GetLastError() );
  3730. DBGPRINTF(( DBG_CONTEXT,
  3731. "Failed to write MD_MAPNTACCT. hr = %x\n",
  3732. hr ));
  3733. // Don't consider fatal. Move on }
  3734. }
  3735. // save the password - secure
  3736. if ( !mb.SetString( strObjectPath.QueryStrW(),
  3737. MD_MAPNTPWD,
  3738. IIS_MD_UT_SERVER,
  3739. strPassword.QueryStrW(),
  3740. METADATA_SECURE ) )
  3741. {
  3742. ReportImportProblem( hr );
  3743. hr = HRESULT_FROM_WIN32( GetLastError() );
  3744. DBGPRINTF(( DBG_CONTEXT,
  3745. "Failed to write MD_MAPNTPWD. hr = %x\n",
  3746. hr ));
  3747. // Don't consider fatal. Move on }
  3748. }
  3749. // save the map's name
  3750. if ( !mb.SetString( strObjectPath.QueryStrW(),
  3751. MD_MAPNAME,
  3752. IIS_MD_UT_SERVER,
  3753. strMappingName.QueryStrW(),
  3754. 0 ) )
  3755. {
  3756. ReportImportProblem( hr );
  3757. hr = HRESULT_FROM_WIN32( GetLastError() );
  3758. DBGPRINTF(( DBG_CONTEXT,
  3759. "Failed to write MD_MAPNAME. hr = %x\n",
  3760. hr ));
  3761. // Don't consider fatal. Move on }
  3762. }
  3763. // save the Enabled flag
  3764. // server reads the flag as the value of the dword
  3765. if ( !mb.SetDword( strObjectPath.QueryStrW(),
  3766. MD_MAPENABLED,
  3767. IIS_MD_UT_SERVER,
  3768. *pdwEnabled,
  3769. 0 ) )
  3770. {
  3771. ReportImportProblem( hr );
  3772. hr = HRESULT_FROM_WIN32( GetLastError() );
  3773. DBGPRINTF(( DBG_CONTEXT,
  3774. "Failed to write MD_MAPENABLED. hr = %x\n",
  3775. hr ));
  3776. // Don't consider fatal. Move on }
  3777. }
  3778. NextMapping:
  3779. ;
  3780. }
  3781. //
  3782. // Flush metabase changes after each instance
  3783. // we have to close our metabase handles to make Save possible
  3784. mb.Close();
  3785. if ( !mb.Save() )
  3786. {
  3787. // we failed to save metabase
  3788. // there is no guarantee that data we converted so far
  3789. // will be persisted safely
  3790. // In this case we rather leave legacy structure around
  3791. hr = HRESULT_FROM_WIN32( GetLastError() );
  3792. ReportImportProblem( hr );
  3793. fMBSaved = FALSE;
  3794. }
  3795. else
  3796. {
  3797. fMBSaved = TRUE;
  3798. }
  3799. // Reopen metabase
  3800. // we had to close it to be able to perform Save
  3801. // Note: This function assumes that nobody is messing with the metabase
  3802. // at this time (should be called only during upgrade) on iisadmin startup
  3803. // If new service instance nodes are added or removed then
  3804. // our site instance enumeration index could be off
  3805. if ( !mb.Open( pszServicePath,
  3806. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ) )
  3807. {
  3808. hr = HRESULT_FROM_WIN32( GetLastError() );
  3809. ReportImportProblem( hr );
  3810. DBGPRINTF(( DBG_CONTEXT,
  3811. "Failed to open metabase path %s (import of 1to1 cert mappings will fail). hr = %x\n",
  3812. pszServicePath, hr ));
  3813. // still try another service if there is any left
  3814. continue;
  3815. }
  3816. if ( fMBSaved )
  3817. {
  3818. //
  3819. // delete external storage - the *.mp file
  3820. // for this mapper
  3821. //
  3822. if ( !AcctMapper.Delete() )
  3823. {
  3824. //
  3825. // Unfortunately there will be some legacy data left behind
  3826. //
  3827. hr = HRESULT_FROM_WIN32( GetLastError() );
  3828. ReportImportProblem( hr );
  3829. DBGPRINTF(( DBG_CONTEXT,
  3830. "Failed to delete mp file for %s/%s. hr = %x\n",
  3831. pszServicePath, achServiceInstance, hr ));
  3832. // don't take error as fatal and move on
  3833. }
  3834. if ( !mb.DeleteData( achServiceInstance, MD_SERIAL_CERT11,
  3835. IIS_MD_UT_SERVER, BINARY_METADATA ) )
  3836. {
  3837. //
  3838. // Unfortunately there will be some legacy data left behind
  3839. //
  3840. hr = HRESULT_FROM_WIN32( GetLastError() );
  3841. ReportImportProblem( hr );
  3842. DBGPRINTF(( DBG_CONTEXT,
  3843. "Failed to delete MD_SERIAL_CERT11 for %s/%s. hr = %x\n",
  3844. pszServicePath, achServiceInstance, hr ));
  3845. // don't take error as fatal and move on
  3846. }
  3847. }
  3848. EnumNext:
  3849. ;
  3850. }
  3851. mb.Close();
  3852. }
  3853. Finished:
  3854. if ( hKey != NULL )
  3855. {
  3856. RegCloseKey( hKey );
  3857. hKey = NULL;
  3858. }
  3859. if ( fCoInitialized )
  3860. {
  3861. CoUninitialize();
  3862. }
  3863. return;
  3864. }