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.
360 lines
10 KiB
360 lines
10 KiB
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 2000
|
|
//
|
|
// File: ctnotify.cpp
|
|
//
|
|
// Contents: Cert Type Change Notification APIS
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
#include "pch.cpp"
|
|
|
|
#pragma hdrstop
|
|
|
|
#include <winldap.h>
|
|
#include <ntldap.h>
|
|
#include <cainfop.h>
|
|
#include <ctnotify.h>
|
|
#include <certca.h>
|
|
#include "csldap.h"
|
|
|
|
#define __dwFILE__ __dwFILE_CERTCLIB_CTNOTIFY_CPP__
|
|
|
|
|
|
static WCHAR * s_wszLocation = L"CN=Certificate Templates,CN=Public Key Services,CN=Services,";
|
|
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
// CertTypeQueryProc
|
|
//
|
|
// The thread to recieve change notification from DS
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
DWORD WINAPI CertTypeQueryProc(LPVOID lpParameter)
|
|
{
|
|
CERTTYPE_QUERY_INFO *pCertTypeQueryInfo=NULL;
|
|
ULONG ldaperr=0;
|
|
BOOL fFailed=FALSE;
|
|
|
|
LDAPMessage *results = NULL;
|
|
|
|
if(NULL==lpParameter)
|
|
return FALSE;
|
|
|
|
pCertTypeQueryInfo = (CERTTYPE_QUERY_INFO *)lpParameter;
|
|
|
|
//we wait for the notifications
|
|
while(TRUE)
|
|
{
|
|
ldaperr = ldap_result(
|
|
pCertTypeQueryInfo->pldap,
|
|
pCertTypeQueryInfo->msgID, // message identifier
|
|
LDAP_MSG_ONE, // retrieve one message at a time
|
|
NULL, // no timeout
|
|
&results); // receives the search results
|
|
|
|
fFailed=FALSE;
|
|
|
|
if ((ldaperr == (ULONG) -1) || (ldaperr == 0) || ((results) == NULL))
|
|
{
|
|
fFailed=TRUE;
|
|
}
|
|
else
|
|
{
|
|
if(LDAP_SUCCESS != ldap_result2error(pCertTypeQueryInfo->pldap, results, FALSE))
|
|
{
|
|
fFailed=TRUE;
|
|
}
|
|
}
|
|
|
|
if(TRUE == fFailed)
|
|
{
|
|
pCertTypeQueryInfo->hr = myHLdapError(pCertTypeQueryInfo->pldap, ldaperr, NULL);
|
|
|
|
if(!FAILED(pCertTypeQueryInfo->hr))
|
|
pCertTypeQueryInfo->hr=E_FAIL;
|
|
|
|
_PrintIfError(pCertTypeQueryInfo->hr, "CertTypeQueryProc");
|
|
|
|
if(results)
|
|
{
|
|
ldap_msgfree(results);
|
|
results=NULL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//some change has happened.
|
|
(pCertTypeQueryInfo->dwChangeSequence)++;
|
|
|
|
//make sure that we will never return 0
|
|
if(0 == (pCertTypeQueryInfo->dwChangeSequence))
|
|
{
|
|
(pCertTypeQueryInfo->dwChangeSequence)++;
|
|
}
|
|
|
|
ldap_msgfree(results);
|
|
results=NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// CACertTypeRegisterQuery
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
HRESULT
|
|
CACertTypeRegisterQuery(
|
|
IN DWORD, // dwFlag
|
|
IN LPVOID pvldap,
|
|
OUT HCERTTYPEQUERY *phCertTypeQuery)
|
|
{
|
|
HRESULT hr=E_INVALIDARG;
|
|
LDAPControl simpleControl;
|
|
PLDAPControl controlArray[2];
|
|
LPWSTR rgwszAttribs[2];
|
|
ULONG ldaperr=0;
|
|
DWORD dwThreadID=0;
|
|
LDAP *pldap=NULL;
|
|
|
|
CERTSTR bstrConfig = NULL;
|
|
CERTSTR bstrCertTemplatesContainer = NULL;
|
|
//memory is freed via the thread proc
|
|
CERTTYPE_QUERY_INFO *pCertTypeQueryInfo=NULL;
|
|
|
|
|
|
//assign the input parameter
|
|
pldap = (LDAP *)pvldap;
|
|
|
|
|
|
if(NULL==phCertTypeQuery)
|
|
_JumpError(hr, error, "NULL param");
|
|
|
|
pCertTypeQueryInfo=(CERTTYPE_QUERY_INFO *)LocalAlloc(LPTR, sizeof(CERTTYPE_QUERY_INFO));
|
|
|
|
if(NULL==pCertTypeQueryInfo)
|
|
{
|
|
hr=E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
memset(pCertTypeQueryInfo, 0, sizeof(CERTTYPE_QUERY_INFO));
|
|
|
|
//we start the change sequence as 1
|
|
pCertTypeQueryInfo->dwChangeSequence = 1;
|
|
pCertTypeQueryInfo->hr=S_OK;
|
|
|
|
//bind to DS
|
|
if(pldap)
|
|
{
|
|
pCertTypeQueryInfo->pldap=pldap;
|
|
}
|
|
else
|
|
{
|
|
// retrieve the ldap handle
|
|
hr = myDoesDSExist(TRUE);
|
|
_JumpIfError(hr, error, "myDoesDSExist");
|
|
|
|
hr = myRobustLdapBindEx(
|
|
0, // dwFlags1
|
|
RLBF_REQUIRE_SECURE_LDAP, // dwFlags2
|
|
0, // uVersion
|
|
NULL, // pwszDomainName
|
|
&pCertTypeQueryInfo->pldap,
|
|
NULL); // ppwszForestDNSName
|
|
_JumpIfError(hr , error, "myRobustLdapBindEx");
|
|
|
|
pCertTypeQueryInfo->fUnbind=TRUE;
|
|
}
|
|
|
|
// retrieve the config string
|
|
hr = CAGetAuthoritativeDomainDn(pCertTypeQueryInfo->pldap, NULL, &bstrConfig);
|
|
_JumpIfError(hr, error, "CAGetAuthoritativeDomainDn");
|
|
|
|
//build the template container DN
|
|
bstrCertTemplatesContainer = CertAllocStringLen(NULL, wcslen(bstrConfig) + wcslen(s_wszLocation));
|
|
if(bstrCertTemplatesContainer == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "CertAllocStringLen");
|
|
}
|
|
wcscpy(bstrCertTemplatesContainer, s_wszLocation);
|
|
wcscat(bstrCertTemplatesContainer, bstrConfig);
|
|
|
|
// Set up the change notification control.
|
|
simpleControl.ldctl_oid = LDAP_SERVER_NOTIFICATION_OID_W;
|
|
simpleControl.ldctl_iscritical = TRUE;
|
|
simpleControl.ldctl_value.bv_len = 0;
|
|
simpleControl.ldctl_value.bv_val = NULL;
|
|
controlArray[0] = &simpleControl;
|
|
controlArray[1] = NULL;
|
|
|
|
rgwszAttribs[0] = L"cn";
|
|
rgwszAttribs[1] = NULL;
|
|
|
|
|
|
// Start a persistent asynchronous search.
|
|
ldaperr = ldap_search_ext(
|
|
pCertTypeQueryInfo->pldap,
|
|
(PWCHAR) bstrCertTemplatesContainer, // Template container DN
|
|
LDAP_SCOPE_ONELEVEL,
|
|
L"ObjectClass=*",
|
|
rgwszAttribs, // Attributes to retrieve
|
|
1, // Retrieve attributes only
|
|
(PLDAPControl *) controlArray, // Server size controls
|
|
NULL, // Client controls
|
|
0, // Timeout
|
|
0, // Sizelimit
|
|
(PULONG)&(pCertTypeQueryInfo->msgID) // Receives identifier for results
|
|
);
|
|
|
|
if (LDAP_SUCCESS != ldaperr)
|
|
{
|
|
hr = myHLdapError(pCertTypeQueryInfo->pldap, ldaperr, NULL);
|
|
_JumpError(hr, error, "ldap_search_ext");
|
|
}
|
|
|
|
//start a thread to wait for the notification
|
|
pCertTypeQueryInfo->hThread = CreateThread(
|
|
NULL,
|
|
0,
|
|
CertTypeQueryProc,
|
|
pCertTypeQueryInfo,
|
|
0, //execute immediately
|
|
&dwThreadID);
|
|
|
|
if(NULL == pCertTypeQueryInfo->hThread)
|
|
{
|
|
hr=myHError(GetLastError());
|
|
_JumpError(hr, error, "CreateThread");
|
|
}
|
|
|
|
*phCertTypeQuery=pCertTypeQueryInfo;
|
|
|
|
pCertTypeQueryInfo=NULL;
|
|
|
|
hr=S_OK;
|
|
|
|
error:
|
|
|
|
if(bstrConfig)
|
|
CertFreeString(bstrConfig);
|
|
|
|
if(bstrCertTemplatesContainer)
|
|
{
|
|
CertFreeString(bstrCertTemplatesContainer);
|
|
}
|
|
|
|
if(pCertTypeQueryInfo)
|
|
{
|
|
if(pCertTypeQueryInfo->fUnbind)
|
|
{
|
|
if(pCertTypeQueryInfo->pldap)
|
|
ldap_unbind(pCertTypeQueryInfo->pldap);
|
|
}
|
|
|
|
if(pCertTypeQueryInfo->hThread)
|
|
CloseHandle(pCertTypeQueryInfo->hThread);
|
|
|
|
LocalFree(pCertTypeQueryInfo);
|
|
|
|
pCertTypeQueryInfo=NULL;
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// CACertTypeQuery
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
HRESULT
|
|
CACertTypeQuery(
|
|
IN HCERTTYPEQUERY hCertTypeQuery,
|
|
OUT DWORD *pdwChangeSequence)
|
|
{
|
|
CERTTYPE_QUERY_INFO *pCertTypeQueryInfo=NULL;
|
|
|
|
if((NULL==pdwChangeSequence) || (NULL==hCertTypeQuery))
|
|
return E_INVALIDARG;
|
|
|
|
pCertTypeQueryInfo = (CERTTYPE_QUERY_INFO *)hCertTypeQuery;
|
|
|
|
*pdwChangeSequence = pCertTypeQueryInfo->dwChangeSequence;
|
|
|
|
return (pCertTypeQueryInfo->hr);
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// CACertTypeUnregisterQuery
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
HRESULT
|
|
CACertTypeUnregisterQuery(
|
|
IN HCERTTYPEQUERY hCertTypeQuery)
|
|
{
|
|
CERTTYPE_QUERY_INFO *pCertTypeQueryInfo=NULL;
|
|
ULONG ldaperr=0;
|
|
HRESULT hr=E_INVALIDARG;
|
|
DWORD dwWait=0;
|
|
|
|
if(NULL==hCertTypeQuery)
|
|
_JumpError(hr, error, "NULL param");
|
|
|
|
pCertTypeQueryInfo = (CERTTYPE_QUERY_INFO *)hCertTypeQuery;
|
|
|
|
if(NULL == (pCertTypeQueryInfo->pldap))
|
|
_JumpError(hr, error, "NULL pldap");
|
|
|
|
//abandom the in-progress asynchronous ldap_result call
|
|
ldaperr=ldap_abandon(pCertTypeQueryInfo->pldap, pCertTypeQueryInfo->msgID);
|
|
|
|
if(LDAP_SUCCESS != ldaperr)
|
|
{
|
|
hr = myHLdapError(pCertTypeQueryInfo->pldap, ldaperr, NULL);
|
|
_JumpError(hr, error, "ldap_abandon");
|
|
}
|
|
|
|
//wait for the thread to finish
|
|
dwWait = WaitForSingleObject(pCertTypeQueryInfo->hThread, INFINITE);
|
|
|
|
if(WAIT_OBJECT_0 != dwWait)
|
|
{
|
|
hr = myHError(GetLastError());
|
|
_JumpError(hr, error, "WaitForSingleObject");
|
|
}
|
|
|
|
hr=S_OK;
|
|
|
|
error:
|
|
|
|
//free the memory
|
|
if(pCertTypeQueryInfo)
|
|
{
|
|
if(pCertTypeQueryInfo->fUnbind)
|
|
{
|
|
if(pCertTypeQueryInfo->pldap)
|
|
ldap_unbind(pCertTypeQueryInfo->pldap);
|
|
}
|
|
|
|
if(pCertTypeQueryInfo->hThread)
|
|
CloseHandle(pCertTypeQueryInfo->hThread);
|
|
|
|
LocalFree(pCertTypeQueryInfo);
|
|
|
|
pCertTypeQueryInfo=NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|