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.
475 lines
19 KiB
475 lines
19 KiB
// certmap.cpp : Implementation of CCertmapApp and DLL registration.
|
|
|
|
#include "stdafx.h"
|
|
#include "certmap.h"
|
|
#include "iishelp.h"
|
|
|
|
#include <iiscnfgp.h>
|
|
|
|
#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<ICertConfig, &IID_ICertConfig> 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;
|
|
}
|