windows-nt/Source/XPSP1/NT/ds/security/services/ca/certclib/dstest.cpp
2020-09-26 16:20:57 +08:00

286 lines
6.6 KiB
C++

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: dstest.cpp
//
// Contents: DS ping test
//
// History: 13-Mar-98 mattt created
//
//---------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
#include <winldap.h>
#include <dsrole.h>
#include <dsgetdc.h>
#include <lmaccess.h>
#include <lmapibuf.h>
#include <cainfop.h>
#include "csldap.h"
#define __dwFILE__ __dwFILE_CERTCLIB_DSTEST_CPP__
#define DS_RETEST_SECONDS 3
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);
_PrintIfError(hr, "DsRoleGetPrimaryDomainInformation");
if (S_OK == hr &&
(pDsRole->MachineRole == DsRole_RoleStandaloneServer ||
pDsRole->MachineRole == DsRole_RoleStandaloneWorkstation))
{
hr = HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
_PrintError(hr, "DsRoleGetPrimaryDomainInformation(no 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);
_PrintIfError(hr, "DsGetDcName");
if (S_OK == hr && 0 == (pDCI->Flags & DS_DS_FLAG))
{
hr = HRESULT_FROM_WIN32(ERROR_CANT_ACCESS_DOMAIN_INFO);
_PrintError(hr, "DsGetDcName(no domain info)");
}
if (NULL != pDCI)
{
NetApiBufferFree(pDCI); // Delayload wrapped
}
}
s_fKnowDSExists = TRUE;
}
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
{
}
// else just allow users without netapi flounder with timeouts
// if ds not available...
s_hrDSExists = myHError(hr);
_PrintIfError2(
s_hrDSExists,
"DsRoleGetPrimaryDomainInformation/DsGetDcName",
HRESULT_FROM_WIN32(ERROR_NETWORK_UNREACHABLE));
}
return(s_hrDSExists);
}
HRESULT
myRobustLdapBind(
OUT LDAP **ppldap,
IN BOOL fGC)
{
return(myRobustLdapBindEx(fGC, FALSE, LDAP_VERSION2, NULL, ppldap, NULL));
}
HRESULT
myRobustLdapBindEx(
IN BOOL fGC,
IN BOOL fRediscover,
IN ULONG uVersion,
OPTIONAL IN WCHAR const *pwszDomainName,
OUT LDAP **ppldap,
OPTIONAL OUT WCHAR **ppwszForestDNSName)
{
HRESULT hr;
ULONG ldaperr;
DWORD GetDSNameFlags;
LDAP *pld = NULL;
GetDSNameFlags = DS_RETURN_DNS_NAME;
if (fGC)
{
GetDSNameFlags |= DS_GC_SERVER_REQUIRED;
}
// bind to ds
while (TRUE)
{
if (NULL != pld)
{
ldap_unbind(pld);
}
pld = ldap_init(
const_cast<WCHAR *>(pwszDomainName),
fGC? LDAP_GC_PORT : LDAP_PORT);
if (NULL == pld)
{
hr = myHLdapLastError(NULL, NULL);
if (!fRediscover)
{
_PrintError2(hr, "ldap_init", hr);
fRediscover = TRUE;
continue;
}
_JumpError(hr, error, "ldap_init");
}
if (fRediscover)
{
GetDSNameFlags |= DS_FORCE_REDISCOVERY;
}
ldaperr = ldap_set_option(
pld,
LDAP_OPT_GETDSNAME_FLAGS,
(VOID *) &GetDSNameFlags);
if (LDAP_SUCCESS != ldaperr)
{
hr = myHLdapError(pld, ldaperr, NULL);
if (!fRediscover)
{
_PrintError2(hr, "ldap_set_option", hr);
fRediscover = TRUE;
continue;
}
_JumpError(hr, error, "ldap_set_option");
}
// do not want this to turn on if uVersion is not LDAP_VERSION2
//if (LDAP_VERSION2 == uVersion)
if (IsWhistler())
{
ldaperr = ldap_set_option(pld, LDAP_OPT_SIGN, LDAP_OPT_ON);
if (LDAP_SUCCESS != ldaperr)
{
hr = myHLdapError2(pld, ldaperr, LDAP_PARAM_ERROR, NULL);
if (!fRediscover)
{
_PrintError2(hr, "ldap_set_option", hr);
fRediscover = TRUE;
continue;
}
_JumpError(hr, error, "ldap_set_option");
}
}
// set the client version. No need to set LDAP_VERSION2 since
// this is the default
if (LDAP_VERSION2 != uVersion)
{
ldaperr = ldap_set_option(pld, LDAP_OPT_VERSION, &uVersion);
if (LDAP_SUCCESS != ldaperr)
{
hr = myHLdapError(pld, ldaperr, NULL);
if (!fRediscover)
{
_PrintError2(hr, "ldap_set_option", hr);
fRediscover = TRUE;
continue;
}
_JumpError(hr, error, "ldap_set_option");
}
}
ldaperr = ldap_bind_s(pld, NULL, NULL, LDAP_AUTH_NEGOTIATE);
if (LDAP_SUCCESS != ldaperr)
{
hr = myHLdapError(pld, ldaperr, NULL);
if (!fRediscover)
{
_PrintError2(hr, "ldap_bind_s", hr);
fRediscover = TRUE;
continue;
}
_JumpError(hr, error, "ldap_bind_s");
}
if (NULL != ppwszForestDNSName)
{
WCHAR *pwszDomainControllerName;
hr = myLdapGetDSHostName(pld, &pwszDomainControllerName);
if (S_OK != hr)
{
if (!fRediscover)
{
_PrintError2(hr, "myLdapGetDSHostName", hr);
fRediscover = TRUE;
continue;
}
_JumpError(hr, error, "myLdapGetDSHostName");
}
hr = myDupString(pwszDomainControllerName, ppwszForestDNSName);
_JumpIfError(hr, error, "myDupString");
}
break;
}
*ppldap = pld;
pld = NULL;
hr = S_OK;
error:
if (NULL != pld)
{
ldap_unbind(pld);
}
return(hr);
}