Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

587 lines
14 KiB

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: exit.cpp
//
// Contents: CCertExitSQLSample implementation
//
//---------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
#include <assert.h>
#include "celib.h"
#include "exit.h"
#include "module.h"
BOOL fDebug = DBG_CERTSRV;
#ifndef DBG_CERTSRV
#error -- DBG_CERTSRV not defined!
#endif
#define ceEXITEVENTS \
EXITEVENT_CERTISSUED | \
EXITEVENT_CERTREVOKED
#define CERTTYPE_ATTR_NAME TEXT("CertificateTemplate")
extern HINSTANCE g_hInstance;
// worker
HRESULT
GetServerCallbackInterface(
OUT ICertServerExit** ppServer,
IN LONG Context)
{
HRESULT hr;
if (NULL == ppServer)
{
hr = E_POINTER;
_JumpError(hr, error, "Exit:NULL pointer");
}
hr = CoCreateInstance(
CLSID_CCertServerExit,
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
IID_ICertServerExit,
(VOID **) ppServer);
_JumpIfError(hr, error, "Exit:CoCreateInstance");
if (*ppServer == NULL)
{
hr = E_UNEXPECTED;
_JumpError(hr, error, "Exit:NULL *ppServer");
}
// only set context if nonzero
if (0 != Context)
{
hr = (*ppServer)->SetContext(Context);
_JumpIfError(hr, error, "Exit: SetContext");
}
error:
return hr;
}
//+--------------------------------------------------------------------------
// CCertExitSQLSample::~CCertExitSQLSample -- destructor
//
// free memory associated with this instance
//+--------------------------------------------------------------------------
CCertExitSQLSample::~CCertExitSQLSample()
{
if (SQL_NULL_HDBC != m_hdbc1)
{
SQLDisconnect(m_hdbc1);
SQLFreeHandle(SQL_HANDLE_DBC, m_hdbc1);
}
if (SQL_NULL_HENV != m_henv)
SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
if (NULL != m_strCAName)
{
SysFreeString(m_strCAName);
}
}
//+--------------------------------------------------------------------------
// CCertExitSQLSample::Initialize -- initialize for a CA & return interesting Event Mask
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertExitSQLSample::Initialize(
/* [in] */ BSTR const strConfig,
/* [retval][out] */ LONG __RPC_FAR *pEventMask)
{
HRESULT hr = S_OK;
DWORD dwType;
WCHAR rgchDsn[MAX_PATH];
WCHAR rgchUser[MAX_PATH];
WCHAR rgchPwd[MAX_PATH];
DWORD cbTmp;
ICertServerExit *pServer = NULL;
SQLRETURN retcode = SQL_SUCCESS;
DWORD dwDisposition;
HKEY hkeyStorageLocation = NULL;
VARIANT varValue;
VariantInit(&varValue);
m_strCAName = SysAllocString(strConfig);
if (NULL == m_strCAName)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "Exit:SysAllocString");
}
hr = GetServerCallbackInterface(&pServer, 0);
_JumpIfError(hr, error, "GetServerCallbackInterface");
hr = pServer->GetCertificateProperty(
wszPROPMODULEREGLOC,
PROPTYPE_STRING,
&varValue);
_JumpIfError(hr, error, "GetCertificateProperty");
hr = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
varValue.bstrVal,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_READ,
NULL,
&hkeyStorageLocation,
&dwDisposition);
_JumpIfError(hr, error, "RegCreateKeyEx");
cbTmp = sizeof(rgchDsn)*sizeof(WCHAR);
// dsn
hr = RegQueryValueEx(
hkeyStorageLocation,
wszREG_EXITSQL_DSN,
0,
&dwType,
(PBYTE)rgchDsn,
&cbTmp);
if (dwType != REG_SZ)
hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
_JumpIfError(hr, error, "RegQueryValueEx DSN");
cbTmp = sizeof(rgchUser)*sizeof(WCHAR);
// username
hr = RegQueryValueEx(
hkeyStorageLocation,
wszREG_EXITSQL_USER,
0,
&dwType,
(PBYTE)rgchUser,
&cbTmp);
if (dwType != REG_SZ)
hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
_JumpIfError(hr, error, "RegQueryValueEx User");
cbTmp = sizeof(rgchPwd)*sizeof(WCHAR);
// password
hr = RegQueryValueEx(
hkeyStorageLocation,
wszREG_EXITSQL_PASSWORD,
0,
&dwType,
(PBYTE)rgchPwd,
&cbTmp);
if (dwType != REG_SZ)
hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
_JumpIfError(hr, error, "RegQueryValueEx Pwd");
// Allocate the ODBC Environment and save handle.
retcode = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv);
if (!SQL_SUCCEEDED(retcode))
_JumpError(retcode, error, "SQLAllocHandle");
// Let ODBC know this is an ODBC 3.0 application.
retcode = SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER);
if (!SQL_SUCCEEDED(retcode))
_JumpError(retcode, error, "SQLSetEnvAttr");
// Allocate an ODBC connection and connect.
retcode = SQLAllocHandle(SQL_HANDLE_DBC, m_henv, &m_hdbc1);
if (!SQL_SUCCEEDED(retcode))
_JumpError(retcode, error, "SQLAllocHandle");
retcode = SQLConnect(m_hdbc1, rgchDsn, SQL_NTS, rgchUser, SQL_NTS, rgchPwd, SQL_NTS);
if (!SQL_SUCCEEDED(retcode))
_JumpError(retcode, error, "SQLConnect");
*pEventMask = ceEXITEVENTS;
DBGPRINT((fDebug, "Exit:Initialize(%ws) ==> %x\n", m_strCAName, *pEventMask));
hr = S_OK;
error:
if (pServer)
pServer->Release();
if (hkeyStorageLocation)
RegCloseKey(hkeyStorageLocation);
if (!SQL_SUCCEEDED(retcode))
hr = ERROR_BAD_QUERY_SYNTAX;
return(ceHError(hr));
}
//+--------------------------------------------------------------------------
// CCertExitSQLSample::_NotifyNewCert -- Notify the exit module of a new certificate
//
//+--------------------------------------------------------------------------
HRESULT
CCertExitSQLSample::_NotifyNewCert(
/* [in] */ LONG Context)
{
HRESULT hr;
VARIANT varValue;
ICertServerExit *pServer = NULL;
SYSTEMTIME stBefore, stAfter;
FILETIME ftBefore, ftAfter;
// properties
LONG lRequestID;
BSTR bstrCertType = NULL;
BSTR bstrRequester = NULL;
DATE dateBefore;
DATE dateAfter;
VariantInit(&varValue);
hr = GetServerCallbackInterface(&pServer, Context);
_JumpIfError(hr, error, "GetServerCallbackInterface");
// ReqID
hr = pServer->GetRequestProperty(
wszPROPREQUESTREQUESTID,
PROPTYPE_LONG,
&varValue);
_JumpIfErrorStr(hr, error, "Exit:GetCertificateProperty", wszPROPREQUESTREQUESTID);
if (VT_I4 != varValue.vt)
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
_JumpError(hr, error, "Exit:BAD cert var type");
}
lRequestID = varValue.lVal;
VariantClear(&varValue);
// Requester Name
hr = pServer->GetRequestProperty(
wszPROPREQUESTERNAME,
PROPTYPE_STRING,
&varValue);
_JumpIfErrorStr(hr, error, "Exit:GetCertificateProperty", wszPROPREQUESTREQUESTID);
if (VT_BSTR != varValue.vt)
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
_JumpError(hr, error, "Exit:BAD cert var type");
}
bstrRequester = varValue.bstrVal;
VariantInit(&varValue); // don't init, bstrRequester nows owns memory
// not before
hr = pServer->GetCertificateProperty(
wszPROPCERTIFICATENOTBEFOREDATE,
PROPTYPE_DATE,
&varValue);
_JumpIfErrorStr(hr, error, "Exit:GetCertificateProperty", wszPROPREQUESTREQUESTID);
if (VT_DATE != varValue.vt)
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
_JumpError(hr, error, "Exit:BAD cert var type");
}
dateBefore = varValue.date;
VariantClear(&varValue);
// not after
hr = pServer->GetCertificateProperty(
wszPROPCERTIFICATENOTAFTERDATE,
PROPTYPE_DATE,
&varValue);
_JumpIfErrorStr(hr, error, "Exit:GetCertificateProperty", wszPROPREQUESTREQUESTID);
if (VT_DATE != varValue.vt)
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
_JumpError(hr, error, "Exit:BAD cert var type");
}
dateAfter = varValue.date;
VariantClear(&varValue);
// cert template name
hr = pServer->GetRequestAttribute(CERTTYPE_ATTR_NAME, &bstrCertType);
_PrintIfError2(hr, "Exit:GetRequestAttribute", hr);
// now prettify
hr = ceDateToFileTime(&dateBefore, &ftBefore);
_JumpIfError(hr, error, "ceDateToFileTime");
hr = ceDateToFileTime(&dateAfter, &ftAfter);
_JumpIfError(hr, error, "ceDateToFileTime");
hr = ExitModSetODBCProperty(
lRequestID,
m_strCAName,
bstrRequester,
bstrCertType,
&ftBefore,
&ftAfter);
DBGPRINT((fDebug, "ESQL: Logged request %d to SQL database\n", lRequestID));
error:
if (NULL != bstrCertType)
{
SysFreeString(bstrCertType);
}
if (NULL != bstrRequester)
{
SysFreeString(bstrCertType);
}
VariantClear(&varValue);
if (NULL != pServer)
{
pServer->Release();
}
return(hr);
}
//+--------------------------------------------------------------------------
// CCertExitSQLSample::Notify -- Notify the exit module of an event
//
// Returns S_OK.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertExitSQLSample::Notify(
/* [in] */ LONG ExitEvent,
/* [in] */ LONG Context)
{
char *psz = "UNKNOWN EVENT";
HRESULT hr = S_OK;
switch (ExitEvent)
{
case EXITEVENT_CERTISSUED:
hr = _NotifyNewCert(Context);
psz = "certissued";
break;
case EXITEVENT_CERTPENDING:
psz = "certpending";
break;
case EXITEVENT_CERTDENIED:
psz = "certdenied";
break;
case EXITEVENT_CERTREVOKED:
psz = "certrevoked";
break;
case EXITEVENT_CERTRETRIEVEPENDING:
psz = "retrievepending";
break;
case EXITEVENT_CRLISSUED:
psz = "crlissued";
break;
case EXITEVENT_SHUTDOWN:
psz = "shutdown";
break;
}
DBGPRINT((
fDebug,
"Exit:Notify(%hs=%x, ctx=%u) rc=%x\n",
psz,
ExitEvent,
Context,
hr));
return(hr);
}
STDMETHODIMP
CCertExitSQLSample::GetDescription(
/* [retval][out] */ BSTR *pstrDescription)
{
HRESULT hr = S_OK;
WCHAR sz[MAX_PATH];
assert(wcslen(wsz_SAMPLE_DESCRIPTION) < ARRAYSIZE(sz));
wcscpy(sz, wsz_SAMPLE_DESCRIPTION);
*pstrDescription = SysAllocString(sz);
if (NULL == *pstrDescription)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "Exit:SysAllocString");
}
error:
return(hr);
}
/////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP
CCertExitSQLSample::InterfaceSupportsErrorInfo(REFIID riid)
{
int i;
static const IID *arr[] =
{
&IID_ICertExit,
};
for (i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
{
if (IsEqualGUID(*arr[i],riid))
{
return(S_OK);
}
}
return(S_FALSE);
}
HRESULT
CCertExitSQLSample::ExitModSetODBCProperty(
IN DWORD dwReqId,
IN LPWSTR pszCAName,
IN LPWSTR pszRequester,
IN LPWSTR pszCertType,
IN FILETIME* pftBefore,
IN FILETIME* pftAfter)
{
SQLRETURN retcode;
HRESULT hr = S_OK;
SQLHSTMT hstmt1 = SQL_NULL_HSTMT;
SQLWCHAR* pszStatement = NULL;
SYSTEMTIME stTmp;
SQL_TIMESTAMP_STRUCT dateValidFrom, dateValidTo;
SQLINTEGER cValidFrom=sizeof(dateValidFrom), cValidTo =sizeof(dateValidTo);
static WCHAR szSQLInsertStmt[] = L"INSERT INTO OutstandingCertificates (CAName, RequestID, RequesterName, CertType, validFrom, validTo) VALUES (\'%ws\', %d, \'%ws\', \'%ws\', ?, ?)";
// temporarily fix NULL to ""
if (NULL == pszCAName)
pszCAName = L"";
if (NULL == pszRequester)
pszRequester = L"";
if (NULL == pszCertType)
pszCertType = L"";
// Allocate a statement handle.
retcode = SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc1, &hstmt1);
if (!SQL_SUCCEEDED(retcode))
goto error;
// Bind the parameter.
retcode = SQLBindParameter(hstmt1, 1, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 0, 0,
&dateValidFrom, 0, &cValidFrom);
if (!SQL_SUCCEEDED(retcode))
goto error;
retcode = SQLBindParameter(hstmt1, 2, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 0, 0,
&dateValidTo, 0, &cValidTo);
if (!SQL_SUCCEEDED(retcode))
goto error;
// Place the valid from date in the dsOpenDate structure.
if (!FileTimeToSystemTime(pftBefore, &stTmp))
{
hr = GetLastError();
hr = HRESULT_FROM_WIN32(hr);
_JumpError(hr, error, "FileTimeToSystemTime");
}
dateValidFrom.year = stTmp.wYear;
dateValidFrom.month = stTmp.wMonth;
dateValidFrom.day = stTmp.wDay;
dateValidFrom.hour = stTmp.wHour;
dateValidFrom.minute = stTmp.wMinute;
dateValidFrom.second = stTmp.wSecond;
// Place the valid to date in the dsOpenDate structure.
if (!FileTimeToSystemTime(pftAfter, &stTmp))
{
hr = GetLastError();
hr = HRESULT_FROM_WIN32(hr);
_JumpError(hr, error, "FileTimeToSystemTime");
}
dateValidTo.year = stTmp.wYear;
dateValidTo.month = stTmp.wMonth;
dateValidTo.day = stTmp.wDay;
dateValidTo.hour = stTmp.wHour;
dateValidTo.minute = stTmp.wMinute;
dateValidTo.second = stTmp.wSecond;
// Build INSERT statement.
pszStatement = (SQLWCHAR*) LocalAlloc(LMEM_FIXED, (sizeof(szSQLInsertStmt)+wcslen(pszCAName)+wcslen(pszRequester)+wcslen(pszCertType)+15 +1) *2);
if (NULL == pszStatement)
{
hr = E_OUTOFMEMORY;
goto error;
}
wsprintf(pszStatement, szSQLInsertStmt, pszCAName, dwReqId, pszRequester, pszCertType);
//OutputDebugStringW(pszStatement);
// Execute an SQL statement directly on the statement handle.
// Uses a default result set because no cursor attributes are set.
retcode = SQLExecDirect(hstmt1, pszStatement, SQL_NTS);
if (!SQL_SUCCEEDED(retcode))
goto error;
error:
/* Clean up. */
if (NULL != pszStatement)
LocalFree(pszStatement);
if (SQL_NULL_HSTMT != hstmt1)
SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
if (!SQL_SUCCEEDED(retcode))
hr = ERROR_BAD_QUERY_SYNTAX;
return (hr);
}