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

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: exit.cpp
  7. //
  8. // Contents: CCertExitSQLSample implementation
  9. //
  10. //---------------------------------------------------------------------------
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. #include <assert.h>
  14. #include "celib.h"
  15. #include "exit.h"
  16. #include "module.h"
  17. BOOL fDebug = DBG_CERTSRV;
  18. #ifndef DBG_CERTSRV
  19. #error -- DBG_CERTSRV not defined!
  20. #endif
  21. #define ceEXITEVENTS \
  22. EXITEVENT_CERTISSUED | \
  23. EXITEVENT_CERTREVOKED
  24. #define CERTTYPE_ATTR_NAME TEXT("CertificateTemplate")
  25. extern HINSTANCE g_hInstance;
  26. // worker
  27. HRESULT
  28. GetServerCallbackInterface(
  29. OUT ICertServerExit** ppServer,
  30. IN LONG Context)
  31. {
  32. HRESULT hr;
  33. if (NULL == ppServer)
  34. {
  35. hr = E_POINTER;
  36. _JumpError(hr, error, "Exit:NULL pointer");
  37. }
  38. hr = CoCreateInstance(
  39. CLSID_CCertServerExit,
  40. NULL, // pUnkOuter
  41. CLSCTX_INPROC_SERVER,
  42. IID_ICertServerExit,
  43. (VOID **) ppServer);
  44. _JumpIfError(hr, error, "Exit:CoCreateInstance");
  45. if (*ppServer == NULL)
  46. {
  47. hr = E_UNEXPECTED;
  48. _JumpError(hr, error, "Exit:NULL *ppServer");
  49. }
  50. // only set context if nonzero
  51. if (0 != Context)
  52. {
  53. hr = (*ppServer)->SetContext(Context);
  54. _JumpIfError(hr, error, "Exit: SetContext");
  55. }
  56. error:
  57. return hr;
  58. }
  59. //+--------------------------------------------------------------------------
  60. // CCertExitSQLSample::~CCertExitSQLSample -- destructor
  61. //
  62. // free memory associated with this instance
  63. //+--------------------------------------------------------------------------
  64. CCertExitSQLSample::~CCertExitSQLSample()
  65. {
  66. if (SQL_NULL_HDBC != m_hdbc1)
  67. {
  68. SQLDisconnect(m_hdbc1);
  69. SQLFreeHandle(SQL_HANDLE_DBC, m_hdbc1);
  70. }
  71. if (SQL_NULL_HENV != m_henv)
  72. SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
  73. if (NULL != m_strCAName)
  74. {
  75. SysFreeString(m_strCAName);
  76. }
  77. }
  78. //+--------------------------------------------------------------------------
  79. // CCertExitSQLSample::Initialize -- initialize for a CA & return interesting Event Mask
  80. //
  81. // Returns S_OK on success.
  82. //+--------------------------------------------------------------------------
  83. STDMETHODIMP
  84. CCertExitSQLSample::Initialize(
  85. /* [in] */ BSTR const strConfig,
  86. /* [retval][out] */ LONG __RPC_FAR *pEventMask)
  87. {
  88. HRESULT hr = S_OK;
  89. DWORD dwType;
  90. WCHAR rgchDsn[MAX_PATH];
  91. WCHAR rgchUser[MAX_PATH];
  92. WCHAR rgchPwd[MAX_PATH];
  93. DWORD cbTmp;
  94. ICertServerExit *pServer = NULL;
  95. SQLRETURN retcode = SQL_SUCCESS;
  96. DWORD dwDisposition;
  97. HKEY hkeyStorageLocation = NULL;
  98. VARIANT varValue;
  99. VariantInit(&varValue);
  100. m_strCAName = SysAllocString(strConfig);
  101. if (NULL == m_strCAName)
  102. {
  103. hr = E_OUTOFMEMORY;
  104. _JumpError(hr, error, "Exit:SysAllocString");
  105. }
  106. hr = GetServerCallbackInterface(&pServer, 0);
  107. _JumpIfError(hr, error, "GetServerCallbackInterface");
  108. hr = pServer->GetCertificateProperty(
  109. wszPROPMODULEREGLOC,
  110. PROPTYPE_STRING,
  111. &varValue);
  112. _JumpIfError(hr, error, "GetCertificateProperty");
  113. hr = RegCreateKeyEx(
  114. HKEY_LOCAL_MACHINE,
  115. varValue.bstrVal,
  116. 0,
  117. NULL,
  118. REG_OPTION_NON_VOLATILE,
  119. KEY_READ,
  120. NULL,
  121. &hkeyStorageLocation,
  122. &dwDisposition);
  123. _JumpIfError(hr, error, "RegCreateKeyEx");
  124. cbTmp = sizeof(rgchDsn)*sizeof(WCHAR);
  125. // dsn
  126. hr = RegQueryValueEx(
  127. hkeyStorageLocation,
  128. wszREG_EXITSQL_DSN,
  129. 0,
  130. &dwType,
  131. (PBYTE)rgchDsn,
  132. &cbTmp);
  133. if (dwType != REG_SZ)
  134. hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
  135. _JumpIfError(hr, error, "RegQueryValueEx DSN");
  136. cbTmp = sizeof(rgchUser)*sizeof(WCHAR);
  137. // username
  138. hr = RegQueryValueEx(
  139. hkeyStorageLocation,
  140. wszREG_EXITSQL_USER,
  141. 0,
  142. &dwType,
  143. (PBYTE)rgchUser,
  144. &cbTmp);
  145. if (dwType != REG_SZ)
  146. hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
  147. _JumpIfError(hr, error, "RegQueryValueEx User");
  148. cbTmp = sizeof(rgchPwd)*sizeof(WCHAR);
  149. // password
  150. hr = RegQueryValueEx(
  151. hkeyStorageLocation,
  152. wszREG_EXITSQL_PASSWORD,
  153. 0,
  154. &dwType,
  155. (PBYTE)rgchPwd,
  156. &cbTmp);
  157. if (dwType != REG_SZ)
  158. hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
  159. _JumpIfError(hr, error, "RegQueryValueEx Pwd");
  160. // Allocate the ODBC Environment and save handle.
  161. retcode = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv);
  162. if (!SQL_SUCCEEDED(retcode))
  163. _JumpError(retcode, error, "SQLAllocHandle");
  164. // Let ODBC know this is an ODBC 3.0 application.
  165. retcode = SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER);
  166. if (!SQL_SUCCEEDED(retcode))
  167. _JumpError(retcode, error, "SQLSetEnvAttr");
  168. // Allocate an ODBC connection and connect.
  169. retcode = SQLAllocHandle(SQL_HANDLE_DBC, m_henv, &m_hdbc1);
  170. if (!SQL_SUCCEEDED(retcode))
  171. _JumpError(retcode, error, "SQLAllocHandle");
  172. retcode = SQLConnect(m_hdbc1, rgchDsn, SQL_NTS, rgchUser, SQL_NTS, rgchPwd, SQL_NTS);
  173. if (!SQL_SUCCEEDED(retcode))
  174. _JumpError(retcode, error, "SQLConnect");
  175. *pEventMask = ceEXITEVENTS;
  176. DBGPRINT((fDebug, "Exit:Initialize(%ws) ==> %x\n", m_strCAName, *pEventMask));
  177. hr = S_OK;
  178. error:
  179. if (pServer)
  180. pServer->Release();
  181. if (hkeyStorageLocation)
  182. RegCloseKey(hkeyStorageLocation);
  183. if (!SQL_SUCCEEDED(retcode))
  184. hr = ERROR_BAD_QUERY_SYNTAX;
  185. return(ceHError(hr));
  186. }
  187. //+--------------------------------------------------------------------------
  188. // CCertExitSQLSample::_NotifyNewCert -- Notify the exit module of a new certificate
  189. //
  190. //+--------------------------------------------------------------------------
  191. HRESULT
  192. CCertExitSQLSample::_NotifyNewCert(
  193. /* [in] */ LONG Context)
  194. {
  195. HRESULT hr;
  196. VARIANT varValue;
  197. ICertServerExit *pServer = NULL;
  198. SYSTEMTIME stBefore, stAfter;
  199. FILETIME ftBefore, ftAfter;
  200. // properties
  201. LONG lRequestID;
  202. BSTR bstrCertType = NULL;
  203. BSTR bstrRequester = NULL;
  204. DATE dateBefore;
  205. DATE dateAfter;
  206. VariantInit(&varValue);
  207. hr = GetServerCallbackInterface(&pServer, Context);
  208. _JumpIfError(hr, error, "GetServerCallbackInterface");
  209. // ReqID
  210. hr = pServer->GetRequestProperty(
  211. wszPROPREQUESTREQUESTID,
  212. PROPTYPE_LONG,
  213. &varValue);
  214. _JumpIfErrorStr(hr, error, "Exit:GetCertificateProperty", wszPROPREQUESTREQUESTID);
  215. if (VT_I4 != varValue.vt)
  216. {
  217. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  218. _JumpError(hr, error, "Exit:BAD cert var type");
  219. }
  220. lRequestID = varValue.lVal;
  221. VariantClear(&varValue);
  222. // Requester Name
  223. hr = pServer->GetRequestProperty(
  224. wszPROPREQUESTERNAME,
  225. PROPTYPE_STRING,
  226. &varValue);
  227. _JumpIfErrorStr(hr, error, "Exit:GetCertificateProperty", wszPROPREQUESTREQUESTID);
  228. if (VT_BSTR != varValue.vt)
  229. {
  230. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  231. _JumpError(hr, error, "Exit:BAD cert var type");
  232. }
  233. bstrRequester = varValue.bstrVal;
  234. VariantInit(&varValue); // don't init, bstrRequester nows owns memory
  235. // not before
  236. hr = pServer->GetCertificateProperty(
  237. wszPROPCERTIFICATENOTBEFOREDATE,
  238. PROPTYPE_DATE,
  239. &varValue);
  240. _JumpIfErrorStr(hr, error, "Exit:GetCertificateProperty", wszPROPREQUESTREQUESTID);
  241. if (VT_DATE != varValue.vt)
  242. {
  243. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  244. _JumpError(hr, error, "Exit:BAD cert var type");
  245. }
  246. dateBefore = varValue.date;
  247. VariantClear(&varValue);
  248. // not after
  249. hr = pServer->GetCertificateProperty(
  250. wszPROPCERTIFICATENOTAFTERDATE,
  251. PROPTYPE_DATE,
  252. &varValue);
  253. _JumpIfErrorStr(hr, error, "Exit:GetCertificateProperty", wszPROPREQUESTREQUESTID);
  254. if (VT_DATE != varValue.vt)
  255. {
  256. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  257. _JumpError(hr, error, "Exit:BAD cert var type");
  258. }
  259. dateAfter = varValue.date;
  260. VariantClear(&varValue);
  261. // cert template name
  262. hr = pServer->GetRequestAttribute(CERTTYPE_ATTR_NAME, &bstrCertType);
  263. _PrintIfError2(hr, "Exit:GetRequestAttribute", hr);
  264. // now prettify
  265. hr = ceDateToFileTime(&dateBefore, &ftBefore);
  266. _JumpIfError(hr, error, "ceDateToFileTime");
  267. hr = ceDateToFileTime(&dateAfter, &ftAfter);
  268. _JumpIfError(hr, error, "ceDateToFileTime");
  269. hr = ExitModSetODBCProperty(
  270. lRequestID,
  271. m_strCAName,
  272. bstrRequester,
  273. bstrCertType,
  274. &ftBefore,
  275. &ftAfter);
  276. DBGPRINT((fDebug, "ESQL: Logged request %d to SQL database\n", lRequestID));
  277. error:
  278. if (NULL != bstrCertType)
  279. {
  280. SysFreeString(bstrCertType);
  281. }
  282. if (NULL != bstrRequester)
  283. {
  284. SysFreeString(bstrCertType);
  285. }
  286. VariantClear(&varValue);
  287. if (NULL != pServer)
  288. {
  289. pServer->Release();
  290. }
  291. return(hr);
  292. }
  293. //+--------------------------------------------------------------------------
  294. // CCertExitSQLSample::Notify -- Notify the exit module of an event
  295. //
  296. // Returns S_OK.
  297. //+--------------------------------------------------------------------------
  298. STDMETHODIMP
  299. CCertExitSQLSample::Notify(
  300. /* [in] */ LONG ExitEvent,
  301. /* [in] */ LONG Context)
  302. {
  303. char *psz = "UNKNOWN EVENT";
  304. HRESULT hr = S_OK;
  305. switch (ExitEvent)
  306. {
  307. case EXITEVENT_CERTISSUED:
  308. hr = _NotifyNewCert(Context);
  309. psz = "certissued";
  310. break;
  311. case EXITEVENT_CERTPENDING:
  312. psz = "certpending";
  313. break;
  314. case EXITEVENT_CERTDENIED:
  315. psz = "certdenied";
  316. break;
  317. case EXITEVENT_CERTREVOKED:
  318. psz = "certrevoked";
  319. break;
  320. case EXITEVENT_CERTRETRIEVEPENDING:
  321. psz = "retrievepending";
  322. break;
  323. case EXITEVENT_CRLISSUED:
  324. psz = "crlissued";
  325. break;
  326. case EXITEVENT_SHUTDOWN:
  327. psz = "shutdown";
  328. break;
  329. }
  330. DBGPRINT((
  331. fDebug,
  332. "Exit:Notify(%hs=%x, ctx=%u) rc=%x\n",
  333. psz,
  334. ExitEvent,
  335. Context,
  336. hr));
  337. return(hr);
  338. }
  339. STDMETHODIMP
  340. CCertExitSQLSample::GetDescription(
  341. /* [retval][out] */ BSTR *pstrDescription)
  342. {
  343. HRESULT hr = S_OK;
  344. WCHAR sz[MAX_PATH];
  345. assert(wcslen(wsz_SAMPLE_DESCRIPTION) < ARRAYSIZE(sz));
  346. wcscpy(sz, wsz_SAMPLE_DESCRIPTION);
  347. *pstrDescription = SysAllocString(sz);
  348. if (NULL == *pstrDescription)
  349. {
  350. hr = E_OUTOFMEMORY;
  351. _JumpError(hr, error, "Exit:SysAllocString");
  352. }
  353. error:
  354. return(hr);
  355. }
  356. /////////////////////////////////////////////////////////////////////////////
  357. //
  358. STDMETHODIMP
  359. CCertExitSQLSample::InterfaceSupportsErrorInfo(REFIID riid)
  360. {
  361. int i;
  362. static const IID *arr[] =
  363. {
  364. &IID_ICertExit,
  365. };
  366. for (i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
  367. {
  368. if (IsEqualGUID(*arr[i],riid))
  369. {
  370. return(S_OK);
  371. }
  372. }
  373. return(S_FALSE);
  374. }
  375. HRESULT
  376. CCertExitSQLSample::ExitModSetODBCProperty(
  377. IN DWORD dwReqId,
  378. IN LPWSTR pszCAName,
  379. IN LPWSTR pszRequester,
  380. IN LPWSTR pszCertType,
  381. IN FILETIME* pftBefore,
  382. IN FILETIME* pftAfter)
  383. {
  384. SQLRETURN retcode;
  385. HRESULT hr = S_OK;
  386. SQLHSTMT hstmt1 = SQL_NULL_HSTMT;
  387. SQLWCHAR* pszStatement = NULL;
  388. SYSTEMTIME stTmp;
  389. SQL_TIMESTAMP_STRUCT dateValidFrom, dateValidTo;
  390. SQLINTEGER cValidFrom=sizeof(dateValidFrom), cValidTo =sizeof(dateValidTo);
  391. static WCHAR szSQLInsertStmt[] = L"INSERT INTO OutstandingCertificates (CAName, RequestID, RequesterName, CertType, validFrom, validTo) VALUES (\'%ws\', %d, \'%ws\', \'%ws\', ?, ?)";
  392. // temporarily fix NULL to ""
  393. if (NULL == pszCAName)
  394. pszCAName = L"";
  395. if (NULL == pszRequester)
  396. pszRequester = L"";
  397. if (NULL == pszCertType)
  398. pszCertType = L"";
  399. // Allocate a statement handle.
  400. retcode = SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc1, &hstmt1);
  401. if (!SQL_SUCCEEDED(retcode))
  402. goto error;
  403. // Bind the parameter.
  404. retcode = SQLBindParameter(hstmt1, 1, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 0, 0,
  405. &dateValidFrom, 0, &cValidFrom);
  406. if (!SQL_SUCCEEDED(retcode))
  407. goto error;
  408. retcode = SQLBindParameter(hstmt1, 2, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 0, 0,
  409. &dateValidTo, 0, &cValidTo);
  410. if (!SQL_SUCCEEDED(retcode))
  411. goto error;
  412. // Place the valid from date in the dsOpenDate structure.
  413. if (!FileTimeToSystemTime(pftBefore, &stTmp))
  414. {
  415. hr = GetLastError();
  416. hr = HRESULT_FROM_WIN32(hr);
  417. _JumpError(hr, error, "FileTimeToSystemTime");
  418. }
  419. dateValidFrom.year = stTmp.wYear;
  420. dateValidFrom.month = stTmp.wMonth;
  421. dateValidFrom.day = stTmp.wDay;
  422. dateValidFrom.hour = stTmp.wHour;
  423. dateValidFrom.minute = stTmp.wMinute;
  424. dateValidFrom.second = stTmp.wSecond;
  425. // Place the valid to date in the dsOpenDate structure.
  426. if (!FileTimeToSystemTime(pftAfter, &stTmp))
  427. {
  428. hr = GetLastError();
  429. hr = HRESULT_FROM_WIN32(hr);
  430. _JumpError(hr, error, "FileTimeToSystemTime");
  431. }
  432. dateValidTo.year = stTmp.wYear;
  433. dateValidTo.month = stTmp.wMonth;
  434. dateValidTo.day = stTmp.wDay;
  435. dateValidTo.hour = stTmp.wHour;
  436. dateValidTo.minute = stTmp.wMinute;
  437. dateValidTo.second = stTmp.wSecond;
  438. // Build INSERT statement.
  439. pszStatement = (SQLWCHAR*) LocalAlloc(LMEM_FIXED, (sizeof(szSQLInsertStmt)+wcslen(pszCAName)+wcslen(pszRequester)+wcslen(pszCertType)+15 +1) *2);
  440. if (NULL == pszStatement)
  441. {
  442. hr = E_OUTOFMEMORY;
  443. goto error;
  444. }
  445. wsprintf(pszStatement, szSQLInsertStmt, pszCAName, dwReqId, pszRequester, pszCertType);
  446. //OutputDebugStringW(pszStatement);
  447. // Execute an SQL statement directly on the statement handle.
  448. // Uses a default result set because no cursor attributes are set.
  449. retcode = SQLExecDirect(hstmt1, pszStatement, SQL_NTS);
  450. if (!SQL_SUCCEEDED(retcode))
  451. goto error;
  452. error:
  453. /* Clean up. */
  454. if (NULL != pszStatement)
  455. LocalFree(pszStatement);
  456. if (SQL_NULL_HSTMT != hstmt1)
  457. SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
  458. if (!SQL_SUCCEEDED(retcode))
  459. hr = ERROR_BAD_QUERY_SYNTAX;
  460. return (hr);
  461. }