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.
 
 
 
 
 
 

1013 lines
28 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 2002
//
// File: tinstall.cpp
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <stdio.h>
#include <certca.h>
#include <winldap.h>
#include <ntldap.h>
#include <dsrole.h>
#include <dsgetdc.h>
#include <accctrl.h>
#include <lmaccess.h>
#include <lmapibuf.h>
#include <lmerr.h>
//--------------------------------------------------------------------------
//
// Defines
//
//--------------------------------------------------------------------------
#define DS_RETEST_SECONDS 3
#define CVT_BASE (1000 * 1000 * 10)
#define CVT_SECONDS (1)
#define CERTTYPE_SECURITY_DESCRIPTOR_NAME L"NTSecurityDescriptor"
#define TEMPLATE_CONTAINER_NAME L"CN=Certificate Templates,CN=Public Key Services,CN=Services,"
#define SCHEMA_CONTAINER_NAME L"CN=Schema,"
typedef WCHAR *CERTSTR;
bool g_bSchemaIsW2K = false;
//--------------------------------------------------------------------------
//
//
// Helper Functions
//
//--------------------------------------------------------------------------
HANDLE GetClientIdentity()
{
HANDLE hHandle = NULL;
HANDLE hClientToken = NULL;
HANDLE hProcessToken = NULL;
// Step 1: attempt to acquire the thread token.
hHandle = GetCurrentThread();
if ( hHandle )
{
if ( OpenThreadToken(hHandle,
TOKEN_QUERY,
TRUE, // open as self
&hClientToken))
goto Exit;
}
if (hHandle != NULL)
{
CloseHandle(hHandle);
hHandle=NULL;
}
// We failed to get the thread token, now try to acquire the process token:
hHandle = GetCurrentProcess();
if (NULL == hHandle)
goto Exit;
if (!OpenProcessToken(hHandle,
TOKEN_DUPLICATE,
&hProcessToken))
goto Exit;
// security review 2/20/2002 BryanWal ok
if(!DuplicateToken(hProcessToken,
SecurityImpersonation,
&hClientToken))
goto Exit;
Exit:
if (NULL != hHandle)
CloseHandle(hHandle);
if (NULL != hProcessToken)
CloseHandle(hProcessToken);
return hClientToken;
}
HRESULT myHError(HRESULT hr)
{
if (S_OK != hr && S_FALSE != hr && !FAILED(hr))
{
hr = HRESULT_FROM_WIN32(hr);
if ( SUCCEEDED (hr) )
{
// A call failed without properly setting an error condition!
hr = E_UNEXPECTED;
}
}
return(hr);
}
HRESULT
myDupString (
IN WCHAR const *pwszIn,
IN WCHAR **ppwszOut)
{
ASSERT (pwszIn && ppwszOut);
if ( !pwszIn || !ppwszOut )
return E_POINTER;
HRESULT hr = S_OK;
// security review 2/20/2002 BryanWal ok
size_t cb = (wcslen(pwszIn) + 1) * sizeof(WCHAR);
*ppwszOut = (WCHAR *) LocalAlloc (LPTR, cb);
if (NULL == *ppwszOut)
{
hr = E_OUTOFMEMORY;
goto error;
}
// security review 2/20/2002 BryanWal ok
CopyMemory (*ppwszOut, pwszIn, cb);
hr = S_OK;
error:
return(hr);
}
DWORD
CAGetAuthoritativeDomainDn(
IN LDAP* LdapHandle,
OUT CString* pszDomainDn,
OUT CString* pszConfigDn
)
/*++
Routine Description:
This routine simply queries the operational attributes for the
domaindn and configdn.
The strings returned by this routine must be freed by the caller
using RtlFreeHeap() using the process heap.
Parameters:
LdapHandle : a valid handle to an ldap session
pszDomainDn : a pointer to a string to be allocated in this routine
pszConfigDn : a pointer to a string to be allocated in this routine
Return Values:
An error from the win32 error space.
ERROR_SUCCESS and
Other operation errors.
--*/
{
DWORD WinError = ERROR_SUCCESS;
ULONG LdapError;
LDAPMessage *SearchResult = NULL;
LDAPMessage *Entry = NULL;
WCHAR *Attr = NULL;
BerElement *BerElement;
WCHAR **Values = NULL;
WCHAR *AttrArray[3];
WCHAR *DefaultNamingContext = L"defaultNamingContext";
WCHAR *ConfigNamingContext = L"configurationNamingContext";
WCHAR *ObjectClassFilter = L"objectClass=*";
//
// These must be present
//
//
// Set the out parameters to null
//
if ( pszDomainDn )
*pszDomainDn = L"";
if ( pszConfigDn )
*pszConfigDn = L"";
//
// Query for the ldap server operational attributes to obtain the default
// naming context.
//
AttrArray[0] = DefaultNamingContext;
AttrArray[1] = ConfigNamingContext; // this is the sentinel
AttrArray[2] = NULL; // this is the sentinel
__try
{
LdapError = ldap_search_sW(LdapHandle,
NULL,
LDAP_SCOPE_BASE,
ObjectClassFilter,
AttrArray,
FALSE,
&SearchResult);
WinError = LdapMapErrorToWin32(LdapError);
if (ERROR_SUCCESS == WinError) {
Entry = ldap_first_entry(LdapHandle, SearchResult);
if (Entry)
{
Attr = ldap_first_attributeW(LdapHandle, Entry, &BerElement);
while (Attr)
{
if (!_wcsicmp(Attr, DefaultNamingContext))
{
if ( pszDomainDn )
{
Values = ldap_get_values(LdapHandle, Entry, Attr);
if (Values && Values[0])
{
*pszDomainDn = Values[0];
}
ldap_value_free(Values);
}
}
else if (!_wcsicmp(Attr, ConfigNamingContext))
{
if ( pszConfigDn )
{
Values = ldap_get_values(LdapHandle, Entry, Attr);
if (Values && Values[0])
{
*pszConfigDn = Values[0];
}
ldap_value_free(Values);
}
}
Attr = ldap_next_attribute(LdapHandle, Entry, BerElement);
}
}
if ( pszDomainDn && pszDomainDn->IsEmpty () )
{
//
// We could get the default domain - bail out
//
WinError = ERROR_CANT_ACCESS_DOMAIN_INFO;
}
else if ( pszConfigDn && pszConfigDn->IsEmpty () )
{
//
// We could get the default domain - bail out
//
WinError = ERROR_CANT_ACCESS_DOMAIN_INFO;
}
}
}
__except(WinError = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
{
}
// make sure we free this
if (SearchResult)
ldap_msgfree( SearchResult );
return WinError;
}
HRESULT myDoesDSExist (IN BOOL fRetry)
{
HRESULT hr = S_OK;
static BOOL s_fKnowDSExists = FALSE;
static HRESULT s_hrDSExists = HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
static FILETIME s_ftNextTest = {0,0};
if (s_fKnowDSExists && (s_hrDSExists != S_OK) && fRetry)
// s_fKnowDSExists = FALSE; // force a retry
{
FILETIME ftCurrent;
GetSystemTimeAsFileTime(&ftCurrent);
// if Compare is < 0 (next < current), force retest
if (0 > CompareFileTime(&s_ftNextTest, &ftCurrent))
s_fKnowDSExists = FALSE;
}
if (!s_fKnowDSExists)
{
GetSystemTimeAsFileTime(&s_ftNextTest);
// set NEXT in 100ns increments
((LARGE_INTEGER *) &s_ftNextTest)->QuadPart +=
(__int64) (CVT_BASE * CVT_SECONDS * 60) * DS_RETEST_SECONDS;
// NetApi32 is delay loaded, so wrap to catch problems when it's not available
__try
{
DOMAIN_CONTROLLER_INFO *pDCI;
DSROLE_PRIMARY_DOMAIN_INFO_BASIC *pDsRole;
// ensure we're not standalone
pDsRole = NULL;
hr = DsRoleGetPrimaryDomainInformation( // Delayload wrapped
NULL,
DsRolePrimaryDomainInfoBasic,
(BYTE **) &pDsRole);
if (S_OK == hr &&
(pDsRole->MachineRole == DsRole_RoleStandaloneServer ||
pDsRole->MachineRole == DsRole_RoleStandaloneWorkstation))
{
hr = HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
}
if (NULL != pDsRole)
{
DsRoleFreeMemory(pDsRole); // Delayload wrapped
}
if (S_OK == hr)
{
// not standalone; return info on our DS
pDCI = NULL;
hr = DsGetDcName( // Delayload wrapped
NULL,
NULL,
NULL,
NULL,
DS_DIRECTORY_SERVICE_PREFERRED,
&pDCI);
if (S_OK == hr && 0 == (pDCI->Flags & DS_DS_FLAG))
{
hr = HRESULT_FROM_WIN32(ERROR_CANT_ACCESS_DOMAIN_INFO);
}
if (NULL != pDCI)
{
NetApiBufferFree(pDCI); // Delayload wrapped
}
}
s_fKnowDSExists = TRUE;
}
__except(hr = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
{
}
// else just allow users without netapi flounder with timeouts
// if ds not available...
s_hrDSExists = myHError(hr);
}
return(s_hrDSExists);
}
//--------------------------------------------------------------------------
//
// AERobustLdapBind
//
//--------------------------------------------------------------------------
HRESULT
AERobustLdapBind(
OUT LDAP ** ppldap)
{
HRESULT hr = S_OK;
BOOL fForceRediscovery = FALSE;
DWORD dwDSNameFlags= DS_RETURN_DNS_NAME | DS_BACKGROUND_ONLY;
LDAP *pld = NULL;
ULONG ldaperr=LDAP_SERVER_DOWN;
do {
if(fForceRediscovery)
{
dwDSNameFlags |= DS_FORCE_REDISCOVERY;
}
ldaperr = LDAP_SERVER_DOWN;
if(NULL != pld)
{
ldap_unbind(pld);
pld=NULL;
}
// bind to ds
if((pld = ldap_initW(NULL, LDAP_PORT)) == NULL)
{
ldaperr = LdapGetLastError();
}
else
{
ldaperr = ldap_set_option(pld, LDAP_OPT_GETDSNAME_FLAGS, (VOID *)&dwDSNameFlags);
if(LDAP_SUCCESS == ldaperr)
{
ldaperr = ldap_set_option(pld, LDAP_OPT_SIGN, LDAP_OPT_ON);
if (LDAP_SUCCESS == ldaperr)
{
ldaperr = ldap_bind_sW(pld, NULL, NULL, LDAP_AUTH_NEGOTIATE);
}
}
}
hr = HRESULT_FROM_WIN32(LdapMapErrorToWin32(ldaperr));
if(fForceRediscovery)
{
break;
}
fForceRediscovery = TRUE;
} while(ldaperr == LDAP_SERVER_DOWN);
if(S_OK != hr)
goto error;
*ppldap = pld;
pld = NULL;
hr=S_OK;
error:
if(pld)
{
ldap_unbind(pld);
}
return hr;
}
//--------------------------------------------------------------------
static HRESULT GetRootDomEntitySid(SID ** ppSid, DWORD dwEntityRid)
{
HRESULT hr = S_OK;
NET_API_STATUS nasError = 0;
unsigned int nSubAuthorities = 0;
unsigned int nSubAuthIndex = 0;
// must be cleaned up
SID * psidRootDomEntity=NULL;
USER_MODALS_INFO_2 * pumi2=NULL;
DOMAIN_CONTROLLER_INFOW * pdci=NULL;
DOMAIN_CONTROLLER_INFOW * pdciForest=NULL;
// initialize out params
*ppSid=NULL;
// get the forest name
nasError=DsGetDcNameW(NULL, NULL, NULL, NULL, 0, &pdciForest);
if (NERR_Success!=nasError) {
hr=HRESULT_FROM_WIN32(nasError);
goto error;
}
// get the top level DC name
nasError=DsGetDcNameW(NULL, pdciForest->DnsForestName, NULL, NULL, 0, &pdci);
if (NERR_Success!=nasError) {
hr=HRESULT_FROM_WIN32(nasError);
goto error;
}
// get the domain Sid on the top level DC.
nasError = NetUserModalsGet (pdci->DomainControllerName, 2, (LPBYTE *)&pumi2);
if ( NERR_Success!=nasError || !pumi2 )
{
hr=HRESULT_FROM_WIN32(nasError);
goto error;
}
nSubAuthorities = *GetSidSubAuthorityCount (pumi2->usrmod2_domain_id);
// allocate storage for new Sid. account domain Sid + account Rid
psidRootDomEntity=(SID *)LocalAlloc(LPTR, GetSidLengthRequired((UCHAR)(nSubAuthorities+1)));
if(NULL == psidRootDomEntity)
{
hr=E_OUTOFMEMORY;
goto error;
}
// copy the first few pieces into the SID
// security review 2/20/2002 BryanWal ok
if (!InitializeSid(psidRootDomEntity,
GetSidIdentifierAuthority(pumi2->usrmod2_domain_id),
(BYTE)(nSubAuthorities+1)))
{
hr=HRESULT_FROM_WIN32(GetLastError());
goto error;
}
// copy existing subauthorities from account domain Sid into new Sid
for (nSubAuthIndex=0; nSubAuthIndex < nSubAuthorities ; nSubAuthIndex++) {
*GetSidSubAuthority(psidRootDomEntity, nSubAuthIndex)=
*GetSidSubAuthority(pumi2->usrmod2_domain_id, nSubAuthIndex);
}
// append Rid to new Sid
*GetSidSubAuthority(psidRootDomEntity, nSubAuthorities)=dwEntityRid;
*ppSid=psidRootDomEntity;
psidRootDomEntity=NULL;
hr=S_OK;
error:
if (NULL!=psidRootDomEntity) {
FreeSid(psidRootDomEntity);
}
if (NULL!=pdci) {
NetApiBufferFree(pdci);
}
if (NULL!=pdci) {
NetApiBufferFree(pdciForest);
}
if (NULL!=pumi2) {
NetApiBufferFree(pumi2);
}
return hr;
}
//--------------------------------------------------------------------
HRESULT GetRootDomAdminSid(SID ** ppSid)
{
return GetRootDomEntitySid(ppSid, DOMAIN_GROUP_RID_ADMINS);
}
HRESULT GetEnterpriseAdminSid(SID ** ppSid)
{
return GetRootDomEntitySid(ppSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS);
}
//***********************************************************************************
//
//
// Main
//
// This function will install new Windows 2002 certificate template if and onlyif
// the following conditions are TRUE:
//
// 1. Whistler Schema
// 2. New certificate templates have not yet installed
// 3. The caller has privilege to install templates in the directory
//
//
//***********************************************************************************
void InstallWindows2002CertTemplates ()
{
_TRACE (1, L"Entering InstallWindows2002CertTemplates()\n");
AFX_MANAGE_STATE (AfxGetStaticModuleState ());
OSVERSIONINFOEX osVersionInfo;
::ZeroMemory (&osVersionInfo, sizeof (osVersionInfo));
osVersionInfo.dwOSVersionInfoSize = sizeof (osVersionInfo);
if ( !::GetVersionEx (reinterpret_cast<OSVERSIONINFO*>(&osVersionInfo)) )
{
DWORD dwErr = GetLastError ();
_TRACE (0, L"GetVersionEx () failed: 0x%x. Template install attempt will not be made.", dwErr);
_TRACE (-1, L"Leaving InstallWindows2002CertTemplates()\n");
return;
}
if ( VER_NT_WORKSTATION == osVersionInfo.wProductType && // Windows XP Home Edition or Windows XP Professional
5 == osVersionInfo.dwMajorVersion && // Windows XP
1 == osVersionInfo.dwMinorVersion ) // Windows XP
{
// is Windows XP client
// NTRAIDE# 530524 CERTTMPL: ADMINPAK: adminpak installed on XP 2600
// Pro, will prompt to upgrade templates every time it is opened
_TRACE (0, L"Computer is running Windows XP workstation version. Template install attempt will not be made.\n");
_TRACE (-1, L"Leaving InstallWindows2002CertTemplates()\n");
return;
}
HRESULT hr=S_OK;
DWORD dwErr=0;
ULONG ldaperr=0;
struct l_timeval timeout;
DWORD dwCount=0;
LPWSTR awszAttr[2] = {0, 0};
BOOL fAccessAllowed = FALSE;
DWORD grantAccess=0;
GENERIC_MAPPING AccessMapping;
PRIVILEGE_SET ps;
DWORD dwPSSize = sizeof(ps);
LDAPMessage *Entry = NULL;
char sdBerValue[] = {0x30, 0x03, 0x02, 0x01, DACL_SECURITY_INFORMATION |
OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION };
LDAPControl se_info_control =
{
LDAP_SERVER_SD_FLAGS_OID_W,
{
5, sdBerValue
},
TRUE
};
LDAPControl permissive_modify_control =
{
LDAP_SERVER_PERMISSIVE_MODIFY_OID_W,
{
0, NULL
},
FALSE
};
PLDAPControl server_controls[3] =
{
&se_info_control,
&permissive_modify_control,
NULL
};
HCERTTYPE hCertType=NULL;
LDAP *pld = NULL;
CString szConfig;
CString szDN;
LDAPMessage *SearchResult = NULL;
LDAPMessage *SDResult = NULL;
struct berval **apSD =NULL;
PSECURITY_DESCRIPTOR pSD=NULL;
HANDLE hClientToken=NULL;
CString text;
CString caption;
SID * psidRootDomAdmins=NULL;
BOOL bIsRootDomAdmin=FALSE;
SID * psidEnterpriseAdmins=NULL;
BOOL bIsEnterpriseAdmin=FALSE;
CThemeContextActivator activator;
//*************************************************************
//
// check the schema version
//
_TRACE (0, L"Checking the schema version...\n");
//retrieve the ldap handle and the config string
if(S_OK != myDoesDSExist(TRUE))
{
_TRACE (0, L"No DS exists.\n");
goto error;
}
if ( S_OK != (hr = AERobustLdapBind (&pld)))
{
_TRACE (0, L"Error: Failed to bind to the DS.\n");
goto error;
}
dwErr = CAGetAuthoritativeDomainDn(pld, NULL, &szConfig);
if(ERROR_SUCCESS != dwErr)
{
_TRACE (0, L"Error: Failed to get the domain name.\n");
hr = HRESULT_FROM_WIN32(dwErr);
goto error;
}
szDN = SCHEMA_CONTAINER_NAME;
szDN += szConfig;
timeout.tv_sec = 300;
timeout.tv_usec = 0;
awszAttr[0]=L"cn";
awszAttr[1]=NULL;
ldaperr = ldap_search_stW(
pld,
const_cast <PWCHAR>((PCWSTR) szDN),
LDAP_SCOPE_ONELEVEL,
L"(cn=ms-PKI-Enrollment-Flag)",
awszAttr,
0,
&timeout,
&SearchResult);
if ( LDAP_SUCCESS != ldaperr )
{
_TRACE (0, L"We have W2K Schema. Exit\n");
g_bSchemaIsW2K = true;
hr = S_OK;
goto error;
}
dwCount = ldap_count_entries(pld, SearchResult);
if(0 == dwCount)
{
_TRACE (0, L"We have W2K Schema. Exit\n");
hr=S_OK;
goto error;
}
//*************************************************************
//
// check if keyRecoveryAgent certificate is present and
// and update to date
//
//check if all the templates are update to date
// NTRAID# 501806 Certtmpl.msc: Need to detect enterprise admin rights
// and verify each template for upgrade
if ( CAIsCertTypeCurrent (0,NULL) )
{
_TRACE (0, L"All certificate templates are current. Exit\n");
goto error;
}
//*************************************************************
//
// check the write access
//
//
_TRACE (0, L"Checking the write access...\n");
if(NULL==(hClientToken=GetClientIdentity()))
{
TRACE (0, L"Can not retrieve client identity.\n");
hr = myHError(GetLastError());
goto error;
}
//get the SD of the certificate template container
_TRACE (0, L"Getting the SD of the certificate template container...\n");
szDN = TEMPLATE_CONTAINER_NAME;
szDN += szConfig;
awszAttr[0]=CERTTYPE_SECURITY_DESCRIPTOR_NAME;
awszAttr[1]=NULL;
ldaperr = ldap_search_ext_sW(
pld,
const_cast <PWCHAR>((PCWSTR) szDN),
LDAP_SCOPE_BASE,
L"(objectclass=*)",
awszAttr,
0,
(PLDAPControl *)server_controls,
NULL,
&timeout,
10,
&SDResult);
if(LDAP_SUCCESS != ldaperr)
{
_TRACE (0, L"Fail to locate the template container.\n");
hr = myHError(LdapMapErrorToWin32(ldaperr));
goto error;
}
if(NULL == (Entry = ldap_first_entry(pld, SDResult)))
{
_TRACE (0, L"Can not find first entry for template container.\n");
hr = E_UNEXPECTED;
goto error;
}
apSD = ldap_get_values_len(pld, Entry, CERTTYPE_SECURITY_DESCRIPTOR_NAME);
if(apSD == NULL)
{
_TRACE (0, L"Can not retrieve security descriptor.\n");
hr = E_FAIL;
goto error;
}
pSD = LocalAlloc(LPTR, (*apSD)->bv_len);
if(pSD == NULL)
{
_TRACE (0, L"Error: No more memory.\n");
hr = E_OUTOFMEMORY;
goto error;
}
// security review 2/20/2002 BryanWal ok
CopyMemory(pSD, (*apSD)->bv_val, (*apSD)->bv_len);
//check the write access
_TRACE (0, L"Checking the write access...\n");
if(!AccessCheckByType(
pSD, // security descriptor
NULL, // SID of object being checked
hClientToken, // handle to client access token
ACTRL_DS_CREATE_CHILD |
ACTRL_DS_LIST, // requested access rights
NULL, // array of object types
0, // number of object type elements
&AccessMapping, // map generic to specific rights
&ps, // receives privileges used
&dwPSSize, // size of privilege-set buffer
&grantAccess, // retrieves mask of granted rights
&fAccessAllowed)) // retrieves results of access check);
{
_TRACE (0, L"Error: Fail to check the write access.\n");
hr = myHError(GetLastError());
goto error;
}
if(!fAccessAllowed)
{
_TRACE (0, L"No previlege to create certificate template. Exit\n");
hr = S_OK;
goto error;
}
//*************************************************************
//
// check the root domain admin rights
//
//
hr=GetRootDomAdminSid(&psidRootDomAdmins);
if( FAILED (hr) )
{
_TRACE (0, L"Error: GetRootDomAdminSid.\n");
goto error;
}
// check for membership
if (!CheckTokenMembership(NULL, psidRootDomAdmins, &bIsRootDomAdmin))
{
hr=HRESULT_FROM_WIN32(GetLastError());
_TRACE (0, L"Error: CheckTokenMembership.\n");
goto error;
}
//*************************************************************
//
// check the enterprise admin rights
//
//
hr=GetEnterpriseAdminSid(&psidEnterpriseAdmins);
if( FAILED (hr) )
{
_TRACE (0, L"Error: GetEnterpriseAdminSid.\n");
goto error;
}
// check for membership
if (!CheckTokenMembership(NULL, psidEnterpriseAdmins, &bIsEnterpriseAdmin))
{
hr=HRESULT_FROM_WIN32(GetLastError());
_TRACE (0, L"Error: CheckTokenMembership.\n");
goto error;
}
if ( !bIsEnterpriseAdmin || !bIsRootDomAdmin )
{
CString missingRights;
VERIFY (caption.LoadString (IDS_CERTTMPL));
if ( !bIsEnterpriseAdmin && !bIsRootDomAdmin )
VERIFY (missingRights.LoadString (IDS_NO_ENTERPRISE_OR_DOMAIN_ADMIN_RIGHTS));
else if ( !bIsEnterpriseAdmin )
VERIFY (missingRights.LoadString (IDS_NO_ENTERPRISE_ADMIN_RIGHTS));
else /* !bIsRootDomAdmin */
VERIFY (missingRights.LoadString (IDS_NO_DOMAIN_ADMIN_RIGHTS));
// security review 2/20/2002 BryanWal ok
text.FormatMessage (IDS_MUST_HAVE_DOMAIN_AND_ENTERPRISE_ADMIN_RIGHTS_TO_INSTALL_CERT_TEMPLATES,
(PCWSTR) missingRights);
MessageBoxW (NULL,
text,
caption,
MB_ICONWARNING | MB_OK);
_TRACE (0, L"No domain admin and/or enterprise admin rights to create certificate template. Exit\n");
hr = S_OK;
goto error;
}
//*************************************************************
//
// everything looks good. Install the certificate templates
//
//
_TRACE (0, L"Everything looks good. Installing the certificate templates...\n");
VERIFY (caption.LoadString (IDS_CERTTMPL));
VERIFY (text.LoadString (IDS_INSTALL_WINDOWS2002_CERT_TEMPLATES));
if ( IDYES == MessageBoxW (
NULL,
text,
caption,
MB_YESNO) )
{
hr = CAInstallDefaultCertType(0);
_TRACE (0, L"CAInstallDefaultCertType () returned: 0x%x\n", hr);
if(hr != S_OK)
{
VERIFY (caption.LoadString (IDS_CERTTMPL));
// security review 2/20/2002 BryanWal ok
text.FormatMessage (IDS_INSTALL_FAILURE_WINDOWS2002_CERT_TEMPLATES, GetSystemMessage (hr));
MessageBoxW(
NULL,
text,
caption,
MB_ICONWARNING | MB_OK);
}
else
{
VERIFY (caption.LoadString (IDS_CERTTMPL));
VERIFY (text.LoadString (IDS_INSTALL_SUCCESS_WINDOWS2002_CERT_TEMPLATES));
MessageBoxW(
NULL,
text,
caption,
MB_OK);
}
}
else
{
_TRACE (0, L"User chose not to install templates\n");
hr=S_OK;
}
error:
if (psidEnterpriseAdmins)
FreeSid(psidEnterpriseAdmins);
if (psidRootDomAdmins)
FreeSid(psidRootDomAdmins);
if(hClientToken)
CloseHandle(hClientToken);
if(pSD)
LocalFree(pSD);
if(apSD != NULL)
ldap_value_free_len(apSD);
if(SDResult)
ldap_msgfree(SDResult);
if(SearchResult)
ldap_msgfree(SearchResult);
if(hCertType)
CACloseCertType(hCertType);
if (pld)
ldap_unbind(pld);
_TRACE (-1, L"Leaving InstallWindows2002CertTemplates()\n");
}