|
|
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: admin.cpp
//
// Contents: Implementation of DCOM object for RPC services
//
// History: July-97 xtan created
//
//---------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
#include <accctrl.h>
#include "csdisp.h"
#include "csprop.h"
#include "cscom.h"
#include "certlog.h"
#include "certsrvd.h"
#include "admin.h"
#include "resource.h"
#include "dbtable.h"
#include "elog.h"
#define __dwFILE__ __dwFILE_CERTSRV_ADMIN_CPP__
// Global variables
long g_cAdminComponents = 0; // Count of active components
long g_cAdminServerLocks = 0; // Count of locks
DWORD g_dwAdminRegister = 0; IClassFactory* g_pIAdminFactory = NULL;
extern HWND g_hwndMain;
#ifdef DBG_CERTSRV_DEBUG_PRINT
DWORD s_ssAdmin = DBG_SS_CERTSRVI; #endif
using namespace CertSrv;
// Admin component
// begin implementing cert admin services
HRESULT AdminGetIndexedCRL( /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [in] */ DWORD CertIndex, // -1: current CA cert
/* [in] */ DWORD Flags, // CA_CRL_*
/* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbCRL) { HRESULT hr; CRL_CONTEXT const *pCRL = NULL; CAuditEvent audit(0, g_dwAuditFilter); DWORD State = 0;
pctbCRL->pb = NULL; pctbCRL->cb = 0;
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
switch (Flags) { case CA_CRL_BASE: case CA_CRL_DELTA: break;
default: hr = E_INVALIDARG; _LeaveError(hr, "Flags"); }
// get the requested CRL:
hr = CRLGetCRL(CertIndex, CA_CRL_DELTA == Flags, &pCRL, NULL); _LeaveIfError(hr, "CRLGetCRL");
pctbCRL->cb = pCRL->cbCrlEncoded; pctbCRL->pb = (BYTE *) MIDL_user_allocate(pCRL->cbCrlEncoded); if (NULL == pctbCRL->pb) { hr = E_OUTOFMEMORY; _LeaveError(hr, "MIDL_user_allocate"); } CopyMemory(pctbCRL->pb, pCRL->pbCrlEncoded, pCRL->cbCrlEncoded);
myRegisterMemFree(pctbCRL->pb, CSM_MIDLUSERALLOC); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != pCRL) { CertFreeCRLContext(pCRL); } CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::GetCRL( /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbCRL) { HRESULT hr;
// Just get current base CRL:
hr = AdminGetIndexedCRL(pwszAuthority, MAXDWORD, CA_CRL_BASE, pctbCRL); _JumpIfError(hr, error, "AdminGetIndexedCRL");
error: CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::GetArchivedKey( /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [in] */ DWORD dwRequestId, /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbArchivedKey) { HRESULT hr; CAuditEvent audit(SE_AUDITID_CERTSRV_GETARCHIVEDKEY, g_dwAuditFilter); DWORD State = 0;
pctbArchivedKey->pb = NULL; pctbArchivedKey->cb = 0;
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { hr = audit.AddData(dwRequestId); // %1 request ID
_LeaveIfError(hr, "CAuditEvent::AddData");
hr = audit.AccessCheck( CA_ACCESS_OFFICER, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
hr = CheckOfficerRights(dwRequestId, audit); _LeaveIfError(hr, "CheckOfficerRights");
hr = PKCSGetArchivedKey( dwRequestId, &pctbArchivedKey->pb, &pctbArchivedKey->cb); _LeaveIfError(hr, "PKCSGetArchivedKey");
myRegisterMemFree(pctbArchivedKey->pb, CSM_COTASKALLOC);
hr = audit.CachedGenerateAudit(); _LeaveIfError(hr, "CAuditEvent::CachedGenerateAudit"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::GetCAProperty( IN wchar_t const *pwszAuthority, IN LONG PropId, // CR_PROP_*
IN LONG PropIndex, IN LONG PropType, // PROPTYPE_*
OUT CERTTRANSBLOB *pctbPropertyValue) { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::GetCAProperty(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { CAuditEvent audit(0, g_dwAuditFilter);
hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
hr = RequestGetCAProperty( PropId, PropIndex, PropType, pctbPropertyValue); _LeaveIfError(hr, "RequestGetCAProperty"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::SetCAProperty( IN wchar_t const *pwszAuthority, IN LONG PropId, // CR_PROP_*
IN LONG PropIndex, IN LONG PropType, // PROPTYPE_*
OUT CERTTRANSBLOB *pctbPropertyValue) { HRESULT hr;
DBGPRINT(( s_ssAdmin, "CCertAdminD::SetCAProperty(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = RequestSetCAProperty( pwszAuthority, PropId, PropIndex, PropType, pctbPropertyValue); _JumpIfError(hr, error, "RequestSetCAProperty");
error: return(hr); }
STDMETHODIMP CCertAdminD::GetCAPropertyInfo( IN wchar_t const *pwszAuthority, OUT LONG *pcProperty, OUT CERTTRANSBLOB *pctbPropInfo) { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::GetCAPropertyInfo(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { CAuditEvent audit(0, g_dwAuditFilter);
hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
hr = RequestGetCAPropertyInfo( pcProperty, pctbPropInfo); _LeaveIfError(hr, "RequestGetCAPropertyInfo"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::PublishCRL( /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [in] */ FILETIME NextUpdate) { HRESULT hr;
// CA_CRL_BASE implies CA_CRL_DELTA when delta CRLs are enabled.
hr = PublishCRLs(pwszAuthority, NextUpdate, CA_CRL_BASE); _JumpError(hr, error, "PublishCRLs");
error: CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::PublishCRLs( /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [in] */ FILETIME NextUpdate, /* [in] */ DWORD Flags) // CA_CRL_*
{ HRESULT hr; BOOL fRetry = FALSE; BOOL fForceRepublishCRL; BOOL fShadowDelta = FALSE; WCHAR *pwszUserName = NULL; CAuditEvent audit(SE_AUDITID_CERTSRV_PUBLISHCRL, g_dwAuditFilter); DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::PublishCRL(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { HRESULT hrPublish;
hr = audit.AddData(NextUpdate); // %1 next update
_LeaveIfError(hr, "AddData");
hr = audit.AddData( (CA_CRL_BASE & Flags)? true : false); // %2 publish base
_LeaveIfError(hr, "AddData");
hr = audit.AddData( (CA_CRL_DELTA & Flags)? true : false); // %3 publish delta
_LeaveIfError(hr, "AddData");
hr = audit.AccessCheck( CA_ACCESS_ADMIN, audit.m_gcAuditSuccessOrFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
switch (~CA_CRL_REPUBLISH & Flags) { case CA_CRL_BASE: break;
case CA_CRL_DELTA: if (g_fDeltaCRLPublishDisabled) { fShadowDelta = TRUE; } break;
case CA_CRL_BASE | CA_CRL_DELTA: if (g_fDeltaCRLPublishDisabled) { hr = E_INVALIDARG; _LeaveError(hr, "Delta CRLs disabled"); } break;
default: hr = E_INVALIDARG; _LeaveError(hr, "Flags"); }
fForceRepublishCRL = (CA_CRL_REPUBLISH & Flags)? TRUE : FALSE;
hr = GetClientUserName(NULL, &pwszUserName, NULL); _LeaveIfError(hr, "GetClientUserName");
hr = CRLPublishCRLs( !fForceRepublishCRL, // fRebuildCRL
fForceRepublishCRL, // fForceRepublish
pwszUserName, CA_CRL_DELTA == (~CA_CRL_REPUBLISH & Flags), // fDeltaOnly
fShadowDelta, NextUpdate, &fRetry, &hrPublish); _LeaveIfError(hr, "CRLPublishCRLs");
hr = hrPublish; _LeaveIfError(hr, "CRLPublishCRLs(hrPublish)"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != pwszUserName) { LocalFree(pwszUserName); } CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::SetExtension( /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [in] */ DWORD dwRequestId, /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszExtensionName, /* [in] */ DWORD dwType, /* [in] */ DWORD dwFlags, /* [ref][in] */ CERTTRANSBLOB __RPC_FAR *pctbValue) { HRESULT hr; ICertDBRow *prow = NULL; CAuditEvent audit(SE_AUDITID_CERTSRV_SETEXTENSION, g_dwAuditFilter); DWORD State = 0; BOOL fCommitted = FALSE;
DBGPRINT(( s_ssAdmin, "CCertAdminD::SetExtension(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { hr = audit.AddData(dwRequestId); // %1 Request ID
_LeaveIfError(hr, "AddData");
hr = audit.AddData(pwszExtensionName); // %2 name
_LeaveIfError(hr, "AddData");
hr = audit.AddData(dwType); // %3 type
_LeaveIfError(hr, "AddData");
hr = audit.AddData(dwFlags); // %4 flags
_LeaveIfError(hr, "AddData");
hr = audit.AddData(pctbValue->pb, pctbValue->cb); // %5 data
_LeaveIfError(hr, "AddData");
hr = audit.AccessCheck( CA_ACCESS_OFFICER, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
hr = CheckOfficerRights(dwRequestId, audit); _LeaveIfError(hr, "CheckOfficerRights");
hr = g_pCertDB->OpenRow(PROPTABLE_REQCERT, dwRequestId, NULL, &prow); _LeaveIfError(hr, "OpenRow");
hr = CoreValidateRequestId(prow, DB_DISP_PENDING); if (S_OK != hr) { hr = myHError(hr); _LeaveError(hr, "CoreValidateRequestId"); }
hr = PropSetExtension( prow, PROPCALLER_ADMIN | (PROPTYPE_MASK & dwType), pwszExtensionName, EXTENSION_ORIGIN_ADMIN | (EXTENSION_POLICY_MASK & dwFlags), pctbValue->cb, pctbValue->pb); _LeaveIfError(hr, "PropSetExtension");
hr = prow->CommitTransaction(TRUE); _LeaveIfError(hr, "CommitTransaction");
fCommitted = TRUE;
hr = audit.CachedGenerateAudit(); _LeaveIfError(hr, "CAuditEvent::CachedGenerateAudit");
} __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != prow) { if (S_OK != hr && !fCommitted) { HRESULT hr2 = prow->CommitTransaction(FALSE); _PrintIfError(hr2, "CommitTransaction"); } prow->Release(); } CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::SetAttributes( /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [in] */ DWORD dwRequestId, /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAttributes) { HRESULT hr; ICertDBRow *prow = NULL; CAuditEvent audit(SE_AUDITID_CERTSRV_SETATTRIBUTES, g_dwAuditFilter); DWORD State = 0; BOOL fCommitted = FALSE;
DBGPRINT(( s_ssAdmin, "CCertAdminD::SetAttributes(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { hr = audit.AddData(dwRequestId); // %1 request ID
_LeaveIfError(hr, "AddData");
hr = audit.AddData(pwszAttributes); // %2 attributes
_LeaveIfError(hr, "AddData"); hr = audit.AccessCheck( CA_ACCESS_OFFICER, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
hr = CheckOfficerRights(dwRequestId, audit); _LeaveIfError(hr, "CheckOfficerRights");
hr = g_pCertDB->OpenRow(PROPTABLE_REQCERT, dwRequestId, NULL, &prow); _LeaveIfError(hr, "OpenRow");
hr = CoreValidateRequestId(prow, DB_DISP_PENDING); if (S_OK != hr) { hr = myHError(hr); _LeaveError(hr, "CoreValidateRequestId"); }
if (NULL == pwszAttributes) { hr = E_INVALIDARG; _LeaveError(hr, "pwszAttributes NULL"); } hr = PKCSParseAttributes( prow, pwszAttributes, FALSE, PROPTABLE_CERTIFICATE, NULL); if (S_OK != hr) { hr = myHError(hr); _LeaveError(hr, "PKCSParseAttributes"); } hr = prow->CommitTransaction(TRUE); _LeaveIfError(hr, "CommitTransaction");
fCommitted = TRUE;
hr = audit.CachedGenerateAudit(); _LeaveIfError(hr, "CAuditEvent::CachedGenerateAudit"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != prow) { if (S_OK != hr && !fCommitted) { HRESULT hr2 = prow->CommitTransaction(FALSE); _PrintIfError(hr2, "CommitTransaction"); } prow->Release(); } CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::DenyRequest( /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [in] */ DWORD dwRequestId) { HRESULT hr; DWORD Disposition; WCHAR *pwszUserName = NULL; CERTSRV_COM_CONTEXT ComContext; DWORD dwComContextIndex = MAXDWORD; CERTSRV_RESULT_CONTEXT Result; CAuditEvent audit(SE_AUDITID_CERTSRV_DENYREQUEST, g_dwAuditFilter); DWORD State = 0;
ZeroMemory(&ComContext, sizeof(ComContext));
DBGPRINT(( s_ssAdmin, "CCertAdminD::DenyRequest(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No Authority Name");
hr = RegisterComContext(&ComContext, &dwComContextIndex); _JumpIfError(hr, error, "RegisterComContext");
ZeroMemory(&Result, sizeof(Result)); Result.pdwRequestId = &dwRequestId; Result.pdwDisposition = &Disposition;
__try { hr = audit.AddData(dwRequestId); // %1 request ID
_LeaveIfError(hr, "AddData"); hr = audit.AccessCheck( CA_ACCESS_OFFICER, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
hr = CheckOfficerRights(dwRequestId, audit); _LeaveIfError(hr, "CheckOfficerRights");
hr = GetClientUserName(NULL, &pwszUserName, NULL); _LeaveIfError(hr, "GetClientUserName");
hr = CoreProcessRequest( CR_IN_DENY, // dwFlags
pwszUserName, 0, // cbRequest
NULL, // pbRequest
NULL, // pwszAttributes
NULL, // pwszSerialNumber
dwComContextIndex, dwRequestId, &Result); if (S_OK != hr) { hr = myHError(hr); _LeaveError(hr, "CoreProcessRequest"); } if (FAILED(Disposition)) { hr = (HRESULT) Disposition; _LeaveError(hr, "CoreProcessRequest(Disposition)"); } hr = audit.CachedGenerateAudit(); _LeaveIfError(hr, "CAuditEvent::CachedGenerateAudit"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != pwszUserName) { LocalFree(pwszUserName); } if (MAXDWORD != dwComContextIndex) { UnregisterComContext(&ComContext, dwComContextIndex); } CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::ResubmitRequest( /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [in] */ DWORD dwRequestId, /* [out] */ DWORD __RPC_FAR *pdwDisposition) { HRESULT hr; WCHAR *pwszUserName = NULL; CERTSRV_COM_CONTEXT ComContext; DWORD dwComContextIndex = MAXDWORD; CERTSRV_RESULT_CONTEXT Result; CAuditEvent audit(SE_AUDITID_CERTSRV_RESUBMITREQUEST, g_dwAuditFilter); DWORD State = 0;
ZeroMemory(&ComContext, sizeof(ComContext));
DBGPRINT(( s_ssAdmin, "CCertAdminD::ResubmitRequest(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
hr = RegisterComContext(&ComContext, &dwComContextIndex); _JumpIfError(hr, error, "RegisterComContext");
__try { hr = audit.AddData(dwRequestId); // %1 request ID
_LeaveIfError(hr, "AddData"); hr = audit.AccessCheck( CA_ACCESS_OFFICER, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
hr = CheckOfficerRights(dwRequestId, audit); _LeaveIfError(hr, "CheckOfficerRights");
hr = GetClientUserName(NULL, &pwszUserName, NULL); _LeaveIfError(hr, "GetClientUserName");
ComContext.fInRequestGroup = MAXDWORD; // mark value invalid
ZeroMemory(&Result, sizeof(Result)); Result.pdwRequestId = &dwRequestId; Result.pdwDisposition = pdwDisposition; hr = CoreProcessRequest( CR_IN_RESUBMIT, // dwFlags
pwszUserName, // pwszUserName
0, // cbRequest
NULL, // pbRequest
NULL, // pwszAttributes
NULL, // pwszSerialNumber
dwComContextIndex, dwRequestId, &Result);
if (S_OK != hr) { hr = myHError(hr); _LeaveError(hr, "CoreProcessRequest"); }
hr = audit.CachedGenerateAudit(); _LeaveIfError(hr, "CAuditEvent::CachedGenerateAudit");
} __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != pwszUserName) { LocalFree(pwszUserName); } if (NULL != ComContext.hAccessToken) { __try { CloseHandle(ComContext.hAccessToken); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); } } if (MAXDWORD != dwComContextIndex) { UnregisterComContext(&ComContext, dwComContextIndex); } CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::EnumViewColumn( /* [ref][in] */ wchar_t const *pwszAuthority, /* [in] */ DWORD iColumn, /* [in] */ DWORD cColumn, /* [out] */ DWORD *pcColumn, /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbColumnInfo) // CoTaskMem*
{ HRESULT hr;
hr = EnumViewColumnTable( pwszAuthority, CVRC_TABLE_REQCERT, iColumn, cColumn, pcColumn, pctbColumnInfo); // CoTaskMem*
_JumpIfError(hr, error, "EnumViewColumnTable");
error: CSASSERT(S_OK == hr || S_FALSE == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::EnumViewColumnTable( /* [ref][in] */ wchar_t const *pwszAuthority, /* [in] */ DWORD iTable, /* [in] */ DWORD iColumn, /* [in] */ DWORD cColumn, /* [out] */ DWORD *pcColumn, /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbColumnInfo) // CoTaskMem*
{ HRESULT hr; LONG iColumnCurrent; CERTDBCOLUMN *rgColumn = NULL; CERTDBCOLUMN *pColumn; CERTDBCOLUMN *pColumnEnd; CERTTRANSDBCOLUMN *rgtColumnOut = NULL; CERTTRANSDBCOLUMN *ptColumn; DWORD cColumnFetched; DWORD cb; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::EnumViewColumnTable(tid=%d, this=%x, icol=%d, ccol=%d)\n", GetCurrentThreadId(), this, iColumn, cColumn));
pctbColumnInfo->cb = 0; pctbColumnInfo->pb = NULL;
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { if (NULL == m_pEnumCol || iTable != m_iTableEnum) { if (NULL != m_pEnumCol) { m_pEnumCol->Release(); m_pEnumCol = NULL; } hr = g_pCertDB->EnumCertDBColumn(iTable, &m_pEnumCol); _LeaveIfError(hr, "EnumCertDBColumn");
m_iTableEnum = iTable; }
rgColumn = (CERTDBCOLUMN *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, cColumn * sizeof(rgColumn[0])); if (NULL == rgColumn) { hr = E_OUTOFMEMORY; _LeaveError(hr, "Alloc rgColumn"); }
hr = m_pEnumCol->Skip(0, &iColumnCurrent); _LeaveIfError(hr, "Skip");
if (iColumnCurrent != (LONG) iColumn) { hr = m_pEnumCol->Skip( (LONG) iColumn - iColumnCurrent, &iColumnCurrent); _LeaveIfError(hr, "Skip");
CSASSERT((LONG) iColumn == iColumnCurrent); }
hr = m_pEnumCol->Next(cColumn, rgColumn, &cColumnFetched); if (S_FALSE != hr) { _LeaveIfError(hr, "Next"); }
DBGPRINT(( DBG_SS_CERTSRVI, "EnumViewColumnTable: cColumnFetched=%d\n", cColumnFetched));
cb = cColumnFetched * sizeof(rgtColumnOut[0]); pColumnEnd = &rgColumn[cColumnFetched]; for (pColumn = rgColumn; pColumn < pColumnEnd; pColumn++) { cb += DWORDROUND((wcslen(pColumn->pwszName) + 1) * sizeof(WCHAR)); cb += DWORDROUND((wcslen(pColumn->pwszDisplayName) + 1) * sizeof(WCHAR)); }
rgtColumnOut = (CERTTRANSDBCOLUMN *) MIDL_user_allocate(cb); if (NULL == rgtColumnOut) { hr = E_OUTOFMEMORY; _LeaveError(hr, "MIDL_user_allocate rgtColumnOut"); } ZeroMemory(rgtColumnOut, cb); pctbColumnInfo->cb = cb;
cb = cColumnFetched * sizeof(rgtColumnOut[0]); pColumnEnd = &rgColumn[cColumnFetched]; ptColumn = rgtColumnOut; for (pColumn = rgColumn; pColumn < pColumnEnd; ptColumn++, pColumn++) { DWORD cbT;
ptColumn->Type = pColumn->Type; ptColumn->Index = pColumn->Index; ptColumn->cbMax = pColumn->cbMax; DBGPRINT(( DBG_SS_CERTSRVI, "EnumViewColumnTable: ielt=%d idx=%x \"%ws\"\n", iColumn + (ptColumn - rgtColumnOut), ptColumn->Index, pColumn->pwszName));
cbT = (wcslen(pColumn->pwszName) + 1) * sizeof(WCHAR); CopyMemory(Add2Ptr(rgtColumnOut, cb), pColumn->pwszName, cbT); ptColumn->obwszName = cb; cb += DWORDROUND(cbT);
cbT = (wcslen(pColumn->pwszDisplayName) + 1) * sizeof(WCHAR); CopyMemory(Add2Ptr(rgtColumnOut, cb), pColumn->pwszDisplayName, cbT); ptColumn->obwszDisplayName = cb; cb += DWORDROUND(cbT); } CSASSERT(cb == pctbColumnInfo->cb);
pctbColumnInfo->pb = (BYTE *) rgtColumnOut; rgtColumnOut = NULL; *pcColumn = cColumnFetched;
myRegisterMemFree(pctbColumnInfo->pb, CSM_MIDLUSERALLOC); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != rgColumn) { pColumnEnd = &rgColumn[cColumn]; for (pColumn = rgColumn; pColumn < pColumnEnd; pColumn++) { if (NULL != pColumn->pwszName) { CoTaskMemFree(pColumn->pwszName); } if (NULL != pColumn->pwszDisplayName) { CoTaskMemFree(pColumn->pwszDisplayName); } } LocalFree(rgColumn); } if (NULL != rgtColumnOut) { MIDL_user_free(rgtColumnOut); } DBGPRINT(( DBG_SS_CERTSRVI, "EnumViewColumnTable: icol=%d, ccol=%d, ccolout=%d, hr=%x\n", iColumn, cColumn, *pcColumn, hr));
CertSrvExitServer(State); CSASSERT(S_OK == hr || S_FALSE == hr || FAILED(hr)); return(hr); }
HRESULT CCertAdminD::GetViewDefaultColumnSet( IN wchar_t const *pwszAuthority, IN DWORD iColumnSetDefault, OUT DWORD *pcColumn, OUT CERTTRANSBLOB *ptbColumnInfo) // CoTaskMem*
{ HRESULT hr; DWORD ccol; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::GetViewDefaultColumnSet(tid=%d, this=%x, icolset=%d)\n", GetCurrentThreadId(), this, iColumnSetDefault));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { { CAuditEvent audit(0, g_dwAuditFilter);
hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck"); }
hr = g_pCertDB->GetDefaultColumnSet(iColumnSetDefault, 0, &ccol, NULL); _LeaveIfError(hr, "GetDefaultColumnSet");
ptbColumnInfo->cb = ccol * sizeof(DWORD); ptbColumnInfo->pb = (BYTE *) MIDL_user_allocate(ptbColumnInfo->cb); if (NULL == ptbColumnInfo->pb) { hr = E_OUTOFMEMORY; _LeaveError(hr, "MIDL_user_allocate"); } myRegisterMemFree(ptbColumnInfo->pb, CSM_MIDLUSERALLOC);
hr = g_pCertDB->GetDefaultColumnSet( iColumnSetDefault, ccol, pcColumn, (DWORD *) ptbColumnInfo->pb); _LeaveIfError(hr, "GetDefaultColumnSet"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: DBGPRINT(( S_OK == hr? DBG_SS_CERTSRVI : DBG_SS_CERTSRV, "GetViewDefaultColumnSet: icolset=%d, ccolout=%d, hr=%x\n", iColumnSetDefault, *pcColumn, hr)); CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
HRESULT CCertAdminD::_EnumAttributes( IN ICertDBRow *prow, IN CERTDBNAME *adbn, IN DWORD celt, OUT CERTTRANSBLOB *pctbOut) // CoTaskMem*
{ HRESULT hr; DWORD i; DWORD cb; DWORD cbT; CERTTRANSDBATTRIBUTE *pteltOut; BYTE *pbOut; BYTE *pbOutEnd; DWORD State = 0;
CSASSERT(NULL == pctbOut->pb);
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
cb = sizeof(*pteltOut) * celt; for (i = 0; i < celt; i++) { cb += (wcslen(adbn[i].pwszName) + 1) * sizeof(WCHAR); cb = DWORDROUND(cb);
cbT = 0; hr = prow->GetProperty( adbn[i].pwszName, PROPTYPE_STRING | PROPCALLER_ADMIN | PROPTABLE_ATTRIBUTE, &cbT, NULL); _JumpIfError(hr, error, "GetProperty(NULL)");
cb += DWORDROUND(cbT); }
pctbOut->pb = (BYTE *) MIDL_user_allocate(cb); if (NULL == pctbOut->pb) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "MIDL_user_allocate out data"); } pctbOut->cb = cb;
pteltOut = (CERTTRANSDBATTRIBUTE *) pctbOut->pb; pbOut = (BYTE *) &pteltOut[celt]; pbOutEnd = &pctbOut->pb[pctbOut->cb];
for (i = 0; i < celt; i++) { cbT = (wcslen(adbn[i].pwszName) + 1) * sizeof(WCHAR); CopyMemory(pbOut, adbn[i].pwszName, cbT); pteltOut->obwszName = SAFE_SUBTRACT_POINTERS(pbOut, pctbOut->pb); pbOut += DWORDROUND(cbT);
cbT = SAFE_SUBTRACT_POINTERS(pbOutEnd, pbOut); hr = prow->GetProperty( adbn[i].pwszName, PROPTYPE_STRING | PROPCALLER_ADMIN | PROPTABLE_ATTRIBUTE, &cbT, pbOut); _JumpIfError(hr, error, "GetProperty(pbOut)");
CSASSERT(wcslen((WCHAR const *) pbOut) * sizeof(WCHAR) == cbT); pteltOut->obwszValue = SAFE_SUBTRACT_POINTERS(pbOut, pctbOut->pb); pbOut += DWORDROUND(cbT + sizeof(WCHAR)); pteltOut++; } CSASSERT(pbOut == pbOutEnd); hr = S_OK;
error: if (S_OK != hr && NULL != pctbOut->pb) { MIDL_user_free(pctbOut->pb); pctbOut->pb = NULL; } CertSrvExitServer(State); return(hr); }
HRESULT CCertAdminD::_EnumExtensions( IN ICertDBRow *prow, IN CERTDBNAME *adbn, IN DWORD celt, OUT CERTTRANSBLOB *pctbOut) // CoTaskMem*
{ HRESULT hr; DWORD i; DWORD cb; DWORD cbT; DWORD ExtFlags; CERTTRANSDBEXTENSION *pteltOut; BYTE *pbOut; BYTE *pbOutEnd; DWORD State = 0;
CSASSERT(NULL == pctbOut->pb);
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
cb = sizeof(*pteltOut) * celt; for (i = 0; i < celt; i++) { cb += (wcslen(adbn[i].pwszName) + 1) * sizeof(WCHAR); cb = DWORDROUND(cb);
cbT = 0; hr = prow->GetExtension( adbn[i].pwszName, &ExtFlags, &cbT, NULL); _JumpIfError(hr, error, "GetExtension(NULL)");
cb += DWORDROUND(cbT); }
pctbOut->pb = (BYTE *) MIDL_user_allocate(cb); if (NULL == pctbOut->pb) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "MIDL_user_allocate out data"); } pctbOut->cb = cb;
pteltOut = (CERTTRANSDBEXTENSION *) pctbOut->pb; pbOut = (BYTE *) &pteltOut[celt]; pbOutEnd = &pctbOut->pb[pctbOut->cb];
for (i = 0; i < celt; i++) { cbT = (wcslen(adbn[i].pwszName) + 1) * sizeof(WCHAR); CopyMemory(pbOut, adbn[i].pwszName, cbT); pteltOut->obwszName = SAFE_SUBTRACT_POINTERS(pbOut, pctbOut->pb); pbOut += DWORDROUND(cbT);
cbT = SAFE_SUBTRACT_POINTERS(pbOutEnd, pbOut); hr = prow->GetExtension( adbn[i].pwszName, (DWORD *) &pteltOut->ExtFlags, &cbT, pbOut); _JumpIfError(hr, error, "GetExtension(pbOut)");
pteltOut->cbValue = cbT; pteltOut->obValue = SAFE_SUBTRACT_POINTERS(pbOut, pctbOut->pb); pbOut += DWORDROUND(cbT); pteltOut++; } CSASSERT(pbOut == pbOutEnd); hr = S_OK;
error: if (S_OK != hr && NULL != pctbOut->pb) { MIDL_user_free(pctbOut->pb); pctbOut->pb = NULL; } CertSrvExitServer(State); return(hr); }
STDMETHODIMP CCertAdminD::EnumAttributesOrExtensions( IN wchar_t const *pwszAuthority, IN DWORD RowId, IN DWORD Flags, OPTIONAL IN wchar_t const *pwszLast, IN DWORD celt, OUT DWORD *pceltFetched, OUT CERTTRANSBLOB *pctbOut) // CoTaskMem*
{ HRESULT hr; ICertDBRow *prow = NULL; IEnumCERTDBNAME *penum = NULL; DWORD EnumFlags; CERTDBNAME *adbn = NULL; DWORD celtFetched; DWORD i; DWORD j; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::EnumAttributesOrExtensions(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
DBGPRINT(( DBG_SS_CERTSRVI, "EnumAttributesOrExtensions(row=%d, flags=0x%x, last=%ws, celt=%d)\n", RowId, Flags, pwszLast, celt)); __try { pctbOut->pb = NULL; { CAuditEvent audit(0, g_dwAuditFilter);
hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck"); }
if (0 >= RowId) { hr = E_INVALIDARG; _LeaveError(hr, "RowId"); } switch (Flags) { case CDBENUM_ATTRIBUTES: EnumFlags = CIE_TABLE_ATTRIBUTES; break;
case CDBENUM_EXTENSIONS: EnumFlags = CIE_TABLE_EXTENSIONS; break;
default: hr = E_INVALIDARG; _LeaveError(hr, "Flags"); }
hr = g_pCertDB->OpenRow( PROPOPEN_READONLY | PROPTABLE_REQCERT, RowId, NULL, &prow); _LeaveIfError(hr, "OpenRow(RowId)");
hr = prow->EnumCertDBName(EnumFlags, &penum); _LeaveIfError(hr, "EnumCertDBName");
adbn = (CERTDBNAME *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, sizeof(adbn[0]) * celt); if (NULL == adbn) { hr = E_OUTOFMEMORY; _LeaveError(hr, "Alloc string pointers"); }
// If specified, skip entries up to and including the last key.
if (NULL != pwszLast) { int r;
do { hr = penum->Next(1, &adbn[0], &celtFetched); if (S_FALSE == hr) { hr = E_INVALIDARG; _PrintError(hr, "pwszLast missing"); } _LeaveIfError(hr, "Next");
r = lstrcmpi(pwszLast, adbn[0].pwszName); LocalFree(adbn[0].pwszName); adbn[0].pwszName = NULL; } while (0 != r); }
hr = penum->Next(celt, adbn, &celtFetched); if (S_FALSE != hr) { _LeaveIfError(hr, "Next"); }
if (CIE_TABLE_ATTRIBUTES == EnumFlags) { hr = _EnumAttributes(prow, adbn, celtFetched, pctbOut); _LeaveIfError(hr, "_EnumAttributes"); } else { hr = _EnumExtensions(prow, adbn, celtFetched, pctbOut); _LeaveIfError(hr, "_EnumExtensions"); }
myRegisterMemFree(pctbOut->pb, CSM_MIDLUSERALLOC);
*pceltFetched = celtFetched; hr = S_OK; if (celt > celtFetched) { hr = S_FALSE; } } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != adbn) { for (i = 0; i < celt; i++) { if (NULL != adbn[i].pwszName) { MIDL_user_free(adbn[i].pwszName); } } LocalFree(adbn); } if (NULL != penum) { penum->Release(); } if (NULL != prow) { prow->Release(); } DBGPRINT(( DBG_SS_CERTSRVI, "EnumAttributesOrExtensions: celtFetched=%d, hr=%x\n", *pceltFetched, hr)); CertSrvExitServer(State); CSASSERT(S_OK == hr || S_FALSE == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::OpenView( IN wchar_t const *pwszAuthority, IN DWORD ccvr, IN CERTVIEWRESTRICTION const *acvr, IN DWORD ccolOut, IN DWORD const *acolOut, IN DWORD ielt, IN DWORD celt, OUT DWORD *pceltFetched, OUT CERTTRANSBLOB *pctbResultRows) // CoTaskMem*
{ HRESULT hr; IEnumCERTDBRESULTROW *pview = NULL; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::OpenView(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
DBGPRINT(( DBG_SS_CERTSRVI, "================================================================\n")); DBGPRINT(( DBG_SS_CERTSRVI, "OpenView(ccvr=%d, ccolOut=%d, celt=%d)\n", ccvr, ccolOut, celt));
__try { pctbResultRows->pb = NULL; { CAuditEvent audit(0, g_dwAuditFilter);
hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck"); }
if (NULL != m_pView) { hr = E_UNEXPECTED; _LeaveError(hr, "Has View"); }
hr = g_pCertDB->OpenView( ccvr, acvr, ccolOut, acolOut, CDBOPENVIEW_WORKERTHREAD, &pview); _LeaveIfError(hr, "OpenView");
hr = _EnumViewNext(pview, ielt, celt, pceltFetched, pctbResultRows); if (S_FALSE != hr) { _LeaveIfError(hr, "_EnumViewNext"); }
m_pView = pview; pview = NULL; myRegisterMemFree(pctbResultRows->pb, CSM_MIDLUSERALLOC); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != pview) { pview->Release(); } DBGPRINT(( DBG_SS_CERTSRVI, "OpenView: celtFetched=%d, hr=%x\n", *pceltFetched, hr)); CertSrvExitServer(State); CSASSERT(S_OK == hr || S_FALSE == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::EnumView( IN wchar_t const *pwszAuthority, IN DWORD ielt, IN DWORD celt, OUT DWORD *pceltFetched, OUT CERTTRANSBLOB *pctbResultRows) // CoTaskMem*
{ HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::EnumView(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
DBGPRINT((DBG_SS_CERTSRVI, "EnumView(ielt=%d, celt=%d)\n", ielt, celt));
__try { if (NULL == m_pView) { hr = E_UNEXPECTED; _LeaveError(hr, "No View"); }
hr = _EnumViewNext( m_pView, ielt, celt, pceltFetched, pctbResultRows); if (S_FALSE != hr) { _LeaveIfError(hr, "_EnumViewNext"); } myRegisterMemFree(pctbResultRows->pb, CSM_MIDLUSERALLOC); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: DBGPRINT(( DBG_SS_CERTSRVI, "EnumView: celtFetched=%d, hr=%x\n", *pceltFetched, hr)); CertSrvExitServer(State); CSASSERT(S_OK == hr || S_FALSE == hr || FAILED(hr)); return(hr); }
HRESULT CCertAdminD::_EnumViewNext( IN IEnumCERTDBRESULTROW *pview, IN DWORD ielt, IN DWORD celt, OUT DWORD *pceltFetched, OUT CERTTRANSBLOB *pctbResultRows) // CoTaskMem
{ HRESULT hr; BOOL fNoMore = FALSE; BOOL fFetched = FALSE; DWORD cb; DWORD cbT; DWORD cColTotal; CERTDBRESULTROW *aelt = NULL; CERTDBRESULTROW *pelt; CERTDBRESULTROW *peltEnd; CERTDBRESULTCOLUMN *pcol; CERTDBRESULTCOLUMN *pcolEnd; CERTTRANSDBRESULTROW *pteltOut; CERTTRANSDBRESULTCOLUMN *ptcolOut; BYTE *pbOut; DWORD ieltLast; DWORD State = 0;
if(1<InterlockedIncrement(&m_cNext)) { hr = E_UNEXPECTED; _JumpError(hr, error, "Calls from multiple threads on the same view object"); }
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
DBGPRINT((DBG_SS_CERTSRVI, "_EnumViewNext(ielt=%d celt=%d)\n", ielt, celt));
aelt = (CERTDBRESULTROW *) LocalAlloc(LMEM_FIXED, celt * sizeof(aelt[0])); if (NULL == aelt) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Alloc result rows"); }
hr = pview->Skip(0, (LONG *) &ieltLast); _JumpIfError(hr, error, "Skip");
if (ielt != ieltLast + 1) { DBGPRINT(( DBG_SS_CERTSRVI, "_EnumViewNext! ieltLast=%d cskip=%d\n", ieltLast, ielt - ieltLast)); hr = pview->Skip(ielt - (ieltLast + 1), (LONG *) &ieltLast); _JumpIfError(hr, error, "Skip");
DBGPRINT(( DBG_SS_CERTSRVI, "_EnumViewNext! ielt after skip=%d\n", ieltLast)); }
hr = pview->Next(celt, aelt, pceltFetched); if (S_FALSE == hr) { fNoMore = TRUE; } else { _JumpIfError(hr, error, "Next"); } fFetched = TRUE;
DBGPRINT(( DBG_SS_CERTSRVI, "_EnumViewNext! celtFetched=%d\n", *pceltFetched));
cb = *pceltFetched * sizeof(*pteltOut); if (fNoMore) { cb += sizeof(*pteltOut); } cColTotal = 0;
peltEnd = &aelt[*pceltFetched]; for (pelt = aelt; pelt < peltEnd; pelt++) { cColTotal += pelt->ccol; cb += pelt->ccol * sizeof(*ptcolOut);
pcolEnd = &pelt->acol[pelt->ccol]; for (pcol = pelt->acol; pcol < pcolEnd; pcol++) { CSASSERT(DWORDROUND(cb) == cb); if (NULL != pcol->pbValue) { if ((DTI_REQUESTTABLE | DTR_REQUESTRAWARCHIVEDKEY) == pcol->Index) { cb += sizeof(DWORD); } else { cb += DWORDROUND(pcol->cbValue); } } } }
pctbResultRows->pb = (BYTE *) MIDL_user_allocate(cb); if (NULL == pctbResultRows->pb) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "MIDL_user_allocate result rows"); } pctbResultRows->cb = cb; ZeroMemory(pctbResultRows->pb, pctbResultRows->cb);
pbOut = pctbResultRows->pb;
DBGPRINT(( DBG_SS_CERTSRVI, "_EnumViewNext! Result Row data cb=0x%x @%x\n", pctbResultRows->cb, pctbResultRows->pb));
for (pelt = aelt; pelt < peltEnd; pelt++) { pteltOut = (CERTTRANSDBRESULTROW *) pbOut; pbOut += sizeof(*pteltOut); ptcolOut = (CERTTRANSDBRESULTCOLUMN *) pbOut; pbOut += pelt->ccol * sizeof(*ptcolOut);
pteltOut->rowid = pelt->rowid; pteltOut->ccol = pelt->ccol;
pcolEnd = &pelt->acol[pelt->ccol]; for (pcol = pelt->acol; pcol < pcolEnd; pcol++, ptcolOut++) { ptcolOut->Type = pcol->Type; ptcolOut->Index = pcol->Index;
if (NULL != pcol->pbValue) { if ((DTI_REQUESTTABLE | DTR_REQUESTRAWARCHIVEDKEY) == ptcolOut->Index) { cbT = sizeof(BYTE); CSASSERT(0 == *(DWORD *) pbOut); } else { cbT = pcol->cbValue; CopyMemory(pbOut, pcol->pbValue, cbT); } ptcolOut->cbValue = cbT; ptcolOut->obValue = SAFE_SUBTRACT_POINTERS(pbOut, (BYTE *) pteltOut); pbOut += DWORDROUND(cbT); } } pteltOut->cbrow = SAFE_SUBTRACT_POINTERS(pbOut, (BYTE *) pteltOut); }
// if past the end or at end of rowset, write an extra record containimg
// the maximum element count.
if (fNoMore) { pteltOut = (CERTTRANSDBRESULTROW *) pbOut; pbOut += sizeof(*pteltOut); pteltOut->rowid = pelt->rowid; pteltOut->ccol = pelt->ccol; pteltOut->cbrow = SAFE_SUBTRACT_POINTERS(pbOut, (BYTE *) pteltOut); CSASSERT(pteltOut->rowid == ~pteltOut->ccol); DBGPRINT(( DBG_SS_CERTSRVI, "_EnumViewNext! celtMax=%d\n", pteltOut->rowid)); }
DBGPRINT(( DBG_SS_CERTSRVI, "_EnumViewNext! pbOut=%x/%x\n", pbOut, &pctbResultRows->pb[pctbResultRows->cb]));
CSASSERT(&pctbResultRows->pb[pctbResultRows->cb] == pbOut);
if (fNoMore) { hr = S_FALSE; }
error: DBGPRINT(( DBG_SS_CERTSRVI, "_EnumViewNext: celtFetched=%d, hr=%x\n", *pceltFetched, hr)); if (fFetched) { HRESULT hr2;
hr2 = pview->ReleaseResultRow(*pceltFetched, aelt); _PrintIfError(hr2, "ReleaseResultRow"); } if (NULL != aelt) { LocalFree(aelt); }
CertSrvExitServer(State); InterlockedDecrement(&m_cNext); return(hr); }
STDMETHODIMP CCertAdminD::CloseView( IN wchar_t const *pwszAuthority) { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::CloseView(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { if (NULL == m_pView) { hr = E_UNEXPECTED; _LeaveError(hr, "No View"); }
m_pView->Release(); m_pView = NULL; hr = S_OK; } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::RevokeCertificate( /* [unique][in] */ USHORT const __RPC_FAR *pwszAuthority, /* [in, string, unique] */ USHORT const __RPC_FAR *pwszSerialNumber, /* [in] */ DWORD Reason, /* [in] */ FILETIME FileTime) { HRESULT hr; DWORD ReqId; DWORD cbProp; DWORD Disposition; DWORD OldReason; ICertDBRow *prow = NULL; WCHAR const *pwszDisposition = NULL; WCHAR const *pwszDispT; BOOL fUnRevoke = FALSE; BOOL fRevokeOnHold = FALSE; WCHAR *pwszUserName = NULL; CAuditEvent audit(SE_AUDITID_CERTSRV_REVOKECERT, g_dwAuditFilter); LPWSTR pwszRequesterName = NULL; DWORD State = 0; BOOL fCommitted = FALSE;
DBGPRINT(( s_ssAdmin, "CCertAdminD::RevokeCertificate(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { hr = audit.AddData(pwszSerialNumber); // %1 serial no.
_LeaveIfError(hr, "CAuditEvent::AddData");
hr = audit.AddData(Reason); // %2 reason
_LeaveIfError(hr, "CAuditEvent::AddData");
hr = audit.AccessCheck( CA_ACCESS_OFFICER, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
switch (Reason) { case MAXDWORD: fUnRevoke = TRUE; break;
case CRL_REASON_CERTIFICATE_HOLD: fRevokeOnHold = TRUE; break;
case CRL_REASON_UNSPECIFIED: case CRL_REASON_KEY_COMPROMISE: case CRL_REASON_CA_COMPROMISE: case CRL_REASON_AFFILIATION_CHANGED: case CRL_REASON_SUPERSEDED: case CRL_REASON_CESSATION_OF_OPERATION: case CRL_REASON_REMOVE_FROM_CRL: break;
default: hr = E_INVALIDARG; _LeaveError(hr, "Reason parameter"); }
hr = g_pCertDB->OpenRow(PROPTABLE_REQCERT, 0, pwszSerialNumber, &prow); if (S_OK != hr) { if (CERTSRV_E_PROPERTY_EMPTY == hr) { hr = E_INVALIDARG; // Invalid Serial Number
} _LeaveErrorStr(hr, "OpenRow", pwszSerialNumber); }
hr = PKCSGetProperty( prow, g_wszPropRequesterName, PROPTYPE_STRING | PROPCALLER_SERVER | PROPTABLE_REQUEST, NULL, (BYTE **) &pwszRequesterName); if (CERTSRV_E_PROPERTY_EMPTY != hr) { _LeaveIfErrorStr(hr, "PKCSGetProperty", g_wszPropRequesterName); }
hr = CheckOfficerRights(pwszRequesterName, audit); _LeaveIfError(hr, "CheckOfficerRights");
cbProp = sizeof(Disposition); hr = prow->GetProperty( g_wszPropRequestDisposition, PROPTYPE_LONG | PROPCALLER_SERVER | PROPTABLE_REQUEST, &cbProp, (BYTE *) &Disposition); _LeaveIfError(hr, "GetProperty");
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); switch (Disposition) { HRESULT hr2;
case DB_DISP_CA_CERT: if (!IsRootCA(g_CAType)) { _LeaveError(hr, "non-root CA"); } // FALLTHROUGH
case DB_DISP_ISSUED: case DB_DISP_REVOKED: cbProp = sizeof(OldReason); hr2 = prow->GetProperty( g_wszPropRequestRevokedReason, PROPTYPE_LONG | PROPCALLER_SERVER | PROPTABLE_REQUEST, &cbProp, (BYTE *) &OldReason);
// Converted MDB databases have UNrevoked rows' RevokedReason
// column set to zero (CRL_REASON_UNSPECIFIED).
if (S_OK != hr2 || (DB_DISP_ISSUED == Disposition && CRL_REASON_UNSPECIFIED == OldReason)) { OldReason = MAXDWORD; } if (fRevokeOnHold && MAXDWORD != OldReason && CRL_REASON_CERTIFICATE_HOLD != OldReason) { _LeaveError(hr, "already revoked: not on hold"); } if (fUnRevoke && CRL_REASON_CERTIFICATE_HOLD != OldReason) { _LeaveError(hr, "unrevoke: not on hold"); } break;
default: _LeaveError(hr, "invalid disposition"); }
hr = PropSetRequestTimeProperty(prow, g_wszPropRequestRevokedWhen); if (S_OK != hr) { hr = myHError(hr); _LeaveError(hr, "PropSetRequestTimeProperty"); }
hr = prow->SetProperty( g_wszPropRequestRevokedEffectiveWhen, PROPTYPE_DATE | PROPCALLER_SERVER | PROPTABLE_REQUEST, sizeof(FileTime), (BYTE const *) &FileTime); _LeaveIfError(hr, "SetProperty");
hr = prow->SetProperty( g_wszPropRequestRevokedReason, PROPTYPE_LONG | PROPCALLER_SERVER | PROPTABLE_REQUEST, sizeof(Reason), (BYTE const *) &Reason); _LeaveIfError(hr, "SetProperty");
hr = GetClientUserName(NULL, &pwszUserName, NULL); _LeaveIfError(hr, "GetClientUserName");
pwszDispT = fUnRevoke? g_pwszUnrevokedBy : g_pwszRevokedBy; pwszDisposition = CoreBuildDispositionString( pwszDispT, pwszUserName, NULL, NULL, S_OK, FALSE); if (NULL == pwszDisposition) { pwszDisposition = pwszDispT; }
hr = prow->SetProperty( g_wszPropRequestDispositionMessage, PROPTYPE_STRING | PROPCALLER_SERVER | PROPTABLE_REQUEST, MAXDWORD, (BYTE const *) pwszDisposition); _LeaveIfError(hr, "SetProperty");
if (DB_DISP_CA_CERT != Disposition) { Disposition = fUnRevoke? DB_DISP_ISSUED : DB_DISP_REVOKED; hr = prow->SetProperty( g_wszPropRequestDisposition, PROPTYPE_LONG | PROPCALLER_SERVER | PROPTABLE_REQUEST, sizeof(Disposition), (BYTE const *) &Disposition); _LeaveIfError(hr, "SetProperty"); }
hr = prow->CommitTransaction(TRUE); _LeaveIfError(hr, "CommitTransaction");
fCommitted = TRUE;
hr = audit.CachedGenerateAudit(); _LeaveIfError(hr, "CAuditEvent::CachedGenerateAudit");
prow->GetRowId(&ReqId); ExitNotify(EXITEVENT_CERTREVOKED, ReqId, MAXDWORD); CoreLogRequestStatus( prow, MSG_DN_CERT_REVOKED, hr, pwszDisposition); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != pwszUserName) { LocalFree(pwszUserName); } if (NULL != pwszRequesterName) { LocalFree(pwszRequesterName); } if (NULL != pwszDisposition && pwszDisposition != g_pwszRevokedBy) { LocalFree(const_cast<WCHAR *>(pwszDisposition)); } if (NULL != prow) { if (S_OK != hr && !fCommitted) { HRESULT hr2 = prow->CommitTransaction(FALSE); _PrintIfError(hr2, "CommitTransaction"); } prow->Release(); } CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::IsValidCertificate( /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszSerialNumber, /* [out] */ LONG __RPC_FAR *pRevocationReason, /* [out] */ LONG __RPC_FAR *pDisposition) { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::IsValidCertificate(tid=%d, this=%x, serial=%ws)\n", GetCurrentThreadId(), this, pwszSerialNumber));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { CAuditEvent audit(0, g_dwAuditFilter);
hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
hr = PKCSIsRevoked( 0, pwszSerialNumber, pRevocationReason, pDisposition); _LeaveIfError(hr, "PKCSIsRevoked"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); } DBGPRINT(( s_ssAdmin, "CCertAdminD::IsValidCertificate(serial=%ws) --> %x, Reason=%u Disposition=%u\n", pwszSerialNumber, hr, *pRevocationReason, *pDisposition));
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::ServerControl( IN wchar_t const *pwszAuthority, IN DWORD dwControlFlags, OUT CERTTRANSBLOB *pctbOut) { HRESULT hr; BOOL fBackupAccess = FALSE; CAuditEvent audit(SE_AUDITID_CERTSRV_SHUTDOWN, g_dwAuditFilter); DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::ServerControl(tid=%d, this=%x, Flags=0x%x)\n", GetCurrentThreadId(), this, dwControlFlags));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority, true); //allow empty name
_JumpIfError(hr, error, "CheckAuthorityName");
switch (dwControlFlags) { case CSCONTROL_SUSPEND: case CSCONTROL_RESTART: fBackupAccess = TRUE; break;
case CSCONTROL_SHUTDOWN: break;
default: hr = E_INVALIDARG; _JumpError(hr, error, "bad control flags"); }
__try { hr = audit.AccessCheck( fBackupAccess?CA_ACCESS_OPERATOR:CA_ACCESS_ADMIN, audit.m_gcAuditSuccessOrFailure); _LeaveIfError( hr, fBackupAccess? "CAuditEvent::AccessCheck backup": "CAuditEvent::AccessCheck admin");
switch (dwControlFlags) { case CSCONTROL_SHUTDOWN: myRegisterMemFree(this, CSM_NEW | CSM_GLOBALDESTRUCTOR);
hr = CertSrvLockServer(&State); _JumpIfError(hr, error, "CertSrvLockServer");
// have message loop run shutdown code
SendMessage(g_hwndMain, WM_STOPSERVER, 0, 0);
// post, don't wait for shutdown
PostMessage(g_hwndMain, WM_SYNC_CLOSING_THREADS, 0, 0); break; } } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
HRESULT CCertAdminD::_Ping( IN WCHAR const *pwszAuthority) { HRESULT hr; DWORD State = 0;
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority, true); //allow empty name
_JumpIfError(hr, error, "CheckAuthorityName");
__try { CAuditEvent audit(0, g_dwAuditFilter);
hr = audit.AccessCheck( CA_ACCESS_ADMIN, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
myRegisterMemDump(); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::Ping( IN WCHAR const *pwszAuthority) { HRESULT hr;
DBGPRINT(( s_ssAdmin, "CCertAdminD::Ping(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = _Ping(pwszAuthority); _JumpIfError(hr, error, "_Ping");
error: CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::Ping2( IN WCHAR const *pwszAuthority) { HRESULT hr;
DBGPRINT(( s_ssAdmin, "CCertAdminD::Ping2(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = _Ping(pwszAuthority); _JumpIfError(hr, error, "_Ping");
error: CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::GetServerState( IN WCHAR const *pwszAuthority, OUT DWORD *pdwState) { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::GetServerState(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority, true); //allow empty name
_JumpIfError(hr, error, "CheckAuthorityName");
__try { *pdwState = 0; { CAuditEvent audit(0, g_dwAuditFilter);
hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck"); }
*pdwState = 1; } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::BackupPrepare( IN WCHAR const *pwszAuthority, IN unsigned long grbitJet, IN unsigned long dwBackupFlags, IN WCHAR const *pwszBackupAnnotation, IN DWORD dwClientIdentifier) { HRESULT hr; CertSrv::CAuditEvent audit(SE_AUDITID_CERTSRV_BACKUPSTART,g_dwAuditFilter); DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::BackupPrepare(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority, true); //allow empty name
_JumpIfError(hr, error, "CheckAuthorityName");
__try { hr = audit.AddData(dwBackupFlags); //%1 backup type
_LeaveIfError(hr, "CAuditEvent::AddData");
hr = audit.AccessCheck( CA_ACCESS_OPERATOR, audit.m_gcAuditSuccessOrFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
if (NULL != m_pBackup) { hr = E_UNEXPECTED; _LeaveError(hr, "Has Backup"); } hr = g_pCertDB->OpenBackup(grbitJet, &m_pBackup); _LeaveIfError(hr, "OpenBackup");
m_grbitBackup = grbitJet; } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::BackupEnd() { HRESULT hr; CertSrv::CAuditEvent audit(SE_AUDITID_CERTSRV_BACKUPEND,g_dwAuditFilter); DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::BackupEnd(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
__try { hr = audit.AccessCheck( CA_ACCESS_OPERATOR, audit.m_gcAuditSuccessOrFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
if (NULL == m_pBackup) { hr = E_UNEXPECTED; _LeaveError(hr, "No backup"); } m_pBackup->Release(); m_pBackup = NULL; hr = S_OK; } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
HRESULT CCertAdminD::_GetDynamicFileList( IN OUT DWORD *pcwcList, OPTIONAL OUT WCHAR *pwszzList) { HRESULT hr = S_OK; HRESULT hr2; DWORD iCert; DWORD iDelta; DWORD iDeltaMax; DWORD cwc; DWORD cwcRemain; DWORD cwcTotal; WCHAR const * const *papwszSrc; WCHAR const * const *ppwsz; DWORD State = 0;
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
cwcRemain = *pcwcList; cwcTotal = 0; iDeltaMax = g_fDeltaCRLPublishDisabled? 0 : 1;
for (iCert = 0; iCert < g_cCACerts; iCert++) { for (iDelta = 0; iDelta <= iDeltaMax; iDelta++) { hr2 = PKCSGetCRLList(0 != iDelta, iCert, &papwszSrc); if (S_OK != hr2) { _PrintError2(hr2, "PKCSGetCRLList", hr2); continue; } for (ppwsz = papwszSrc; NULL != *ppwsz; ppwsz++) { WCHAR const *pwsz = *ppwsz;
// Just return local full path files:
if (iswalpha(pwsz[0]) && L':' == pwsz[1] && L'\\' == pwsz[2]) { cwc = wcslen(pwsz) + 1; if (NULL != pwszzList) { DWORD cwcT;
cwcT = min(cwc, cwcRemain); CopyMemory(pwszzList, *ppwsz, cwcT * sizeof(WCHAR)); pwszzList += cwcT; if (cwc > cwcT) { hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW); pwszzList = NULL; } cwcRemain -= cwcT; } cwcTotal += cwc; } } } }
// append an extra trailing L'\0'
if (NULL != pwszzList) { if (1 <= cwcRemain) { *pwszzList = L'\0'; } else { hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW); } } cwcTotal++;
*pcwcList = cwcTotal; _JumpIfError(hr, error, "Buffer Overflow");
error: CertSrvExitServer(State); return(hr); }
typedef struct _DBTAG { WCHAR const *pwszPath; WCHAR wcFileType; } DBTAG;
DBTAG g_adbtag[] = { { g_wszDatabase, CSBFT_CERTSERVER_DATABASE }, { g_wszLogDir, CSBFT_LOG_DIR }, { g_wszSystemDir, CSBFT_CHECKPOINT_DIR }, };
CSBFT BftClassify( IN WCHAR const *pwszFileName) { WCHAR *pwszPath = NULL; WCHAR const *pwszExt; WCHAR *pwsz; DWORD i; CSBFT bft;
// Do the easy cases first.
pwszExt = wcsrchr(pwszFileName, L'.'); if (NULL != pwszExt) { if (0 == lstrcmpi(pwszExt, L".pat")) { bft = CSBFT_PATCH_FILE; goto done; } if (0 == lstrcmpi(pwszExt, L".log")) { bft = CSBFT_LOG; goto done; } if (0 == lstrcmpi(pwszExt, L".edb")) { // It's a database. Find out which database it is.
for (i = 0; i < ARRAYSIZE(g_adbtag); i++) { bft = g_adbtag[i].wcFileType; if ((bft & CSBFT_DATABASE_DIRECTORY) && 0 == lstrcmpi(g_adbtag[i].pwszPath, pwszFileName)) { goto done; } } } }
// Ok, I give up. We don't know anything about this file at all;
// try to figure out what we can tell the caller about it.
pwszPath = (WCHAR *) LocalAlloc( LMEM_FIXED, (wcslen(pwszFileName) + 1) * sizeof(WCHAR)); if (NULL != pwszPath) { wcscpy(pwszPath, pwszFileName); pwsz = wcsrchr(pwszPath, L'\\'); if (NULL != pwsz) { *pwsz = L'\0'; // truncate to directory path
} for (i = 0; i < ARRAYSIZE(g_adbtag); i++) { bft = g_adbtag[i].wcFileType; if (bft & CSBFT_DIRECTORY) { // If this file's directory matches the directory we're
// looking at, we know where it needs to go on the restore.
if (0 == lstrcmpi(g_adbtag[i].pwszPath, pwszPath)) { goto done; } } } } bft = CSBFT_UNKNOWN;
done: if (NULL != pwszPath) { LocalFree(pwszPath); } return(bft); }
HRESULT CCertAdminD::_GetDatabaseLocations( IN OUT DWORD *pcwcList, OPTIONAL OUT WCHAR *pwszzList) { HRESULT hr = S_OK; DWORD cwc; DWORD cwcRemain; WCHAR *pwcRemain; DWORD i; DWORD State = 0;
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
cwcRemain = *pcwcList; pwcRemain = pwszzList;
cwc = 1; for (i = 0; i < ARRAYSIZE(g_adbtag); i++) { DWORD cwcT;
cwcT = wcslen(g_adbtag[i].pwszPath) + 1; cwc += 1 + cwcT; if (NULL != pwcRemain && 0 < cwcRemain) { *pwcRemain++ = g_adbtag[i].wcFileType; cwcRemain--; if (cwcT > cwcRemain) { cwcT = cwcRemain; } CopyMemory(pwcRemain, g_adbtag[i].pwszPath, cwcT * sizeof(WCHAR)); pwcRemain += cwcT; cwcRemain -= cwcT; } } if (NULL != pwcRemain) { if (0 < cwcRemain) { *pwcRemain = L'\0'; } if (cwc > *pcwcList) { hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW); } } *pcwcList = cwc; _JumpIfError(hr, error, "Buffer Overflow");
error: CertSrvExitServer(State); return(hr); }
STDMETHODIMP CCertAdminD::RestoreGetDatabaseLocations( OUT WCHAR **ppwszDatabaseLocations, OUT LONG *pcwcPaths) { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::RestoreGetDatabaseLocations(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
__try { hr = _BackupGetFileList(MAXDWORD, ppwszDatabaseLocations, pcwcPaths); _LeaveIfError(hr, "_BackupGetFileList");
myRegisterMemFree(*ppwszDatabaseLocations, CSM_MIDLUSERALLOC); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
// Convert UNC path to local full path, as in:
// \\server\c$\foo... --> c:\foo...
// Note the server name need not match the current server name.
HRESULT ConvertUNCToLocalPath( IN WCHAR const *pwszPath, OUT WCHAR **ppwszPathLocal) // LocalAlloc
{ HRESULT hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); WCHAR const *pwc;
*ppwszPathLocal = NULL;
if (L'\\' != pwszPath[0] || L'\\' != pwszPath[1]) { _JumpError(hr, error, "not a UNC path"); } pwc = wcschr(&pwszPath[2], L'\\'); if (NULL == pwc || !iswalpha(pwc[1]) || L'$' != pwc[2] || L'\\' != pwc[3]) { _JumpError(hr, error, "bad-UNC path"); } pwc++;
*ppwszPathLocal = (WCHAR *) LocalAlloc( LMEM_FIXED, (wcslen(pwc) + 1) * sizeof(WCHAR)); if (NULL == *ppwszPathLocal) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } wcscpy(*ppwszPathLocal, pwc);
CSASSERT(L'$' == (*ppwszPathLocal)[1]); (*ppwszPathLocal)[1] = L':';
hr = S_OK;
error: return(hr); }
// Convert local possibly annotated full paths to possibly annotated UNC, as:
// [CSBFT_*]c:\foo... --> [CSBFT_*]\\server\c$\foo...
HRESULT ConvertLocalPathsToMungedUNC( IN WCHAR const *pwszzFiles, IN BOOL fAnnotated, // TRUE if already annotated
IN WCHAR wcFileType, // else Annotation WCHAR (if not L'\0')
OUT DWORD *pcwc, OUT WCHAR **ppwszzFilesUNC) // MIDL_user_allocate
{ HRESULT hr; DWORD cwc; WCHAR const *pwsz; WCHAR *pwszDst; DWORD cfiles = 0; WCHAR *pwszzFilesUNC = NULL;
*pcwc = 0; for (pwsz = pwszzFiles; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1) { if (fAnnotated) { pwsz++; } if (!iswalpha(pwsz[0]) || L':' != pwsz[1] || L'\\' != pwsz[2]) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "non-local path"); } cfiles++; } cwc = SAFE_SUBTRACT_POINTERS(pwsz, pwszzFiles) + 1; cwc += cfiles * (2 + wcslen(g_pwszServerName) + 1); if (!fAnnotated && 0 != wcFileType) { cwc += cfiles; // Add munged CSBFT_* character
}
pwszzFilesUNC = (WCHAR *) MIDL_user_allocate(cwc * sizeof(WCHAR)); if (NULL == pwszzFilesUNC) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "MIDL_user_allocate pwszzFiles"); }
pwszDst = pwszzFilesUNC; for (pwsz = pwszzFiles; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1) { if (fAnnotated) { *pwszDst++ = *pwsz++; // "CSBFT"
} else if (0 != wcFileType) { *pwszDst++ = BftClassify(pwsz); // "CSBFT"
} wcscpy(pwszDst, L"\\\\"); // "[CSBFT]\\"
wcscat(pwszDst, g_pwszServerName); // "[CSBFT]\\server"
pwszDst += wcslen(pwszDst); *pwszDst++ = L'\\'; // "[CSBFT]\\server\"
*pwszDst++ = *pwsz++; // "[CSBFT]\\server\c"
*pwszDst++ = L'$'; // "[CSBFT]\\server\c$"
pwsz++; // skip colon
wcscpy(pwszDst, pwsz); // "[CSBFT]\\server\c$\foo..."
pwszDst += wcslen(pwszDst) + 1; } *pwszDst = L'\0'; CSASSERT(SAFE_SUBTRACT_POINTERS(pwszDst, pwszzFilesUNC) + 1 == cwc);
*pcwc = cwc; *ppwszzFilesUNC = pwszzFilesUNC; hr = S_OK;
error: return(hr); }
HRESULT CCertAdminD::_BackupGetFileList( IN DWORD dwFileType, OUT WCHAR **ppwszzFiles, // CoTaskMem*
OUT LONG *pcwcFiles) { HRESULT hr; WCHAR *pwszzFiles = NULL; WCHAR *pwszzFilesUNC = NULL; DWORD cwcFiles = 0; DWORD cwc; BOOL fAnnotated = FALSE; DWORD State = 0;
*ppwszzFiles = NULL; *pcwcFiles = 0;
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
if (NULL == m_pBackup && MAXDWORD != dwFileType && 0 != dwFileType) { hr = E_UNEXPECTED; _JumpIfError(hr, error, "No backup"); } while (TRUE) { cwc = cwcFiles; if (CSBFT_CERTSERVER_DATABASE == dwFileType) { hr = m_pBackup->GetDBFileList(&cwc, pwszzFiles); _JumpIfError(hr, error, "GetDBFileList"); } else if (CSBFT_LOG == dwFileType) { hr = m_pBackup->GetLogFileList(&cwc, pwszzFiles); _JumpIfError(hr, error, "GetLogFileList"); } else if (MAXDWORD == dwFileType) { hr = _GetDatabaseLocations(&cwc, pwszzFiles); _JumpIfError(hr, error, "_GetDatabaseLocations");
fAnnotated = TRUE; } else if (0 == dwFileType) { hr = _GetDynamicFileList(&cwc, pwszzFiles); _JumpIfError(hr, error, "_GetDynamicFileList"); } else { CSASSERT(!"bad FileListtype"); }
if (NULL != pwszzFiles) { break; } pwszzFiles = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR)); if (NULL == pwszzFiles) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc pwszzFiles"); } cwcFiles = cwc; } hr = ConvertLocalPathsToMungedUNC( pwszzFiles, fAnnotated, (WCHAR) dwFileType, &cwc, &pwszzFilesUNC); _JumpIfError(hr, error, "ConvertLocalPathsToMungedUNC");
*ppwszzFiles = pwszzFilesUNC; *pcwcFiles = cwc; pwszzFilesUNC = NULL;
error: if (NULL != pwszzFilesUNC) { MIDL_user_free(pwszzFilesUNC); } if (NULL != pwszzFiles) { LocalFree(pwszzFiles); } CertSrvExitServer(State); return(hr); }
STDMETHODIMP CCertAdminD::BackupGetAttachmentInformation( OUT WCHAR **ppwszzDBFiles, OUT LONG *pcwcDBFiles) { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::BackupGetAttachmentInformation(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
__try { hr = _BackupGetFileList( CSBFT_CERTSERVER_DATABASE, ppwszzDBFiles, pcwcDBFiles); _LeaveIfError(hr, "_BackupGetFileList");
myRegisterMemFree(*ppwszzDBFiles, CSM_MIDLUSERALLOC); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::BackupGetBackupLogs( OUT WCHAR **ppwszzLogFiles, OUT LONG *pcwcLogFiles) { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::BackupGetBackupLogs(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
__try { hr = _BackupGetFileList(CSBFT_LOG, ppwszzLogFiles, pcwcLogFiles); _LeaveIfError(hr, "_BackupGetFileList");
myRegisterMemFree(*ppwszzLogFiles, CSM_MIDLUSERALLOC); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::BackupGetDynamicFiles( OUT WCHAR **ppwszzFiles, OUT LONG *pcwcFiles) { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::BackupGetDynamicFiles(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
__try { hr = _BackupGetFileList(0, ppwszzFiles, pcwcFiles); _LeaveIfError(hr, "_BackupGetFileList");
myRegisterMemFree(*ppwszzFiles, CSM_MIDLUSERALLOC); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::BackupOpenFile( IN WCHAR const *pwszPath, OUT unsigned hyper *pliLength) { HRESULT hr; WCHAR *pwszPathLocal = NULL; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::BackupOpenFile(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
__try { if (NULL == m_pBackup) { hr = E_UNEXPECTED; _LeaveIfError(hr, "No backup"); } hr = ConvertUNCToLocalPath(pwszPath, &pwszPathLocal); _LeaveIfError(hr, "ConvertUNCToLocalPath");
hr = m_pBackup->OpenFile(pwszPathLocal, (ULARGE_INTEGER *) pliLength); _LeaveIfError(hr, "OpenFile"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); } if (NULL != pwszPathLocal) { LocalFree(pwszPathLocal); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::BackupReadFile( OUT BYTE *pbBuffer, IN LONG cbBuffer, OUT LONG *pcbRead) { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::BackupReadFile(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
__try { if (NULL == m_pBackup) { hr = E_UNEXPECTED; _LeaveIfError(hr, "No backup"); } *pcbRead = cbBuffer;
hr = m_pBackup->ReadFile((DWORD *) pcbRead, pbBuffer); _LeaveIfError(hr, "ReadFile"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::BackupCloseFile() { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::BackupCloseFile(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
__try { if (NULL == m_pBackup) { hr = E_UNEXPECTED; _LeaveIfError(hr, "No backup"); } hr = m_pBackup->CloseFile(); _LeaveIfError(hr, "CloseFile"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::BackupTruncateLogs() { HRESULT hr; DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::BackupTruncateLogs(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
__try { WCHAR *apwsz[1];
if (NULL == m_pBackup) { hr = E_UNEXPECTED; _LeaveIfError(hr, "No backup"); } hr = m_pBackup->TruncateLog(); _LeaveIfError(hr, "TruncateLog");
apwsz[0] = wszREGDBLASTINCREMENTALBACKUP; hr = CertSrvSetRegistryFileTimeValue( TRUE, (JET_bitBackupIncremental & m_grbitBackup)? wszREGDBLASTINCREMENTALBACKUP : wszREGDBLASTFULLBACKUP, (DWORD)((JET_bitBackupIncremental & m_grbitBackup)? 0 : ARRAYSIZE(apwsz)), apwsz); _PrintIfError(hr, "CertSrvSetRegistryFileTimeValue"); hr = S_OK; } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::ImportCertificate( IN wchar_t const *pwszAuthority, IN CERTTRANSBLOB *pctbCertificate, IN LONG Flags, OUT LONG *pRequestId) { HRESULT hr; ICertDBRow *prow = NULL; CERT_CONTEXT const *pCert = NULL; WCHAR *pwszUserName = NULL; BOOL fAllowed = FALSE; CACTX *pCAContext; CAuditEvent audit(SE_AUDITID_CERTSRV_IMPORTCERT, g_dwAuditFilter); DWORD State = 0; BOOL fCommitted = FALSE; DWORD Disposition; BYTE abHash[CBMAX_CRYPT_HASH_LEN]; DWORD cbHash; BSTR strHash = NULL;
DBGPRINT(( s_ssAdmin, "CCertAdminD::ImportCertificate(tid=%d, this=%x, cb=%x)\n", GetCurrentThreadId(), this, pctbCertificate->cb));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
if (~(ICF_ALLOWFOREIGN | CR_IN_ENCODEMASK) & Flags) { hr = E_INVALIDARG; _JumpError(hr, error, "Flags"); } if ((ICF_ALLOWFOREIGN & Flags) && 0 == (KRAF_ENABLEFOREIGN & g_KRAFlags)) { hr = E_INVALIDARG; _JumpError(hr, error, "Foreign disabled"); } hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { hr = audit.AddData( pctbCertificate->pb, pctbCertificate->cb); // %1 Certificate
_LeaveIfError(hr, "CAuditEvent::AddData");
hr = audit.AddData((DWORD)0); // %2 dummy request ID, if access check fails
// and a deny event is generated, we need the
// right number of audit arguments
_LeaveIfError(hr, "CAuditEvent::AddData");
hr = audit.AccessCheck( CA_ACCESS_OFFICER, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
pCert = CertCreateCertificateContext( X509_ASN_ENCODING, pctbCertificate->pb, pctbCertificate->cb); if (NULL == pCert) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _LeaveError(hr, "CertCreateCertificateContext"); }
// Be sure we issued this certificate before adding it to the database.
Disposition = DB_DISP_ISSUED; hr = PKCSVerifyIssuedCertificate(pCert, &pCAContext); if (S_OK != hr) { _PrintError2(hr, "PKCSVerifyIssuedCertificate", NTE_BAD_SIGNATURE); if (0 == (ICF_ALLOWFOREIGN & Flags)) { _LeaveError2( hr, "PKCSVerifyIssuedCertificate", NTE_BAD_SIGNATURE); } Disposition = DB_DISP_FOREIGN; pCAContext = NULL; }
cbHash = sizeof(abHash); if (!CertGetCertificateContextProperty( pCert, CERT_SHA1_HASH_PROP_ID, abHash, &cbHash)) { hr = myHLastError(); _LeaveError(hr, "CertGetCertificateContextProperty"); }
hr = MultiByteIntegerToBstr(TRUE, cbHash, abHash, &strHash); _LeaveIfError(hr, "MultiByteIntegerToBstr");
hr = g_pCertDB->OpenRow( PROPOPEN_READONLY | PROPOPEN_CERTHASH | PROPTABLE_REQCERT, 0, // RequestId
strHash, &prow); if (CERTSRV_E_PROPERTY_EMPTY != hr) { _LeaveIfErrorStr(hr, "OpenRow", strHash);
fCommitted = TRUE; // open for read-only: skip rollback
hr = HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS); _LeaveErrorStr2( hr, "Cert exists", strHash, HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS)); }
// okay, we've got valid data. Time to write to the Database.
hr = g_pCertDB->OpenRow(PROPTABLE_REQCERT, 0, NULL, &prow); _LeaveIfError(hr, "OpenRow");
// set request id
hr = prow->GetRowId((DWORD *) pRequestId); _LeaveIfError(hr, "GetRowId");
hr = GetClientUserName(NULL, &pwszUserName, NULL); _LeaveIfError(hr, "GetClientUserName");
hr = prow->SetProperty( g_wszPropRequesterName, PROPTYPE_STRING | PROPCALLER_SERVER | PROPTABLE_REQUEST, MAXDWORD, (BYTE const *) pwszUserName); _LeaveIfError(hr, "SetProperty(requester)");
hr = prow->SetProperty( g_wszPropCallerName, PROPTYPE_STRING | PROPCALLER_SERVER | PROPTABLE_REQUEST, MAXDWORD, (BYTE const *) pwszUserName); _LeaveIfError(hr, "SetProperty(caller)");
hr = PKCSParseImportedCertificate( Disposition, prow, pCAContext, pCert); _LeaveIfError(hr, "PKCSParseImportedCertificate");
hr = prow->CommitTransaction(TRUE); _LeaveIfError(hr, "CommitTransaction");
fCommitted = TRUE;
audit.DeleteLastData(); // remove dummy request ID added above
hr = audit.AddData((DWORD) *pRequestId); // %2 request ID
_LeaveIfError(hr, "CAuditEvent::AddData");
hr = audit.CachedGenerateAudit(); _LeaveIfError(hr, "CAuditEvent::CachedGenerateAudit"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != strHash) { SysFreeString(strHash); } if (NULL != pwszUserName) { LocalFree(pwszUserName); } if (NULL != pCert) { CertFreeCertificateContext(pCert); } if (NULL != prow) { if (S_OK != hr && !fCommitted) { HRESULT hr2 = prow->CommitTransaction(FALSE); _PrintIfError(hr2, "CommitTransaction"); } prow->Release(); } CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::ImportKey( IN wchar_t const *pwszAuthority, IN DWORD RequestId, IN wchar_t const *pwszCertHash, IN DWORD Flags, IN CERTTRANSBLOB *pctbKey) { HRESULT hr; ICertDBRow *prow = NULL; CAuditEvent audit(SE_AUDITID_CERTSRV_IMPORTKEY, g_dwAuditFilter); DWORD State = 0; BOOL fCommitted = FALSE; BYTE *pbCert = NULL; DWORD cbCert; CERT_CONTEXT const *pCert = NULL;
DBGPRINT(( s_ssAdmin, "CCertAdminD::ImportKey(tid=%d, this=%x, cb=%x)\n", GetCurrentThreadId(), this, pctbKey->cb));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
if (~(IKF_OVERWRITE | CR_IN_ENCODEMASK) & Flags) { hr = E_INVALIDARG; _JumpError(hr, error, "Flags"); }
__try { CRYPT_ATTR_BLOB BlobEncrypted; DWORD cb;
hr = audit.AddData(RequestId); // %1 request ID
_LeaveIfError(hr, "AddData");
hr = audit.AccessCheck( CA_ACCESS_OFFICER, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
if (MAXDWORD == RequestId) { RequestId = 0; } if (0 == RequestId && NULL == pwszCertHash) { hr = E_INVALIDARG; _LeaveError(hr, "pwszCertHash NULL"); }
hr = g_pCertDB->OpenRow( PROPTABLE_REQCERT | (NULL != pwszCertHash? PROPOPEN_CERTHASH : 0), RequestId, pwszCertHash, &prow); _LeaveIfErrorStr(hr, "OpenRow", pwszCertHash);
BlobEncrypted.cbData = pctbKey->cb; BlobEncrypted.pbData = pctbKey->pb;
cb = 0; hr = prow->GetProperty( g_wszPropRequestRawArchivedKey, PROPTYPE_BINARY | PROPCALLER_SERVER | PROPTABLE_REQUEST, &cb, NULL); if (CERTSRV_E_PROPERTY_EMPTY != hr) { _LeaveIfErrorStr(hr, "OpenRow", pwszCertHash); } hr = PKCSGetProperty( prow, g_wszPropRawCertificate, PROPTYPE_BINARY | PROPCALLER_SERVER | PROPTABLE_CERTIFICATE, &cbCert, (BYTE **) &pbCert); _LeaveIfError(hr, "PKCSGetProperty(cert)");
pCert = CertCreateCertificateContext(X509_ASN_ENCODING, pbCert, cbCert); if (NULL == pCert) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _LeaveError(hr, "CertCreateCertificateContext"); }
hr = PKCSArchivePrivateKey( prow, CERT_V1 == pCert->pCertInfo->dwVersion, (IKF_OVERWRITE & Flags)? TRUE : FALSE, &BlobEncrypted, NULL); _LeaveIfError2( hr, "PKCSArchivePrivateKey", HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS));
hr = prow->CommitTransaction(TRUE); _LeaveIfError(hr, "CommitTransaction");
fCommitted = TRUE;
hr = audit.CachedGenerateAudit(); _LeaveIfError(hr, "CAuditEvent::CachedGenerateAudit"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (NULL != pbCert) { LocalFree(pbCert); } if (NULL != pCert) { CertFreeCertificateContext(pCert); } if (NULL != prow) { if (S_OK != hr && !fCommitted) { HRESULT hr2 = prow->CommitTransaction(FALSE); _PrintIfError(hr2, "CommitTransaction"); } prow->Release(); } CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
STDMETHODIMP CCertAdminD::GetCASecurity( IN WCHAR const *pwszAuthority, OUT CERTTRANSBLOB *pctbSD) // CoTaskMem*
{ HRESULT hr; PSECURITY_DESCRIPTOR pSD = NULL; CAuditEvent audit(0, g_dwAuditFilter); DWORD State = 0;
// init
pctbSD->pb = NULL; pctbSD->cb = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::GetCASecurity(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "CheckAuthorityName");
__try { hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
// get current SD:
hr = g_CASD.LockGet(&pSD); // no free
_LeaveIfError(hr, "CProtectedSecurityDescriptor::LockGet");
pctbSD->cb = GetSecurityDescriptorLength(pSD); pctbSD->pb = (BYTE *) MIDL_user_allocate(pctbSD->cb); if (NULL == pctbSD->pb) { hr = E_OUTOFMEMORY; _LeaveError(hr, "MIDL_user_allocate"); } myRegisterMemFree(pctbSD->pb, CSM_MIDLUSERALLOC); CopyMemory(pctbSD->pb, pSD, pctbSD->cb);
hr = g_CASD.Unlock(); _LeaveIfError(hr, "CProtectedSecurityDescriptor::Unlock"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); return hr; }
STDMETHODIMP CCertAdminD::SetCASecurity( IN WCHAR const *pwszAuthority, IN CERTTRANSBLOB *pctbSD) { HRESULT hr; PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR) pctbSD->pb; LPWSTR pwszSD = NULL; CAuditEvent audit(SE_AUDITID_CERTSRV_SETSECURITY, g_dwAuditFilter); DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::SetCASecurity(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "CheckAuthorityName");
__try { hr = audit.AddData(pctbSD->pb, pctbSD->cb); // %1 dump permissions as blob, we
// don't want to parse the blob unless
// access check succeeds
_LeaveIfError(hr, "CAuditEvent::AddData");
hr = audit.AccessCheck( CA_ACCESS_ADMIN, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
hr = CCertificateAuthoritySD::ConvertToString(pSD, pwszSD); _LeaveIfError(hr, "CAuditEvent::ConvertToString");
audit.DeleteLastData(); // remove permissions blob to add a human friendly SD dump
hr = audit.AddData(pwszSD); _LeaveIfError(hr, "CAuditEvent::AddData");
hr = g_CASD.Set(pSD, g_fUseDS?true:false); _LeaveIfError(hr, "CProtectedSecurityDescriptor::Set");
if (g_OfficerRightsSD.IsEnabled()) { // adjust officer rights to match new CA SD; persistently save it
hr = g_OfficerRightsSD.Adjust(pSD); _LeaveIfError(hr, "CProtectedSecurityDescriptor::Adjust");
hr = g_OfficerRightsSD.Save(); _LeaveIfError(hr, "CProtectedSecurityDescriptor::Save"); }
hr = g_CASD.Save(); _LeaveIfError(hr, "CProtectedSecurityDescriptor::Save");
hr = audit.CachedGenerateAudit(); _LeaveIfError(hr, "CAuditEvent::CachedGenerateAudit");
} __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: if (HRESULT_FROM_WIN32(ERROR_CAN_NOT_COMPLETE) == hr) { LogEventString( EVENTLOG_ERROR_TYPE, MSG_E_CANNOT_WRITE_TO_DS, g_wszCommonName); } else { if(S_OK != hr) { LogEventHResult( EVENTLOG_ERROR_TYPE, MSG_E_CANNOT_SET_PERMISSIONS, hr); } }
LOCAL_FREE(pwszSD); CertSrvExitServer(State); return hr; }
// Constructor
CCertAdminD::CCertAdminD() : m_cRef(1), m_cNext(0) { InterlockedIncrement(&g_cAdminComponents); m_pEnumCol = NULL; m_pView = NULL; m_pBackup = NULL; }
// Destructor
CCertAdminD::~CCertAdminD() { InterlockedDecrement(&g_cAdminComponents); if (NULL != m_pEnumCol) { m_pEnumCol->Release(); m_pEnumCol = NULL; } if (NULL != m_pView) { m_pView->Release(); m_pView = NULL; } if (NULL != m_pBackup) { m_pBackup->Release(); m_pBackup = NULL; } }
// IUnknown implementation
STDMETHODIMP CCertAdminD::QueryInterface(const IID& iid, void** ppv) { if (iid == IID_IUnknown) { *ppv = static_cast<ICertAdminD *>(this); } else if (iid == IID_ICertAdminD) { *ppv = static_cast<ICertAdminD *>(this); } else if (iid == IID_ICertAdminD2) { *ppv = static_cast<ICertAdminD2 *>(this); } else { *ppv = NULL; return(E_NOINTERFACE); } reinterpret_cast<IUnknown *>(*ppv)->AddRef(); return(S_OK); }
ULONG STDMETHODCALLTYPE CCertAdminD::AddRef() { return(InterlockedIncrement(&m_cRef)); }
ULONG STDMETHODCALLTYPE CCertAdminD::Release() { ULONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef) { delete this; } return(cRef); }
CAdminFactory::~CAdminFactory() { if (m_cRef != 0) { DBGPRINT(( DBG_SS_CERTSRV, "CAdminFactory has %d instances left over\n", m_cRef)); } }
// Class factory IUnknown implementation
STDMETHODIMP CAdminFactory::QueryInterface(const IID& iid, void** ppv) { if ((iid == IID_IUnknown) || (iid == IID_IClassFactory)) { *ppv = static_cast<IClassFactory*>(this); } else { *ppv = NULL; return(E_NOINTERFACE); } reinterpret_cast<IUnknown *>(*ppv)->AddRef(); return(S_OK); }
ULONG STDMETHODCALLTYPE CAdminFactory::AddRef() { return(InterlockedIncrement(&m_cRef)); }
ULONG STDMETHODCALLTYPE CAdminFactory::Release() { ULONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef) { delete this; return(0); } return(cRef); }
// IClassFactory implementation
STDMETHODIMP CAdminFactory::CreateInstance( IUnknown *pUnknownOuter, const IID& iid, void **ppv) { HRESULT hr; CCertAdminD *pA;
// Cannot aggregate.
if (pUnknownOuter != NULL) { hr = CLASS_E_NOAGGREGATION; _JumpError(hr, error, "pUnknownOuter"); }
// Create component.
pA = new CCertAdminD; if (pA == NULL) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "out of memory"); }
// Get the requested interface.
hr = pA->QueryInterface(iid, ppv);
// Release the IUnknown pointer.
// (If QueryInterface failed, component will delete itself.)
pA->Release();
error: CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
// LockServer
STDMETHODIMP CAdminFactory::LockServer( BOOL bLock) { if (bLock) { InterlockedIncrement(&g_cAdminServerLocks); } else { InterlockedDecrement(&g_cAdminServerLocks); } return(S_OK); }
STDMETHODIMP CAdminFactory::CanUnloadNow() { if (g_cAdminComponents || g_cAdminServerLocks) { return(S_FALSE); } return(S_OK); }
STDMETHODIMP CAdminFactory::StartFactory() { HRESULT hr;
g_pIAdminFactory = new CAdminFactory(); if (NULL == g_pIAdminFactory) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "alloc CAdminFactory"); }
hr = CoRegisterClassObject( CLSID_CCertAdminD, static_cast<IUnknown *>(g_pIAdminFactory), CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &g_dwAdminRegister); _JumpIfError(hr, error, "CoRegisterClassObject");
error: if (S_OK != hr) { CAdminFactory::StopFactory(); } CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
VOID CAdminFactory::StopFactory() { HRESULT hr;
if (0 != g_dwAdminRegister) { hr = CoRevokeClassObject(g_dwAdminRegister); _PrintIfError(hr, "CoRevokeClassObject"); g_dwAdminRegister = 0; } if (NULL != g_pIAdminFactory) { g_pIAdminFactory->Release(); g_pIAdminFactory = NULL; } }
STDMETHODIMP CCertAdminD::GetAuditFilter( IN wchar_t const *pwszAuthority, OUT DWORD *pdwFilter) { HRESULT hr; DWORD State = 0; CAuditEvent audit(0, g_dwAuditFilter);
*pdwFilter = 0;
if (!g_fAdvancedServer) { hr = HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED); _JumpError(hr, error, "g_fAdvancedServer"); }
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
*pdwFilter = g_dwAuditFilter; } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); return(hr); }
STDMETHODIMP CCertAdminD::SetAuditFilter( IN wchar_t const *pwszAuthority, IN DWORD dwFilter) { HRESULT hr; CAuditEvent audit(SE_AUDITID_CERTSRV_SETAUDITFILTER, g_dwAuditFilter); DWORD State = 0;
if (!g_fAdvancedServer) { hr = HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED); _JumpError(hr, error, "g_fAdvancedServer"); }
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { hr = audit.AddData(dwFilter); // %1 filter
_LeaveIfError(hr, "AddParam");
hr = audit.AccessCheck( CA_ACCESS_AUDITOR, audit.m_gcAuditSuccessOrFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
// save the audit filter using a dummy audit object
{ CAuditEvent dummyaudit(0, dwFilter);
hr = dummyaudit.SaveFilter(g_wszSanitizedName); _LeaveIfError(hr, "CAuditEvent::SaveFilter"); } g_dwAuditFilter = dwFilter;
// we can't catch service start/stop events generated
// by SCM, so we need to update the SACL on the service
hr = UpdateServiceSacl(g_dwAuditFilter&AUDIT_FILTER_STARTSTOP); _LeaveIfError(hr, "UpdateServiceSacl"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); return(hr); }
STDMETHODIMP CCertAdminD::GetOfficerRights( IN wchar_t const *pwszAuthority, OUT BOOL *pfEnabled, OUT CERTTRANSBLOB *pctbSD) { HRESULT hr; PSECURITY_DESCRIPTOR pSD = NULL; CAuditEvent audit(0, g_dwAuditFilter); DWORD State = 0;
pctbSD->pb = NULL; pctbSD->cb = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::GetOfficerRights(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
if (!g_fAdvancedServer) { hr = HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED); _JumpError(hr, error, "g_fAdvancedServer"); }
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "CheckAuthorityName");
__try { hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
*pfEnabled = g_OfficerRightsSD.IsEnabled();
// return the security descriptor only if the feature is enabled
if (g_OfficerRightsSD.IsEnabled()) { // get current SD:
hr = g_OfficerRightsSD.LockGet(&pSD); // no free
_LeaveIfError(hr, "CProtectedSecurityDescriptor::LockGet");
pctbSD->cb = GetSecurityDescriptorLength(pSD); pctbSD->pb = (BYTE *) MIDL_user_allocate(pctbSD->cb); if (NULL == pctbSD->pb) { hr = E_OUTOFMEMORY; _LeaveError(hr, "MIDL_user_allocate"); } myRegisterMemFree(pctbSD->pb, CSM_MIDLUSERALLOC); CopyMemory(pctbSD->pb, pSD, pctbSD->cb);
hr = g_OfficerRightsSD.Unlock(); _LeaveIfError(hr, "CProtectedSecurityDescriptor::Unlock"); } } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); return hr;
}
STDMETHODIMP CCertAdminD::SetOfficerRights( IN wchar_t const *pwszAuthority, IN BOOL fEnable, IN CERTTRANSBLOB *pctbSD) { HRESULT hr; PSECURITY_DESCRIPTOR pNewOfficerSD = (PSECURITY_DESCRIPTOR) pctbSD->pb; PSECURITY_DESCRIPTOR pCASD = NULL; LPWSTR pwszSD = NULL; CAuditEvent audit(SE_AUDITID_CERTSRV_SETOFFICERRIGHTS, g_dwAuditFilter); DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::SetOfficerRights(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
if (!g_fAdvancedServer) { hr = HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED); _JumpError(hr, error, "g_fAdvancedServer"); } hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "CheckAuthorityName");
__try {
hr = audit.AddData(fEnable?true:false); // %1 Enable restrictions?
_LeaveIfError(hr, "CAuditEvent::AddData");
if(fEnable) { hr = audit.AddData(pctbSD->pb, pctbSD->cb); // %2 new permissions; add as
// blob, we don't convert to string
// unless access check passes
_LeaveIfError(hr, "CAuditEvent::AddData"); } else { hr = audit.AddData(L""); // %2 no permissions if disabling
// the officer restrictions
_LeaveIfError(hr, "CAuditEvent::AddData"); }
hr = audit.AccessCheck( CA_ACCESS_ADMIN, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
g_OfficerRightsSD.SetEnable(fEnable);
// ignore new security descriptor if asked to turn officer rights off
if (fEnable) { hr = g_CASD.LockGet(&pCASD); // no free
_LeaveIfError(hr, "CProtectedSecurityDescriptor::LockGet");
// adjust new officer rights based on the CA SD and set the
// officer rights SD to the new SD
hr = g_OfficerRightsSD.Merge(pNewOfficerSD, pCASD); _LeaveIfError(hr, "COfficerRightsSD::Merge");
hr = g_CASD.Unlock(); _LeaveIfError(hr, "CProtectedSecurityDescriptor::Unlock"); }
// persistent save to registry
hr = g_OfficerRightsSD.Save(); _LeaveIfError(hr, "CProtectedSecurityDescriptor::Save");
if(fEnable) { hr = COfficerRightsSD::ConvertToString(pNewOfficerSD, pwszSD); _LeaveIfError(hr, "COfficerRightsSD::ConvertToString"); audit.DeleteLastData(); // remove permissions blob
hr = audit.AddData(pwszSD); // %2 add human-friend permissions string
_LeaveIfError(hr, "CAuditEvent::AddData"); }
hr = audit.CachedGenerateAudit(); _LeaveIfError(hr, "CAuditEvent::CachedGenerateAudit");
} __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: LOCAL_FREE(pwszSD); CertSrvExitServer(State); return hr; }
STDMETHODIMP CCertAdminD::GetConfigEntry( wchar_t const *pwszAuthority, wchar_t const *pwszNodePath, wchar_t const *pwszEntry, VARIANT *pVariant) { HRESULT hr; CAuditEvent audit(0, g_dwAuditFilter); DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::GetConfigEntry(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority, true); // allow empty/null name
_JumpIfError(hr, error, "CheckAuthorityName");
__try { hr = audit.AccessCheck( CA_ACCESS_ALLREADROLES, audit.m_gcNoAuditSuccess | audit.m_gcNoAuditFailure); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
hr = g_ConfigStorage.GetEntry( EmptyString(pwszAuthority)? NULL : g_wszSanitizedName, // allow empty/null name
pwszNodePath, pwszEntry, pVariant); _LeaveIfError2( hr, "CConfigStorage::GetConfigEntry", HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
myRegisterMemFree(pVariant, CSM_VARIANT); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); return hr; }
STDMETHODIMP CCertAdminD::SetConfigEntry( wchar_t const *pwszAuthority, wchar_t const *pwszNodePath, wchar_t const *pwszEntry, VARIANT *pVariant) { HRESULT hr; CAuditEvent audit(SE_AUDITID_CERTSRV_SETCONFIGENTRY, g_dwAuditFilter); DWORD State = 0;
DBGPRINT(( s_ssAdmin, "CCertAdminD::SetConfigEntry(tid=%d, this=%x)\n", GetCurrentThreadId(), this));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority, true); // allow empty/null name
_JumpIfError(hr, error, "CheckAuthorityName");
hr = audit.AddData(pwszNodePath); // %1 node
_JumpIfError(hr, error, "CAuditEvent::AddData");
hr = audit.AddData(pwszEntry); // %2 entry
_JumpIfError(hr, error, "CAuditEvent::AddData");
hr = audit.AddData(L""); // %3 empty data, we don't process the variant
// unless the access check passes
_JumpIfError(hr, error, "CAuditEvent::AddData");
__try { hr = audit.AccessCheck( CA_ACCESS_ADMIN, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck");
hr = g_ConfigStorage.SetEntry( EmptyString(pwszAuthority)? NULL : g_wszSanitizedName, // allow empty/null name
pwszNodePath, pwszEntry, pVariant); _LeaveIfError(hr, "CConfigStorage::SetConfigEntry");
// postpone adding the actual data to allow set entry to validate it
audit.DeleteLastData(); hr = audit.AddData( pVariant, // %3 value
true); // true means convert % chars found in strings to %% (bug# 326248)
_LeaveIfError(hr, "CAuditEvent::AddData");
hr = audit.CachedGenerateAudit(); _LeaveIfError(hr, "CAuditEvent::CachedGenerateAudit"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); return hr; }
STDMETHODIMP CCertAdminD::GetMyRoles( IN wchar_t const *pwszAuthority, OUT LONG *pdwRoles) { HRESULT hr; CAuditEvent audit(0, g_dwAuditFilter); DWORD dwRoles = 0; DWORD State = 0;
*pdwRoles = 0;
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try { hr = audit.GetMyRoles(&dwRoles); _LeaveIfError(hr, "CAuditEvent::GetMyRoles");
*pdwRoles = dwRoles; } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); return(hr); }
HRESULT adminDeleteRow( IN DWORD dwRowId, IN DWORD dwPropTable) { HRESULT hr; ICertDBRow *prow = NULL; BOOL fCommitted = FALSE;
hr = g_pCertDB->OpenRow( PROPOPEN_DELETE | dwPropTable, dwRowId, NULL, &prow); _JumpIfError2(hr, error, "OpenRow", CERTSRV_E_PROPERTY_EMPTY);
hr = prow->Delete(); _JumpIfError(hr, error, "Delete");
hr = prow->CommitTransaction(TRUE); _JumpIfError(hr, error, "CommitTransaction");
fCommitted = TRUE;
error: if (NULL != prow) { if (S_OK != hr && !fCommitted) { HRESULT hr2 = prow->CommitTransaction(FALSE); _PrintIfError(hr2, "CommitTransaction"); } prow->Release(); } return(hr); }
HRESULT adminDeleteByRowId( IN DWORD dwRowId, IN DWORD dwPropTable, OUT LONG *pcDeleted) { HRESULT hr; LONG cDeleted = 0; LONG cDeletedExt = 0; LONG cDeletedAttr = 0;
*pcDeleted = 0;
if (PROPTABLE_REQCERT == dwPropTable) { hr = adminDeleteByRowId(dwRowId, PROPTABLE_EXTENSION, &cDeletedExt); _JumpIfError(hr, error, "adminDeleteByRowId(ext)");
DBGPRINT(( DBG_SS_CERTSRV, "adminDeleteByRowId(Rowid=%u) deleted %u extension rows\n", dwRowId, cDeletedExt));
hr = adminDeleteByRowId(dwRowId, PROPTABLE_ATTRIBUTE, &cDeletedAttr); _JumpIfError(hr, error, "adminDeleteByRowId(attrib)");
DBGPRINT(( DBG_SS_CERTSRV, "adminDeleteByRowId(Rowid=%u) deleted %u attribute rows\n", dwRowId, cDeletedAttr)); } while (TRUE) { hr = adminDeleteRow(dwRowId, dwPropTable); if (CERTSRV_E_PROPERTY_EMPTY == hr) { break; } _JumpIfError(hr, error, "adminDeleteByRowId");
cDeleted++; } if (0 == cDeleted && 0 != (cDeletedExt + cDeletedAttr)) { cDeleted++; } hr = S_OK;
error: *pcDeleted += cDeleted; return(hr); }
#define ICOLDEL_DATE 0
#define ICOLDEL_DISPOSITION 1
HRESULT adminDeleteRowsFromQuery( IN DWORD dwPropTable, IN DWORD DateColumn, IN DWORD DispositionColumn, IN BOOL fRequest, IN FILETIME const *pft, OUT LONG *pcDeleted) { HRESULT hr; CERTVIEWRESTRICTION acvr[1]; CERTVIEWRESTRICTION *pcvr; IEnumCERTDBRESULTROW *pView = NULL; DWORD celtFetched; DWORD i; BOOL fEnd; CERTDBRESULTROW aResult[10]; BOOL fResultActive = FALSE; DWORD acol[2]; DWORD ccol; DWORD cDeleted = 0;
*pcDeleted = 0;
// Set up restrictions as follows:
pcvr = acvr;
// DateColumn < *pft
pcvr->ColumnIndex = DateColumn; pcvr->SeekOperator = CVR_SEEK_LT; pcvr->SortOrder = CVR_SORT_ASCEND; pcvr->pbValue = (BYTE *) pft; pcvr->cbValue = sizeof(*pft); pcvr++;
CSASSERT(ARRAYSIZE(acvr) == SAFE_SUBTRACT_POINTERS(pcvr, acvr));
ccol = 0; acol[ccol++] = DateColumn; if (0 != DispositionColumn) { acol[ccol++] = DispositionColumn; }
hr = g_pCertDB->OpenView( ARRAYSIZE(acvr), acvr, ccol, acol, 0, // no worker thread
&pView); _JumpIfError(hr, error, "OpenView");
fEnd = FALSE; while (!fEnd) { hr = pView->Next(ARRAYSIZE(aResult), aResult, &celtFetched); if (S_FALSE == hr) { fEnd = TRUE; if (0 == celtFetched) { break; } hr = S_OK; } _JumpIfError(hr, error, "Next");
fResultActive = TRUE;
CSASSERT(ARRAYSIZE(aResult) >= celtFetched);
for (i = 0; i < celtFetched; i++) { BOOL fDelete = TRUE; CERTDBRESULTROW *pResult = &aResult[i];
CSASSERT(ccol == pResult->ccol);
if (0 != DispositionColumn) { DWORD Disposition;
CSASSERT(NULL != pResult->acol[ICOLDEL_DISPOSITION].pbValue); CSASSERT(PROPTYPE_LONG == (PROPTYPE_MASK & pResult->acol[ICOLDEL_DISPOSITION].Type)); CSASSERT(sizeof(Disposition) == pResult->acol[ICOLDEL_DISPOSITION].cbValue); Disposition = *(DWORD *) pResult->acol[ICOLDEL_DISPOSITION].pbValue;
if (fRequest) { // Delete only pending and failed requests
if (DB_DISP_PENDING != Disposition && DB_DISP_LOG_FAILED_MIN > Disposition) { fDelete = FALSE; } } else { // Delete only issued and revoked certs
if (DB_DISP_LOG_MIN > Disposition || DB_DISP_LOG_FAILED_MIN <= Disposition) { fDelete = FALSE; } } }
CSASSERT(PROPTYPE_DATE == (PROPTYPE_MASK & pResult->acol[ICOLDEL_DATE].Type));
// If the date column is missing, delete the row.
#ifdef DBG_CERTSRV_DEBUG_PRINT
if (NULL != pResult->acol[ICOLDEL_DATE].pbValue && sizeof(FILETIME) == pResult->acol[ICOLDEL_DATE].cbValue) { WCHAR *pwszTime = NULL;
myGMTFileTimeToWszLocalTime( (FILETIME *) pResult->acol[ICOLDEL_DATE].pbValue, TRUE, &pwszTime);
DBGPRINT(( DBG_SS_CERTSRV, "adminDeleteRowsFromQuery(%ws)\n", pwszTime)); if (NULL != pwszTime) { LocalFree(pwszTime); } } #endif // DBG_CERTSRV_DEBUG_PRINT
if (fDelete) { LONG cDelT; hr = adminDeleteByRowId(pResult->rowid, dwPropTable, &cDelT); _JumpIfError(hr, error, "adminDeleteByRowId");
DBGPRINT(( DBG_SS_CERTSRV, "adminDeleteByRowId(Rowid=%u) deleted %u Query rows\n", pResult->rowid, cDelT));
cDeleted += cDelT; } } pView->ReleaseResultRow(celtFetched, aResult); fResultActive = FALSE; } hr = S_OK;
error: *pcDeleted = cDeleted; if (NULL != pView) { if (fResultActive) { pView->ReleaseResultRow(celtFetched, aResult); } pView->Release(); } return(hr); } #undef ICOLDEL_DATE
#undef ICOLDEL_DISPOSITION
STDMETHODIMP CCertAdminD::DeleteRow( IN wchar_t const *pwszAuthority, IN DWORD dwFlags, // CDR_*
IN FILETIME FileTime, IN DWORD dwTable, // CVRC_TABLE_*
IN DWORD dwRowId, OUT LONG *pcDeleted) { HRESULT hr; DWORD dwPropTable; CAuditEvent audit(SE_AUDITID_CERTSRV_DELETEROW, g_dwAuditFilter); DWORD DateColumn; DWORD DispositionColumn; BOOL fRequest; DWORD State = 0;
*pcDeleted = 0;
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
__try {
hr = audit.AddData(dwTable); // %1 table ID
_JumpIfError(hr, error, "CAuditEvent::AddData");
if (0 == dwRowId) { hr = audit.AddData(FileTime); // %2 filter (time)
_JumpIfError(hr, error, "CAuditEvent::AddData"); hr = audit.AddData((DWORD)0); // %3 rows deleted
_JumpIfError(hr, error, "CAuditEvent::AddData");
// bulk deletion -- must be local admin
hr = audit.AccessCheck( CA_ACCESS_LOCALADMIN, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck"); } else { hr = audit.AddData(dwRowId); // %2 filter (request ID)
_JumpIfError(hr, error, "CAuditEvent::AddData");
hr = audit.AddData((DWORD)0); // %3 rows deleted
_JumpIfError(hr, error, "CAuditEvent::AddData");
// individual deletion -- CA admin suffices
hr = audit.AccessCheck( CA_ACCESS_ADMIN, audit.m_gcNoAuditSuccess); _LeaveIfError(hr, "CAuditEvent::AccessCheck"); }
hr = E_INVALIDARG; if ((0 == FileTime.dwLowDateTime && 0 == FileTime.dwHighDateTime) ^ (0 != dwRowId)) { _LeaveError(hr, "row OR date required"); } DateColumn = 0; DispositionColumn = 0; fRequest = FALSE; switch (dwTable) { case CVRC_TABLE_REQCERT: dwPropTable = PROPTABLE_REQCERT; switch (dwFlags) { case CDR_EXPIRED: DateColumn = DTI_CERTIFICATETABLE | DTC_CERTIFICATENOTAFTERDATE; DispositionColumn = DTI_REQUESTTABLE | DTR_REQUESTDISPOSITION; break;
case CDR_REQUEST_LAST_CHANGED: DateColumn = DTI_REQUESTTABLE | DTR_REQUESTRESOLVEDWHEN; DispositionColumn = DTI_REQUESTTABLE | DTR_REQUESTDISPOSITION; fRequest = TRUE; break;
case 0: break;
default: _LeaveError(hr, "dwFlags"); break; } break;
case CVRC_TABLE_EXTENSIONS: if (0 == dwRowId) { _LeaveError(hr, "no date field in Extension table"); } if (0 != dwFlags) { _LeaveError(hr, "dwFlags"); } dwPropTable = PROPTABLE_EXTENSION; break;
case CVRC_TABLE_ATTRIBUTES: if (0 == dwRowId) { _LeaveError(hr, "no date field in Request Attribute table"); } if (0 != dwFlags) { _LeaveError(hr, "dwFlags"); } dwPropTable = PROPTABLE_ATTRIBUTE; break;
case CVRC_TABLE_CRL: dwPropTable = PROPTABLE_CRL; switch (dwFlags) { case CDR_EXPIRED: DateColumn = DTI_CERTIFICATETABLE | DTC_CERTIFICATENOTAFTERDATE; break;
case 0: break;
default: _LeaveError(hr, "dwFlags"); break; } DateColumn = DTI_CRLTABLE | DTL_NEXTUPDATEDATE; break;
default: _LeaveError(hr, "dwTable"); } if (0 != dwRowId) { hr = adminDeleteByRowId(dwRowId, dwPropTable, pcDeleted); _LeaveIfError(hr, "adminDeleteByRowId");
DBGPRINT(( DBG_SS_CERTSRV, "adminDeleteByRowId(Rowid=%u) deleted %u rows\n", dwRowId, *pcDeleted)); } else { CSASSERT(0 != DateColumn);
hr = adminDeleteRowsFromQuery( dwPropTable, DateColumn, DispositionColumn, fRequest, &FileTime, pcDeleted); _LeaveIfError(hr, "adminDeleteRowsFromQuery"); }
audit.DeleteLastData(); hr = audit.AddData((DWORD)*pcDeleted); // %3 rows deleted
_JumpIfError(hr, error, "CAuditEvent::AddData");
hr = audit.CachedGenerateAudit(); _JumpIfError(hr, error, "CAuditEvent::CachedGenerateAudit");
} __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); }
error: CertSrvExitServer(State); return(hr); }
|