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.
 
 
 
 
 
 

1127 lines
26 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 2000
//
// File: info.cpp
//
//--------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
#include <certca.h>
#include <ntdsapi.h>
#include <dsgetdc.h>
#include <lmerr.h>
#include <lmaccess.h>
#include <lmapibuf.h>
#define __dwFILE__ __dwFILE_CERTUTIL_INFO_CPP__
#define DC_DELBAD 0x00000001
#define DC_DELALL 0x00000002
#define DC_VERIFY 0x00000004
// If you invoke DSSTORE with DC=mydc,DC=rd,DC=com DSSTORE calls
// DsGetDcName(NULL, L"mydc", NULL, NULL, DS_RETURN_DNS_NAME, &pDCInfo);
//
// I suspect changing the code to pass L"mydc.rd.com" instead of L"mydc" would
// solve the problem. I will look into this for the port of the code to
// certutil.exe.
//
// -----Original Message-----
// From: Christophe Lapeyre (Intl Vendor)
// Sent: Tuesday, January 09, 2001 3:30 AM
// To: Certificate Server Discussion Alias
// Subject: DSSTORE error 1355 (DsGetDCName failed)
//
//
// Hi all,
//
// I encountered the following problem with the DSSTORE tool:
//
// DSSTORE DC=mydc,DC=rd,DC=com -display
// DsGetDCName failed! - rc=1355 GLE - 3e5
// DsGetDCName failed! - rc=1355 GLE - 3e5
//
// Nltest /dsgetdc:mydc.rd.com just run ok.
//
// My Netbios domain name is different from my DNS domain name.
//
//
//
// There is a preview Kb article numbered Q280122, but I haven't been able to
// find a fix for this.
HRESULT
ExtractCertSubject(
IN CERT_CONTEXT const *pcc,
IN DWORD dwType,
IN DWORD dwFlags,
OUT WCHAR **ppwszOut)
{
HRESULT hr;
DWORD cwc;
DWORD cwcBuf;
WCHAR *pwszOut = NULL;
*ppwszOut = NULL;
cwcBuf = 0;
while (TRUE)
{
cwc = CertGetNameString(
pcc,
dwType,
dwFlags,
NULL, // pvTypePara
pwszOut,
cwcBuf);
if (1 == cwc)
{
hr = CRYPT_E_NOT_FOUND;
_JumpError(hr, error, "CertGetNameString");
}
if (NULL != pwszOut)
{
break;
}
pwszOut = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
if (NULL == pwszOut)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
cwcBuf = cwc;
}
*ppwszOut = pwszOut;
pwszOut = NULL;
hr = S_OK;
error:
if (NULL != pwszOut)
{
LocalFree(pwszOut);
}
return(hr);
}
static WCHAR *s_apwszKDCTemplates[] = {
wszCERTTYPE_DC_AUTH,
wszCERTTYPE_DS_EMAIL_REPLICATION,
wszCERTTYPE_DC,
};
HRESULT
CheckForKDCCertificate(
IN WCHAR const *pwszDC,
IN DWORD dwFlags)
{
HRESULT hr;
HCERTSTORE hStoreRemote = NULL;
WCHAR wszStorePath[512];
WCHAR *apwszCertType[2] = { NULL, NULL };
DWORD cCert = 0;
DWORD dwOpenFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
CERT_CONTEXT const *pcc = NULL;
CERT_CONTEXT const *pccPrev = NULL;
BOOL fDelete;
BOOL fNewLine;
DWORD i;
DWORD j;
CERT_ENHKEY_USAGE *pUsage = NULL;
// If not doing delete operations, open "ReadOnly"
if (0 == ((DC_DELALL | DC_DELBAD) & dwFlags))
{
dwOpenFlags |= CERT_STORE_READONLY_FLAG;
}
swprintf(wszStorePath, L"\\\\%ws\\" wszMY_CERTSTORE, pwszDC);
hStoreRemote = CertOpenStore(
CERT_STORE_PROV_SYSTEM_W,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
NULL,
dwOpenFlags,
(VOID *) wszStorePath);
if (NULL == hStoreRemote)
{
hr = myHLastError();
_JumpError2(hr, error, "CertOpenStore", E_ACCESSDENIED);
}
wprintf(
myLoadResourceString(IDS_FORMAT_KDCCERTS), // "** KDC Certificates for DC %ws"
pwszDC);
wprintf(wszNewLine);
// Look for KDC certs
fNewLine = FALSE;
while (TRUE)
{
BOOL fKDCCert;
for (i = 0; i < ARRAYSIZE(apwszCertType); i++)
{
if (NULL != apwszCertType[i])
{
LocalFree(apwszCertType[i]);
apwszCertType[i] = NULL;
}
}
pcc = CertEnumCertificatesInStore(hStoreRemote, pccPrev);
if (NULL == pcc)
{
hr = myHLastError();
_PrintError2(hr, "CertEnumCertificatesInStore", CRYPT_E_NOT_FOUND);
break;
}
pccPrev = pcc;
fKDCCert = FALSE;
hr = cuGetCertType(
pcc->pCertInfo,
&apwszCertType[0], // ppwszCertTypeNameV1
NULL, // ppwszDisplayNameV1
NULL, // ppwszCertTypeObjId
&apwszCertType[1], // ppwszCertTypeName
NULL); // ppwszDisplayName
if (S_OK != hr)
{
_PrintError(hr, "cuGetCertType");
}
else
{
for (i = 0; i < ARRAYSIZE(apwszCertType); i++)
{
if (NULL != apwszCertType[i])
{
for (j = 0; j < ARRAYSIZE(s_apwszKDCTemplates); j++)
{
if (0 == mylstrcmpiS(
apwszCertType[i],
s_apwszKDCTemplates[j]))
{
fKDCCert = TRUE;
}
}
}
}
}
if (!fKDCCert)
{
WCHAR const *pwsz = apwszCertType[0];
if (NULL == apwszCertType[0])
{
pwsz = apwszCertType[1];
}
if (g_fVerbose)
{
wprintf(
myLoadResourceString(IDS_FORMAT_CERT_TYPE_NOT_DC),
pwsz);
wprintf(wszNewLine);
}
}
if (NULL != pUsage)
{
LocalFree(pUsage);
pUsage = NULL;
}
hr = myCertGetEnhancedKeyUsage(
pcc,
CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
&pUsage);
if (S_OK != hr)
{
_PrintError2(hr, "myCertGetEnhancedKeyUsage", CRYPT_E_NOT_FOUND);
}
else
{
for (i = 0; i < pUsage->cUsageIdentifier; i++)
{
if (0 == strcmp(
szOID_KP_SMARTCARD_LOGON,
pUsage->rgpszUsageIdentifier[i]))
{
fKDCCert = TRUE;
break;
}
}
}
if (!fKDCCert)
{
if (g_fVerbose)
{
wprintf(
myLoadResourceString(IDS_FORMAT_CERT_USAGE_MISSING),
L"szOID_KP_SMARTCARD_LOGON");
wprintf(wszNewLine);
}
if (!g_fForce || fDelete)
{
continue;
}
}
// Cert passed test, dump issuer and subject
wprintf(myLoadResourceString(IDS_FORMAT_CERT_COLON), cCert);
wprintf(wszNewLine);
hr = cuDumpAsnBinaryQuiet(
pcc->pbCertEncoded,
pcc->cbCertEncoded,
MAXDWORD);
_PrintIfError(hr, "cuDumpAsnBinaryQuiet");
wprintf(wszNewLine);
cCert++;
// perform operations on certificatess
fDelete = 0 != (DC_DELALL & dwFlags);
if ((DC_VERIFY | DC_DELBAD) & dwFlags)
{
char *apszUsage[] =
{
szOID_PKIX_KP_SERVER_AUTH,
szOID_KP_SMARTCARD_LOGON,
};
DWORD VerifyState;
hr = cuVerifyCertContext(
pcc,
NULL,
ARRAYSIZE(apszUsage),
apszUsage,
0, // cIssuancePolicies
NULL, // apszIssuancePolicies
TRUE, // fNTAuth
&VerifyState);
if (S_OK != hr)
{
_PrintError(hr, "cuVerifyCertContext");
if (CRYPT_E_REVOCATION_OFFLINE != hr)
{
fDelete = 0 != (DC_DELBAD & dwFlags);
}
}
}
if (fDelete)
{
CERT_CONTEXT const *pccDel;
pccDel = CertDuplicateCertificateContext(pcc);
if (!CertDeleteCertificateFromStore(pccDel))
{
hr = myHLastError();
wprintf(myLoadResourceString(IDS_FORMAT_DELETE_CERT_FROM_STORE_FAILED), hr);
wprintf(wszNewLine);
}
else
{
wprintf(myLoadResourceString(IDS_FORMAT_DELETE_DC_CERT));
wprintf(wszNewLine);
}
}
}
swprintf(wszStorePath, myLoadResourceString(IDS_FORMAT_KDC_PATH), cCert, pwszDC);
wprintf(wszStorePath);
wprintf(wszNewLine);
if (0 == cCert)
{
wprintf(myLoadResourceString(IDS_NO_KDC_MY_STORE));
wprintf(wszNewLine);
hr = CRYPT_E_NOT_FOUND;
_JumpError(hr, error, "cCert");
}
hr = S_OK;
error:
if (NULL != pUsage)
{
LocalFree(pUsage);
}
for (i = 0; i < ARRAYSIZE(apwszCertType); i++)
{
if (NULL != apwszCertType[i])
{
LocalFree(apwszCertType[i]);
}
}
if (NULL != hStoreRemote)
{
CertCloseStore(hStoreRemote, 0);
}
return(hr);
}
// This function queries the access token specified by the hToken parameter,
// and returns an allocated copy of the TokenUser information on success.
//
// The access token specified by hToken must be opened for TOKEN_QUERY access.
//
// On success, the return value is TRUE. The caller is responsible for freeing
// the resultant UserSid via LocalFree.
//
// On failure, the caller does not need to free any buffer.
HRESULT
GetTokenUserSid(
IN HANDLE hToken, // token to query
IN OUT PSID *ppUserSid) // resultant user sid
{
HRESULT hr;
BYTE FastBuffer[256];
BYTE *SlowBuffer = NULL;
TOKEN_USER *ptgUser;
DWORD cbBuffer;
DWORD cbSid;
*ppUserSid = NULL;
// try querying based on a fast stack based buffer first.
ptgUser = (TOKEN_USER *) FastBuffer;
cbBuffer = sizeof(FastBuffer);
if (!GetTokenInformation(
hToken, // identifies access token
TokenUser, // TokenUser info type
ptgUser, // retrieved info buffer
cbBuffer, // size of buffer passed-in
&cbBuffer)) // required buffer size
{
hr = myHLastError();
if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr)
{
_JumpError(hr, error, "GetTokenInformation");
}
// try again with the specified buffer size
SlowBuffer = (BYTE *) LocalAlloc(LMEM_FIXED, cbBuffer);
if (NULL == SlowBuffer)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
ptgUser = (TOKEN_USER *) SlowBuffer;
if (!GetTokenInformation(
hToken, // identifies access token
TokenUser, // TokenUser info type
ptgUser, // retrieved info buffer
cbBuffer, // size of buffer passed-in
&cbBuffer)) // required buffer size
{
hr = myHLastError();
_JumpError(hr, error, "GetTokenInformation");
}
}
// if we got the token info, copy the relevant element for the caller.
cbSid = GetLengthSid(ptgUser->User.Sid);
*ppUserSid = LocalAlloc(LMEM_FIXED, cbSid);
if (NULL == *ppUserSid)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
if (!CopySid(cbSid, *ppUserSid, ptgUser->User.Sid))
{
hr = myHLastError();
_JumpError(hr, error, "CopySid");
}
hr = S_OK;
error:
if (S_OK != hr)
{
if (NULL != *ppUserSid)
{
LocalFree(*ppUserSid);
*ppUserSid = NULL;
}
}
if (NULL != SlowBuffer)
{
LocalFree(SlowBuffer);
}
return(hr);
}
// This routine obtains a domain controller computer name associated with
// the account related to the hToken access token.
//
// hToken should be opened for TOKEN_QUERY access.
// pwszDomain should be of size (UNCLEN+1)
HRESULT
GetDomainControllers(
OPTIONAL IN WCHAR const *pwszDomain,
IN HANDLE hToken,
OUT DS_DOMAIN_CONTROLLER_INFO_1 **ppDCInfoOut,
OUT DWORD *pcDC)
{
HRESULT hr;
PSID pSidUser = NULL; // sid of client user.
WCHAR wszUserName[UNLEN + 1];
DWORD cwcUserName;
WCHAR wszDomainName[DNLEN + 1]; // domain we want a controller for.
DWORD cwcDomainName;
SID_NAME_USE snu;
DOMAIN_CONTROLLER_INFO *pDomainInfo = NULL;
DS_DOMAIN_CONTROLLER_INFO_1 *pDcInfo = NULL;
HANDLE hDS = INVALID_HANDLE_VALUE;
BOOL fSuccess = FALSE;
*ppDCInfoOut = NULL;
if (NULL == pwszDomain)
{
// first, get the user sid associated with the specified access token.
hr = GetTokenUserSid(hToken, &pSidUser);
_JumpIfError(hr, error, "GetTokenUserSid");
// next, lookup the domain name associated with the specified account.
cwcUserName = ARRAYSIZE(wszUserName);
cwcDomainName = ARRAYSIZE(wszDomainName);
if (!LookupAccountSid(
NULL,
pSidUser,
wszUserName,
&cwcUserName,
wszDomainName,
&cwcDomainName,
&snu))
{
hr = myHLastError();
_JumpError(hr, error, "LookupAccountSid");
}
}
else
{
wcscpy(wszDomainName, pwszDomain);
}
hr = DsGetDcName(
NULL,
wszDomainName,
NULL,
NULL,
DS_RETURN_DNS_NAME,
&pDomainInfo);
_JumpIfError(hr, error, "DsGetDcName");
// Get a handle to the DS on that machine
hr = DsBind(pDomainInfo->DomainControllerName, NULL, &hDS);
_JumpIfError(hr, error, "DsBind");
// Use the handle to enumerate all of the DCs
hr = DsGetDomainControllerInfo(
hDS,
pDomainInfo->DomainName,
1, // info level
pcDC,
(VOID **) ppDCInfoOut);
_JumpIfError(hr, error, "DsGetDomainControllerInfo");
error:
if (INVALID_HANDLE_VALUE != hDS)
{
DsUnBind(&hDS);
}
if (NULL != pDomainInfo)
{
NetApiBufferFree(pDomainInfo);
}
if (NULL != pSidUser)
{
LocalFree(pSidUser);
}
return(hr);
}
HRESULT
OpenRemoteEnterpriseRoot(
IN WCHAR const *pwszDC)
{
HRESULT hr;
HCERTSTORE hStoreRemote = NULL;
WCHAR wszStorePath[512];
DWORD cCert = 0;
CERT_CONTEXT const *pcc = NULL;
CERT_CONTEXT const *pccPrev;
swprintf(wszStorePath, L"\\\\%ws\\" wszROOT_CERTSTORE, pwszDC);
hStoreRemote = CertOpenStore(
CERT_STORE_PROV_SYSTEM_W,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
NULL,
CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE |
CERT_STORE_READONLY_FLAG,
(VOID *) wszStorePath);
if (NULL == hStoreRemote)
{
hr = myHLastError();
_JumpError2(hr, error, "CertOpenStore", E_ACCESSDENIED);
}
wprintf(
myLoadResourceString(IDS_FORMAT_DCROOTCERTS), // "** Enterprise Root Certificates for DC %ws"
pwszDC);
wprintf(wszNewLine);
// Dump issuer of enterprise roots.
pccPrev = NULL;
while (TRUE)
{
pcc = CertEnumCertificatesInStore(hStoreRemote, pccPrev);
if (NULL == pcc)
{
hr = myHLastError();
_PrintError2(hr, "CertEnumCertificatesInStore", CRYPT_E_NOT_FOUND);
break;
}
wprintf(myLoadResourceString(IDS_FORMAT_CERT_COLON), cCert);
wprintf(wszNewLine);
hr = cuDumpAsnBinaryQuiet(
pcc->pbCertEncoded,
pcc->cbCertEncoded,
MAXDWORD);
_PrintIfError(hr, "cuDumpAsnBinaryQuiet");
wprintf(wszNewLine);
cCert++;
pccPrev = pcc;
}
if (0 == cCert)
{
wprintf(myLoadResourceString(IDS_NO_KDC_ENT_STORE));
wprintf(wszNewLine);
hr = CRYPT_E_NOT_FOUND;
}
hr = S_OK;
error:
if (NULL != hStoreRemote)
{
CertCloseStore(hStoreRemote, 0);
}
return(hr);
}
HRESULT
verbDCInfo(
IN WCHAR const *pwszOption,
OPTIONAL IN WCHAR const *pwszFlags,
IN WCHAR const *pwszArg2,
IN WCHAR const *pwszArg3,
IN WCHAR const *pwszArg4)
{
HRESULT hr;
HRESULT hrSave;
HANDLE hToken = NULL;
DS_DOMAIN_CONTROLLER_INFO_1 *pDcInfo = NULL;
DWORD cDC = 0;
DWORD dwFlags;
DWORD i;
WCHAR *pwszDomain = NULL;
dwFlags = 0;
if (NULL != pwszFlags)
{
if (0 == LSTRCMPIS(pwszFlags, L"DeleteAll"))
{
dwFlags = DC_DELALL;
}
else
if (0 == LSTRCMPIS(pwszFlags, L"DeleteBad"))
{
dwFlags = DC_DELBAD | DC_VERIFY;
}
else
if (0 == LSTRCMPIS(pwszFlags, L"Verify"))
{
dwFlags = DC_VERIFY;
}
else
{
hr = E_INVALIDARG;
_JumpError(hr, error, "bad Flags");
}
}
// Grovel the process token for user identity. Used in determining
// target domain
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
{
hr = myHLastError();
_JumpError(hr, error, "OpenProcessToken");
}
// Use DS APIs to get all of the DCs in our domain
hr = GetDomainControllers(pwszDomain, hToken, &pDcInfo, &cDC);
_JumpIfError(hr, error, "GetDomainControllers");
for (i = 0; i < cDC; i++)
{
wprintf(L"%u: %ws\n", i, pDcInfo[i].NetbiosName);
}
hrSave = S_OK;
for (i = 0; i < cDC; i++)
{
WCHAR wszBuffer[512];
wprintf(wszNewLine);
wprintf(
myLoadResourceString(IDS_FORMAT_TESTINGDC), // "*** Testing DC[%u]: %ws"
i,
pDcInfo[i].NetbiosName);
wprintf(wszNewLine);
// Is DC available ?
wsprintf(wszBuffer, L"\\\\%ws\\netlogon", pDcInfo[i].NetbiosName);
if (MAXDWORD == GetFileAttributes(wszBuffer))
{
hr = myHLastError();
_PrintError2(hr, "GetFileAttributes", hr);
cuPrintError(IDS_DCUNAVAILABLE, hr);
if (S_OK == hrSave)
{
hrSave = hr;
}
continue;
}
// Open the enterprise root store, and make sure it's got the
// NTDEV ROOT CERTIFICATE (subject #defined above)
hr = OpenRemoteEnterpriseRoot(pDcInfo[i].NetbiosName);
if (S_OK != hr)
{
_PrintError2(hr, "OpenRemoteEnterpriseRoot", hr);
cuPrintError(IDS_REMOTEENTROOT, hr);
if (S_OK == hrSave)
{
hrSave = hr;
}
}
// Make sure the machine has a *valid* KDC certificate
hr = CheckForKDCCertificate(
pDcInfo[i].NetbiosName,
dwFlags);
if (S_OK != hr)
{
_PrintError2(hr, "CheckForKDCCertificate", hr);
cuPrintError(IDS_REMOTEKDCCERT, hr);
if (S_OK == hrSave)
{
hrSave = hr;
}
}
}
wprintf(wszNewLine);
hr = hrSave;
_JumpIfError2(hr, error, "verbDCInfo", hr);
error:
if (NULL != pDcInfo)
{
DsFreeDomainControllerInfo(1, cDC, pDcInfo);
}
return(hr);
}
BOOL
IsAutoenrolledCert(
IN CERT_CONTEXT const *pcc,
OPTIONAL IN WCHAR const *pwszzTemplates)
{
HRESULT hr;
BOOL fMatch = FALSE;
WCHAR *pwszTemplate = NULL;
WCHAR const *pwsz;
hr = cuGetCertType(pcc->pCertInfo, &pwszTemplate, NULL, NULL, NULL, NULL);
if (S_OK != hr)
{
_PrintError(hr, "cuGetCertType");
if (CRYPT_E_NOT_FOUND == hr)
{
hr = S_OK;
}
goto error;
}
pwsz = pwszzTemplates;
if (NULL != pwsz)
{
for ( ; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
{
if (0 == mylstrcmpiL(pwsz, pwszTemplate))
{
fMatch = TRUE;
break;
}
}
}
if (!fMatch)
{
DWORD i;
for (i = 0; i < ARRAYSIZE(s_apwszKDCTemplates); i++)
{
if (0 == mylstrcmpiS(pwszTemplate, s_apwszKDCTemplates[i]))
{
fMatch = TRUE;
}
}
}
error:
if (NULL != pwszTemplate)
{
LocalFree(pwszTemplate);
}
return(fMatch);
}
//
// Check for autoenrolled certificate
//
HRESULT
CheckForV1AutoenrolledCertificate(
IN WCHAR const *pwszDC,
OPTIONAL IN WCHAR const *pwszzTemplates)
{
HRESULT hr;
HCERTSTORE hStoreRemote = NULL;
WCHAR wszStorePath[512];
DWORD cCert;
DWORD cCertArchived;
DWORD dwArchiveBit;
CERT_CONTEXT const *pcc;
swprintf(wszStorePath, L"\\\\%ws\\" wszMY_CERTSTORE, pwszDC);
hStoreRemote = CertOpenStore(
CERT_STORE_PROV_SYSTEM_W,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
NULL,
CERT_STORE_READONLY_FLAG |
CERT_SYSTEM_STORE_LOCAL_MACHINE |
CERT_STORE_ENUM_ARCHIVED_FLAG,
(VOID *) wszStorePath);
if (NULL == hStoreRemote)
{
hr = myHLastError();
wprintf(myLoadResourceString(IDS_FORMAT_OPEN_REMOTE_MY_FAILED), hr);
wprintf(wszNewLine);
goto error;
}
cCert = 0;
cCertArchived = 0;
pcc = NULL;
while (TRUE)
{
pcc = CertEnumCertificatesInStore(hStoreRemote, pcc);
if (NULL == pcc)
{
break;
}
if (!IsAutoenrolledCert(pcc, pwszzTemplates) && 1 >= g_fForce)
{
continue;
}
// Cert passed test, dump issuer and subject
wprintf(myLoadResourceString(IDS_FORMAT_CERT_COLON), cCert);
wprintf(wszNewLine);
if (!CertGetCertificateContextProperty(
pcc,
CERT_ARCHIVED_PROP_ID,
NULL,
&dwArchiveBit))
{
hr = myHLastError();
if (hr != CRYPT_E_NOT_FOUND)
{
wprintf(myLoadResourceString(IDS_FORMAT_ERROR_GET_ARCHIVE_PROP), hr);
wprintf(wszNewLine);
}
}
else
{
wprintf(myLoadResourceString(IDS_LIST_ARCHIVED_CERT));
wprintf(wszNewLine);
cCertArchived++;
}
hr = cuDumpSerial(g_wszPad2, IDS_SERIAL, &pcc->pCertInfo->SerialNumber);
_PrintIfError(hr, "cuDumpSerial");
hr = cuDisplayCertNames(FALSE, g_wszPad2, pcc->pCertInfo);
_PrintIfError(hr, "cuDisplayCertNames");
hr = cuDumpCertType(g_wszPad2, pcc->pCertInfo);
_PrintIfError2(hr, "cuDumpCertType", CRYPT_E_NOT_FOUND);
hr = cuDisplayHash(
g_wszPad2,
pcc,
NULL,
CERT_SHA1_HASH_PROP_ID,
L"sha1");
_PrintIfError(hr, "cuDisplayHash");
wprintf(wszNewLine);
cCert++;
}
if (0 == cCert)
{
wprintf(myLoadResourceString(IDS_NO_AUTOENROLLED_CERT));
wprintf(wszNewLine);
hr = CRYPT_E_NOT_FOUND;
_JumpError(hr, error, "no AE certs");
}
wprintf(
myLoadResourceString(IDS_FORMAT_MACHINE_AND_ARCHIVED_CERTS),
cCert,
cCertArchived);
wprintf(L" ");
wprintf(myLoadResourceString(IDS_FORMAT_FOR_DC), pwszDC);
wprintf(wszNewLine);
hr = S_OK;
error:
if (NULL != hStoreRemote)
{
CertCloseStore(hStoreRemote, 0);
}
return(hr);
}
HRESULT
CheckForV1AutoenrollmentObject(
IN WCHAR const *pwszDC,
OUT WCHAR **ppwszzTemplates)
{
HRESULT hr;
HCERTSTORE hStoreRemote = NULL;
WCHAR wszStorePath[512];
DWORD cAE;
CTL_CONTEXT const *pCTL;
DWORD cwc;
WCHAR *pwsz;
*ppwszzTemplates = NULL;
swprintf(wszStorePath, L"\\\\%ws\\" wszACRS_CERTSTORE, pwszDC);
hStoreRemote = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
NULL,
CERT_SYSTEM_STORE_LOCAL_MACHINE |
CERT_STORE_READONLY_FLAG,
(VOID *) wszStorePath);
if (NULL == hStoreRemote)
{
hr = myHLastError();
wprintf(myLoadResourceString(IDS_FORMAT_OPEN_STORE_REMOTE_ENT_FAILED), hr);
wprintf(wszNewLine);
goto error;
}
cwc = 1;
cAE = 0;
pCTL = NULL;
while (TRUE)
{
pCTL = CertEnumCTLsInStore(hStoreRemote, pCTL);
if (NULL == pCTL)
{
break;
}
cwc += wcslen((WCHAR const *) pCTL->pCtlInfo->ListIdentifier.pbData) + 1;
cAE++;
}
if (0 == cAE)
{
wprintf(myLoadResourceString(IDS_NO_AUTOENROLL_OBJECT));
wprintf(wszNewLine);
}
else
{
pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
if (NULL == pwsz)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
*ppwszzTemplates = pwsz;
wprintf(myLoadResourceString(IDS_V1_AUTOENROLLMENT_OBJECTS_COLON));
while (TRUE)
{
pCTL = CertEnumCTLsInStore(hStoreRemote, pCTL);
if (NULL == pCTL)
{
break;
}
wprintf(L" %ws\n", pCTL->pCtlInfo->ListIdentifier.pbData);
wcscpy(pwsz, (WCHAR const *) pCTL->pCtlInfo->ListIdentifier.pbData);
pwsz += wcslen(pwsz) + 1;
cAE++;
}
*pwsz++ = L'\0';
CSASSERT(cwc == SAFE_SUBTRACT_POINTERS(pwsz, *ppwszzTemplates));
}
wprintf(wszNewLine);
hr = S_OK;
error:
if (NULL != hStoreRemote)
{
CertCloseStore(hStoreRemote, 0);
}
return(hr);
}
//
// This function takes a Marc Jacobs supplied text file (results from SSOLogon
// scripts) and runs through entmon for each machine in the list
//
HRESULT
verbEntInfo(
IN WCHAR const *pwszOption,
IN WCHAR const *pwszSamMachine,
IN WCHAR const *pwszArg2,
IN WCHAR const *pwszArg3,
IN WCHAR const *pwszArg4)
{
HRESULT hr;
HRESULT hrSave;
WCHAR *pwszDomain = NULL;
WCHAR *pwszMachine = NULL;
WCHAR *pwszMachineName = NULL;
WCHAR *pwszzTemplates = NULL;
hr = mySplitConfigString(pwszSamMachine, &pwszDomain, &pwszMachine);
_JumpIfError(hr, error, "mySplitConfigString");
if (NULL == pwszMachine || NULL == wcschr(pwszMachine, L'$'))
{
wprintf(myLoadResourceString(IDS_ERROR_CHECK_MACHINE_NAME));
wprintf(wszNewLine);
hr = E_INVALIDARG;
_JumpError(hr, error, "bad machine name");
}
// knock off trailing $
hr = myDupString(pwszMachine, &pwszMachineName);
_JumpIfError(hr, error, "myDupString");
pwszMachineName[wcslen(pwszMachineName)-1] = L'\0';
// assume for now that we're only interested in opening remote root store
wprintf(myLoadResourceString(IDS_FORMAT_MACHINE_LIST), pwszMachine);
wprintf(wszNewLine);
// Cert store functions, if first fails, bail.
hrSave = S_OK;
hr = OpenRemoteEnterpriseRoot(pwszMachineName);
if (S_OK != hr)
{
cuPrintError(IDS_REMOTEENTROOT, hr);
_PrintError2(hr, "OpenRemoteEnterpriseRoot", hr);
hrSave = hr;
}
else
{
hr = CheckForV1AutoenrollmentObject(pwszMachineName, &pwszzTemplates);
_PrintIfError(hr, "CheckForV1AutoenrollmentObject");
hrSave = hr;
hr = CheckForV1AutoenrolledCertificate(pwszMachineName, pwszzTemplates);
_PrintIfError(hr, "CheckForV1AutoenrolledCertificate");
if (S_OK == hrSave && CRYPT_E_NOT_FOUND != hr)
{
hrSave = hr;
}
}
hr = cuGetGroupMembership(pwszSamMachine);
_PrintIfError(hr, "cuGetGroupMembership");
hr = hrSave;
_JumpIfError2(hr, error, "RunEntmon", hr);
wprintf(wszNewLine);
error:
if (NULL != pwszzTemplates)
{
LocalFree(pwszzTemplates);
}
if (NULL != pwszDomain)
{
LocalFree(pwszDomain);
}
if (NULL != pwszMachine)
{
LocalFree(pwszMachine);
}
if (NULL != pwszMachineName)
{
LocalFree(pwszMachineName);
}
return(hr);
}