// certmap.cpp : Implementation of CCertmapApp and DLL registration. #include "stdafx.h" #include "certmap.h" #include "iishelp.h" #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif CCertmapApp /*NEAR*/ theApp; // tompop: does this have to be near? We are now getting errors when we finish refering to this var's addr const GUID CDECL BASED_CODE _tlid = { 0xbbd8f298, 0x6f61, 0x11d0, { 0xa2, 0x6e, 0x8, 0, 0x2b, 0x2c, 0x6f, 0x32 } }; const WORD _wVerMajor = 1; const WORD _wVerMinor = 0; //-------------------------------------------------------------------------- void CCertmapApp::WinHelp(DWORD dwData, UINT nCmd ) { WinHelpDebug(dwData); COleControlModule::WinHelp(dwData,nCmd); } //////////////////////////////////////////////////////////////////////////// // CCertmapApp::InitInstance - DLL initialization BOOL CCertmapApp::InitInstance() { BOOL bInit = COleControlModule::InitInstance(); // init ole stuff HRESULT hRes = CoInitialize(NULL); // finally, we need to redirect the winhelp file location to something more desirable CString sz; CString szHelpLocation; sz.LoadString( IDS_HELPLOC_PWSHELP ); // expand the path ExpandEnvironmentStrings( sz, // pointer to string with environment variables szHelpLocation.GetBuffer(MAX_PATH + 1), // pointer to string with expanded environment variables MAX_PATH // maximum characters in expanded string ); szHelpLocation.ReleaseBuffer(); // free the existing path, and copy in the new one if ( m_pszHelpFilePath ) free((void*)m_pszHelpFilePath); m_pszHelpFilePath = _tcsdup(szHelpLocation); // get debug flag GetOutputDebugFlag(); return bInit; } //////////////////////////////////////////////////////////////////////////// // CCertmapApp::ExitInstance - DLL termination // tjp: note that in 'CCertmapApp::InitInstance()' we add our help file to the // help path. do we need to remove it on clean up here? int CCertmapApp::ExitInstance() { CoUninitialize(); return COleControlModule::ExitInstance(); } ///////////////////////////////////////////////////////////////////////////// // MigrateGUIDS - does all the GUID migration work. We pass back the // return value of True iff we find GUIDs in the registry and migrate // them to the metabase. // // We are called by top level fnct: InstallCertServerGUIDs that creates // our 'info' structure and handles all the metabase init work. ///////////////////////////////////////////////////////////////////////////// // This code is written in response to bug # 167410. // // This fix will handle all the GUID migration work, moving GUIDS that // CertServer placed in the registry into the metabase for Beta2. // A more general install/deinstall mechanism for products that // work with IIS will be come post-Beta2. // // DETAILS: // -------- // // We look for evidence of CertServer by examing the Registry because // CertServer will write some entries under: // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\KeyRing\Parameters\Certificate // Authorities\Microsoft Certificate Server // // CertServer currently outputs: // CertGetConfig "{C6CC49B0-CE17-11D0-8833-00A0C903B83C}" // CertRequest "{98AFF3F0-5524-11D0-8812-00A0C903B83C}" // // If we see the manditory 'CertRequest' entry, we will load as many strings // as we find, while defaulting the ones that are missing. See below // for the equivalent mdutil commands for what defaults are used // // => if we dont find 'CertRequest' we give up [meaning remove // any present MB GUID string entries] // // When we find that CertServer is installed, we dont fully believe that // certserver is still there. To prove that its there we will do a // CoCreateInstance on CertConfig. If that works we install metabase // entries that are the equivalent of the following mdutil commands: // // ## ICERTGETCONFIG default setting: // mdutil SET "w3svc/CertServers/Microsoft Certificate Server" -dtype:STRING - // -utype:UT_SERVER -prop 5571 -value "{C6CC49B0-CE17-11D0-8833-00A0C903B83C}" // // ## ICERTREQUEST default setting: // mdutil SET "w3svc/CertServers/Microsoft Certificate Server" -dtype:STRING // -utype:UT_SERVER -prop 5572 -value "{98AFF3F0-5524-11D0-8812-00A0C903B83C}" // // ## ICERTCONFIG default setting: // mdutil SET "w3svc/CertServers/Microsoft Certificate Server" -dtype:STRING // -utype:UT_SERVER -prop 5574 -value "{372fce38-4324-11d0-8810-00a0c903b83c}" // // If the CoCreateInstance fails, we give up and remove MB GUID entries. // // --------------------------------------------------------------- // NOTE that we will either install or DE-install the metabase // GUID strings based on its decision that CertServer is present. // If we find GUID strings in the metabase but can not do a // CoCreateInstance on CertConfig: // we remove them so that the rest of CertWizard will see CertServer // Guids iff we can use CertServer. // --------------------------------------------------------------- // NOTE also that if we make a decision to install GUID strings // into the metabase, we honor/preserve any present GUID strings that // are present in the metabase. // --------------------------------------------------------------- // ///////////////////////////////////////////////////////////////////////////// /*ddddddddddddddd BOOL MigrateGUIDS( ADMIN_INFO& info ) { BOOL bRet = FALSE; // value to return, set to F // for defensive reasons. BOOL bFoundCertSrvRegistryEntries = FALSE; // assume false for now TCHAR* szRegPath = _T("SOFTWARE\\Microsoft\\KeyRing\\Parameters\\Certificate Authorities\\Microsoft Certificate Server"); //----------------------------------------------------------------------- // In each of the following 3 sets of parameters, we have (1) a string // like "CertRequest" that CertServer uses in the registry, (2) a default // value to use like "{98AFF3F0-5524-11D0-8812-00A0C903B83C}" that we // use if we can not find anything in the registry, and (3) a CString // to hold the GUID. The value in the CString will be stored in the MB. //----------------------------------------------------------------------- // CertRequest - variables TCHAR* szCertRequest = _T("CertRequest"); TCHAR* szCertRequestGUIDdefault = _T( "{98AFF3F0-5524-11D0-8812-00A0C903B83C}" ); CString szCertRequestGUID; // CertConfig - variables TCHAR* szCertConfig = _T("CertConfig"); TCHAR* szCertConfigGUIDdefault = _T( "{372fce38-4324-11d0-8810-00a0c903b83c}" ); CString szCertConfigGUID; // CertGetConfig - variables TCHAR* szCertGetConfig = _T("CertGetConfig"); TCHAR* szCertGetConfigGUIDdefault = _T( "{C6CC49B0-CE17-11D0-8833-00A0C903B83C}"); CString szCertGetConfigGUID; CString szCertServerMetabaseRoot( SZ_ROOT_CERT_SERV_MB_PATH ); // SZ_ROOT_CERT_SERV_MB_PATH = "/LM/W3SVC/CertServers" szCertServerMetabaseRoot += _T("/Microsoft Certificate Server"); #ifdef DEBUGGING CEditDialog dlg(szCertServerMetabaseRoot, _T("use this to test adding new CertServer entries." " In order for us to install a new key you have to change the path" " below to something [strange] and not already in the metabase.")); dlg.DoModal(); #endif // the following string will be restored into info.szMetaBasePath before // we exit this fnct. We switch out the [info.szMetaBasePath] so that // we can use our native Set/Get metabase string fncts. // We switch it to: "/LM/W3SVC/CertServers/Microsoft Certificate Server" // CString szSaved_info_szMetaBasePath( info.szMetaBasePath ); info.szMetaBasePath = szCertServerMetabaseRoot; // if we dont find HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\KeyRing\Parameters\ // Certificate Authorities\Microsoft Certificate Server" // with key: CertRequest quit! CertServer should have installed this. // We are forgiving about the other 2 Registry GUID strings //------------------------------------------------------------------------- if ( Reg::GetNameValueIn( szRegPath, szCertRequest, szCertRequestGUID, HKEY_LOCAL_MACHINE )) { bFoundCertSrvRegistryEntries = TRUE; } if (! Reg::GetNameValueIn( szRegPath, szCertConfig, szCertConfigGUID, HKEY_LOCAL_MACHINE )) { szCertConfigGUID = szCertConfigGUIDdefault; // assign default } if (! Reg::GetNameValueIn( szRegPath, szCertGetConfig, szCertGetConfigGUID, HKEY_LOCAL_MACHINE )) { szCertGetConfigGUID = szCertGetConfigGUIDdefault; // assign default } //------------------------------------------------------------------------ // First lets try to create the directory path: the user might have // deleted it or this might be a virgin machine. //------------------------------------------------------------------------ { CWrapMetaBase& MB = info.meta.m_mbWrap; // this is the MetaBase Wrapper // its already been openned by // openMetaDataForWrite if ( FALSE == openMetaDataForWrite(info, FALSE) ) { if (ERROR_PATH_NOT_FOUND == HRESULT_CODE( MB.getHRESULT() )) { // lets create the path in the metabase, using AddObject. // recursively creates a "pathway in the metabase". E.g. assume that you // want to make sure that "/LM/W3SVC/CertServers/Microsoft Certificate Server" // is in the metabase. you can open /LM/W3SVC and do a AddKey() on // "CertServers/Microsoft Certificate Server" to create that stub. // above we set: info.szMetaBasePath = szCertServerMetabaseRoot // here we will temporarily pretend that our root is at level // /LM/W3SVC which we assume is at the top of szCertServerMetabaseRoot // and then call AddKey TCHAR szPath[400]; TCHAR* szRootPrefix = _T("/LM/W3SVC"); UINT nRootPrefixLen = STRLEN(szRootPrefix); STRCPY(szPath, szCertServerMetabaseRoot); if (STRNICMP(szRootPrefix, szPath, nRootPrefixLen) != 0) goto returnFALSE; // we could not figure out a common Root info.szMetaBasePath = szRootPrefix; if ( FALSE == openMetaDataForWrite(info) ) goto returnFALSE; // we could not open the metabase // the metabase path is already position to the proper directory // in the MB object. MB will prepend that path to the subDirectory // that we want to create, the following will jump past the trailing // '/' separating the root and the rest of the sub-directory // e.g. "/CertServers/Microsoft Certificate Server" // // We dont do any other error checking besides notifying and // returning FALSE. if (FALSE == MB.AddObject( &szPath[nRootPrefixLen] )) { NotifyUsers_CouldNotAccessMetaBase( MB.getHRESULT() ); goto returnFALSE; // we could not create required path } // since we are continuing, we reset back our proper path. info.szMetaBasePath = szCertServerMetabaseRoot; } else { goto returnFALSE; // we could not open the metabase } } } //------------------------------------------------------------------------ // Below we dont deal with the XENROLL GUID setting that is for future usage // PLUS its not CertServer Related, its Xenroll related. We dont touch it. //------------------------------------------------------------------------ { // lets see if we can do a CoCreateInstance on CertRequest. If we can not // we believe that certServer is not installed and set/clear MB entries // The following values are set or cleared: // // # define MD_SSL_CERT_WIZGUID_ICERTGETCONFIG ( IIS_MD_SSL_BASE+71 ) // # define MD_SSL_CERT_WIZGUID_ICERTREQUEST ( IIS_MD_SSL_BASE+72 ) // # define MD_SSL_CERT_WIZGUID_XENROLL ( IIS_MD_SSL_BASE+73 ) FUTURE USAGE // # define MD_SSL_CERT_WIZGUID_ICERTCONFIG ( IIS_MD_SSL_BASE+74 ) //------------------------------------------------------------------------ IPtr iptr; CString szRemoteDCOMTargetMachine; // REMEMBER bRet returns whether we were able to delete everything // or set everything that we were wanting to set // in both cases assume now that we have success and update bRet when // we find errors, we continue as long as possible. E.g. we add or delete // as many entries as possible and return our status value to the caller. bRet = TRUE; if ( (FALSE == bFoundCertSrvRegistryEntries) || (FALSE == GetICertConfigIPtrFromGuid( iptr, szCertConfigGUID, &szRemoteDCOMTargetMachine)) ) { // remove MB entries! #ifdef DEBUGGING DODBG MsgBox( _T("adding CertServer MB entries")); #endif if ( FALSE == openMetaDataForWrite(info) ) { goto returnFALSE; // we could not open the metabase } // We just need to blow away the cert info in the metabase // which we do using the meta data wrapper // deleting values CWrapMetaBase& MB = info.meta.m_mbWrap; // this is the MetaBase Wrapper // its already been openned by // openMetaDataForWrite // try deletes once // In C++ &&= does not exist. However [bRet &= FALSE;] is OK, but we dont // have a uniform single value of TRUE in C/C++ so its not safe to use &= // to chain a set of TRUE-value // so we can not do: // bRet &&= MB.DeleteData( _T(""), // MD_SSL_CERT_WIZGUID_ICERTGETCONFIG, STRING_METADATA); // so we will use a [if (! xxx) bRet=FALSE;] construct below if (! MB.DeleteData( _T(""), MD_SSL_CERT_WIZGUID_ICERTGETCONFIG, STRING_METADATA)) bRet=FALSE; if (! MB.DeleteData( _T(""), MD_SSL_CERT_WIZGUID_ICERTREQUEST, STRING_METADATA)) bRet=FALSE; if (! MB.DeleteData( _T(""), MD_SSL_CERT_WIZGUID_ICERTCONFIG, STRING_METADATA)) bRet=FALSE; MB.Close(); } else { CString szPresentValue; // used to read the present value // any metabase value so that we // can preserve it. #ifdef DEBUGGING DODBG MsgBox( _T("adding CertServer MB entries")); #endif // add MB entries! If an entry already exists, leave it alone. if (! GetMetaBaseString ( info, IN MD_SSL_CERT_WIZGUID_ICERTREQUEST, IN szPresentValue ) ) { if (!SetMetaBaseString ( info, IN MD_SSL_CERT_WIZGUID_ICERTREQUEST, IN szCertRequestGUID ) ) bRet=FALSE; } if (! GetMetaBaseString ( info, IN MD_SSL_CERT_WIZGUID_ICERTCONFIG, IN szPresentValue ) ) { if (!SetMetaBaseString ( info, IN MD_SSL_CERT_WIZGUID_ICERTCONFIG, IN szCertConfigGUID ) ) bRet=FALSE; } if (! GetMetaBaseString ( info, IN MD_SSL_CERT_WIZGUID_ICERTGETCONFIG, IN szPresentValue ) ) { if (!SetMetaBaseString ( info, IN MD_SSL_CERT_WIZGUID_ICERTGETCONFIG, IN szCertGetConfigGUID ) ) bRet=FALSE; } } } commonReturn: // this is the common return so that we an set // back the metabase path. We saved it so that // we can switch to where the GUIDs live: // the following will restore the original [info.szMetaBasePath] value // before we switched it to: "/LM/W3SVC/CertServers/..." // info.szMetaBasePath = szSaved_info_szMetaBasePath; return(bRet); returnFALSE: // this will cause a FALSE return and do all things // required in our "common return" bRet = FALSE; goto commonReturn; } */ ///////////////////////////////////////////////////////////////////////////// // DllRegisterServer - Adds entries to the system registry STDAPI DllRegisterServer(void) { AFX_MANAGE_STATE(_afxModuleAddrThis); if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid)) return ResultFromScode(SELFREG_E_TYPELIB); if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE)) return ResultFromScode(SELFREG_E_CLASS); return NOERROR; } ///////////////////////////////////////////////////////////////////////////// // DllUnregisterServer - Removes entries from the system registry STDAPI DllUnregisterServer(void) { AFX_MANAGE_STATE(_afxModuleAddrThis); if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor)) return ResultFromScode(SELFREG_E_TYPELIB); if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE)) return ResultFromScode(SELFREG_E_CLASS); return NOERROR; } BOOL IsLegacyMetabase(IMSAdminBase* pMB) { BOOL bReturn = FALSE; CWrapMetaBase mbBase; CString szObjectPath = _T("LM/W3SVC/Info"); DWORD dwMajorVersion = 0; BOOL f = mbBase.FInit(pMB); if ( !f ) return FALSE; // open the base object f = mbBase.Open( szObjectPath, METADATA_PERMISSION_READ); if ( !f ) { return FALSE; } DWORD dwFlags = METADATA_NO_ATTRIBUTES; if (mbBase.GetDword( _T(""), MD_SERVER_VERSION_MAJOR, IIS_MD_UT_SERVER, &dwMajorVersion) ) { if (dwMajorVersion < 6) { bReturn = TRUE; } } mbBase.Close(); return bReturn; }