//+------------------------------------------------------------------------- // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1995 - 1999 // // File: dblog.cpp // // Contents: Database Log Event APIs // // Functions: I_DBLogCrypt32Event // I_DBLogAttach // I_DBLogDetach // // History: 11-Oct-00 philh created //-------------------------------------------------------------------------- #include "global.hxx" #include #ifdef ROOT_AUTO_UPDATE_DOGFOOD #ifdef STATIC #undef STATIC #endif #define STATIC #include "sql.h" #include "sqlext.h" #include "sqltypes.h" #include "odbcss.h" #define SQL_CALL_SUCCESS(status) (status == SQL_SUCCESS || status == SQL_SUCCESS_WITH_INFO) #if DBG || DEBUG #define DebugPrint(a) _DebugPrintW a void __cdecl _DebugPrintW( LPCWSTR szFormat, ... ) { WCHAR szBuffer[512]; va_list ap; va_start(ap, szFormat); vswprintf(szBuffer, szFormat, ap); OutputDebugStringW(szBuffer); } int debugLine = __LINE__; #define DEBUG_MARKER debugLine = __LINE__ #else #define DebugPrint(a) #define DEBUG_MARKER #endif #define SHA1_HASH_LEN 20 #define SHA1_HASH_NAME_LEN (2 * SHA1_HASH_LEN) typedef struct _DBLOG_EVENT_DATA { DWORD dwStatus; DWORD dwCPU64; TIMESTAMP_STRUCT TimeStamp; WCHAR wszOperation[16]; WCHAR wszHash[SHA1_HASH_NAME_LEN + 1]; WCHAR wszSubject[64]; WCHAR wszBuildLab[64]; WCHAR wszMachineName[32]; } DBLOG_EVENT_DATA, *PDBLOG_EVENT_DATA; void I_DBLogAttach() { } void I_DBLogDetach() { } DWORD WINAPI I_DBLogCrypt32EventThreadProc( LPVOID lpThreadParameter ) { PDBLOG_EVENT_DATA pEventData = (PDBLOG_EVENT_DATA) lpThreadParameter; SQLRETURN RetCode = SQL_SUCCESS; HSTMT hStmt = NULL; HENV hEnv = NULL, hDbc = NULL; __try { __try { RetCode = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv ); if(!SQL_CALL_SUCCESS(RetCode)) { DEBUG_MARKER; __leave; } RetCode = SQLSetEnvAttr( hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER ); if(!SQL_CALL_SUCCESS(RetCode)) { DEBUG_MARKER; __leave; } RetCode = SQLAllocHandle( SQL_HANDLE_DBC, hEnv, &hDbc ); if(!SQL_CALL_SUCCESS(RetCode)) { DEBUG_MARKER; __leave; } RetCode = SQLSetConnectAttr( hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) 120, SQL_IS_UINTEGER ); if(!SQL_CALL_SUCCESS(RetCode)) { DEBUG_MARKER; __leave; } RetCode = SQLSetConnectAttr( hDbc, SQL_COPT_SS_INTEGRATED_SECURITY, (SQLPOINTER) SQL_IS_OFF, SQL_IS_INTEGER ); if(!SQL_CALL_SUCCESS(RetCode)) { DEBUG_MARKER; __leave; } { SQLWCHAR szConnect[1024]; SQLSMALLINT cbConnect = 0; SQLWCHAR szInConnect[] = L"DRIVER=SQL Server;SERVER=kschutz-team2;UID=crypt32;PWD=crypt32;DATABASE=Crypt32"; RetCode = SQLDriverConnectW( hDbc, NULL, szInConnect, SQL_NTS, szConnect, sizeof(szConnect) / sizeof(szConnect[0]), &cbConnect, SQL_DRIVER_NOPROMPT ); if(!SQL_CALL_SUCCESS(RetCode)) { DEBUG_MARKER; __leave; } } RetCode = SQLAllocHandle( SQL_HANDLE_STMT, hDbc, &hStmt ); if(!SQL_CALL_SUCCESS(RetCode)) { DEBUG_MARKER; __leave; } WCHAR szStatement[] = L"INSERT INTO AddRoot2 (" L"OPERATION," L"STATUS," L"TIMESTAMP," L"HASH," L"SUBJECT," L"MACHINENAME," L"BUILDLAB," L"CPU64" L") VALUES (?,?,?,?,?,?,?,?)"; RetCode = SQLPrepareW( hStmt, szStatement, SQL_NTS ); if(!SQL_CALL_SUCCESS(RetCode)) { DEBUG_MARKER; __leave; } SQLUSMALLINT iParamNo = 1; // // OPERATION // SQLLEN cbOperation = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, sizeof(pEventData->wszOperation) / sizeof(WCHAR), 0, pEventData->wszOperation, 0, &cbOperation ); // // STATUS // SQLLEN cbStatus = 0; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &pEventData->dwStatus, 0, &cbStatus ); // // TIMESTAMP // SQLLEN cbTimeStamp = 0; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 19, 0, &pEventData->TimeStamp, 0, &cbTimeStamp ); // // HASH // SQLLEN cbHash = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, sizeof(pEventData->wszHash) / sizeof(WCHAR), 0, pEventData->wszHash, 0, &cbHash ); // // SUBJECT // SQLLEN cbSubject = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, sizeof(pEventData->wszSubject) / sizeof(WCHAR), 0, pEventData->wszSubject, 0, &cbSubject ); // // MACHINENAME // SQLLEN cbMachineName = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, sizeof(pEventData->wszMachineName) / sizeof(WCHAR), 0, pEventData->wszMachineName, 0, &cbMachineName ); // // BUILDLAB // SQLLEN cbBuildLab = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, sizeof(pEventData->wszBuildLab) / sizeof(WCHAR), 0, pEventData->wszBuildLab, 0, &cbBuildLab ); // // CPU64 // SQLLEN cbCPU64 = 0; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_TINYINT, 0, 0, &pEventData->dwCPU64, 0, &cbCPU64 ); RetCode = SQLExecute(hStmt); DEBUG_MARKER; } __finally { } if (!SQL_CALL_SUCCESS(RetCode)) { SDWORD swError; SQLWCHAR szErrorMsg[SQL_MAX_MESSAGE_LENGTH]; SWORD swErrorMsg; SQLWCHAR szSQLState[50]; SQLErrorW( hEnv, hDbc, hStmt, szSQLState, &swError, szErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &swErrorMsg ); DebugPrint( (L"I_DBLogCrypt32EventThreadProc: Error (%d) - %s (%s)\n", debugLine, szErrorMsg, szSQLState) ); } if (hStmt) { SQLFreeHandle(SQL_HANDLE_STMT, hStmt); } if (hDbc) { SQLDisconnect(hDbc); SQLFreeHandle(SQL_HANDLE_DBC, hDbc); } if (hEnv) { SQLFreeHandle(SQL_HANDLE_ENV, hEnv); } } __except(EXCEPTION_EXECUTE_HANDLER) { DebugPrint( (L"I_DBLogCrypt32EventThreadProc: Exception Error (%d)\n", GetExceptionCode()) ); RetCode = SQL_ERROR; } PkiFree(pEventData); DebugPrint( (L"I_DBLogCrypt32EventThreadProc %s\n", (SQL_CALL_SUCCESS(RetCode) ? L"succeeded" : L"failed")) ); return 0; } void I_DBLogCrypt32Event( IN WORD wType, IN DWORD dwEventID, IN WORD wNumStrings, IN LPCWSTR *rgpwszStrings ) { PDBLOG_EVENT_DATA pEventData = NULL; HANDLE hThread = NULL; if (NULL == (pEventData = (PDBLOG_EVENT_DATA) PkiZeroAlloc( sizeof(DBLOG_EVENT_DATA)))) goto OutOfMemory; switch (dwEventID) { case MSG_ROOT_AUTO_UPDATE_INFORMATIONAL: case MSG_UNTRUSTED_ROOT_INFORMATIONAL: case MSG_PARTIAL_CHAIN_INFORMATIONAL: switch (dwEventID) { case MSG_ROOT_AUTO_UPDATE_INFORMATIONAL: // Successful auto update of third-party root certificate:: // Subject: <%1> Sha1 thumbprint: <%2> wcscpy(pEventData->wszOperation, L"AddCert"); break; case MSG_UNTRUSTED_ROOT_INFORMATIONAL: // Untrusted root certificate:: Subject: <%1> // Sha1 thumbprint: <%2> wcscpy(pEventData->wszOperation, L"UntrustedRoot"); break; case MSG_PARTIAL_CHAIN_INFORMATIONAL: // Partial Chain:: Issuer: <%1> // Subject Sha1 thumbprint: <%2> wcscpy(pEventData->wszOperation, L"PartialChain"); break; } if (2 <= wNumStrings) { wcsncpy(pEventData->wszSubject, rgpwszStrings[0], sizeof(pEventData->wszSubject) / sizeof(WCHAR) - 1); wcsncpy(pEventData->wszHash, rgpwszStrings[1], sizeof(pEventData->wszHash) / sizeof(WCHAR) - 1); } break; case MSG_ROOT_LIST_AUTO_UPDATE_URL_RETRIEVAL_INFORMATIONAL: // Successful auto update of third-party root list cab from: <%1> case MSG_ROOT_LIST_AUTO_UPDATE_URL_RETRIEVAL_ERROR: // Failed auto update of third-party root list cab from: <%1> // with error: %2 wcscpy(pEventData->wszOperation, L"FetchCab"); break; case MSG_ROOT_LIST_AUTO_UPDATE_EXTRACT_ERROR: // Failed extract of third-party root list from auto update // cab at: <%1> with error: %2 wcscpy(pEventData->wszOperation, L"ExtractCtl"); break; case MSG_ROOT_CERT_AUTO_UPDATE_URL_RETRIEVAL_INFORMATIONAL: // Successful auto update of third-party root certificate from: <%1> case MSG_ROOT_CERT_AUTO_UPDATE_URL_RETRIEVAL_ERROR: // Failed auto update of third-party root certificate from: <%1> // with error: %2 wcscpy(pEventData->wszOperation, L"FetchCert"); // %1 contains // "RootDir" "/" "AsciiHexHash" ".cer" // for example, // "http://www.xyz.com/roots/216B2A29E62A00CE820146D8244141B92511B279.cer" { LPCWSTR pwszHash = rgpwszStrings[0]; DWORD cchHash; cchHash = wcslen(pwszHash); if ((SHA1_HASH_NAME_LEN + 4) <= cchHash) memcpy(pEventData->wszHash, pwszHash + (cchHash - (SHA1_HASH_NAME_LEN + 4)), SHA1_HASH_NAME_LEN * sizeof(WCHAR)); } break; case MSG_CRYPT32_EVENT_LOG_THRESHOLD_WARNING: // Reached crypt32 threshold of %1 events and will suspend // logging for %2 minutes wcscpy(pEventData->wszOperation, L"EventOverflow"); break; case MSG_ROOT_SEQUENCE_NUMBER_AUTO_UPDATE_URL_RETRIEVAL_INFORMATIONAL: // Successful auto update of third-party root list sequence // number from: <%1> case MSG_ROOT_SEQUENCE_NUMBER_AUTO_UPDATE_URL_RETRIEVAL_ERROR: // Failed auto update of third-party root list sequence number // from: <%1> with error: %2 wcscpy(pEventData->wszOperation, L"FetchSeq"); break; default: goto SkipDbLogCrypt32Event; } if (MSG_CRYPT32_EVENT_LOG_THRESHOLD_WARNING == dwEventID) pEventData->dwStatus = (DWORD) ERROR_BUFFER_OVERFLOW; else if (EVENTLOG_ERROR_TYPE == wType && 2 <= wNumStrings) // The second string should contain the error code string pEventData->dwStatus = (DWORD) wcstoul(rgpwszStrings[1], NULL, 0); { SYSTEMTIME SystemTime; GetLocalTime(&SystemTime); pEventData->TimeStamp.day = SystemTime.wDay; pEventData->TimeStamp.month = SystemTime.wMonth; pEventData->TimeStamp.year = SystemTime.wYear; pEventData->TimeStamp.hour = SystemTime.wHour; pEventData->TimeStamp.minute = SystemTime.wMinute; pEventData->TimeStamp.second = SystemTime.wSecond; // pEventData->TimeStamp.fraction = 0; } { WCHAR wszMachineName[MAX_PATH] = L""; DWORD cchMachineName = sizeof(wszMachineName) / sizeof(WCHAR); // intentionally ignore any failures GetComputerNameExW( ComputerNameDnsHostname, wszMachineName, &cchMachineName ); wcsncpy(pEventData->wszMachineName, wszMachineName, sizeof(pEventData->wszMachineName) / sizeof(WCHAR) - 1); } { HKEY hKey; WCHAR wszBuildLab[MAX_PATH]; DWORD dwStatus; wcscpy(wszBuildLab, L""); dwStatus = RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey ); if (dwStatus == ERROR_SUCCESS) { DWORD dwType = REG_SZ; DWORD cbBuildLab = sizeof(wszBuildLab); dwStatus = RegQueryValueExW( hKey, L"BuildLab", 0, &dwType, (LPBYTE) wszBuildLab, &cbBuildLab ); if (dwStatus != ERROR_SUCCESS) { dwType = REG_SZ; cbBuildLab = sizeof(wszBuildLab); dwStatus = RegQueryValueExW( hKey, L"CurrentBuildNumber", 0, &dwType, (LPBYTE) wszBuildLab, &cbBuildLab ); } RegCloseKey(hKey); } wcsncpy(pEventData->wszBuildLab, wszBuildLab, sizeof(pEventData->wszBuildLab) / sizeof(WCHAR) - 1); } #if defined(M_IA64) || defined(IA64) || defined(_IA64_) pEventData->dwCPU64 = 1; #endif // Create the thread to do the logging to the database if (NULL == (hThread = CreateThread( NULL, // lpThreadAttributes 0, // dwStackSize I_DBLogCrypt32EventThreadProc, pEventData, 0, // dwCreationFlags NULL // pdwThreadId ))) goto CreateThreadError; CloseHandle(hThread); CommonReturn: return; ErrorReturn: PkiFree(pEventData); goto CommonReturn; TRACE_ERROR(OutOfMemory) TRACE_ERROR(SkipDbLogCrypt32Event) TRACE_ERROR(CreateThreadError) } #else void I_DBLogAttach() { } void I_DBLogDetach() { } void I_DBLogCrypt32Event( IN WORD wType, IN DWORD dwEventID, IN WORD wNumStrings, IN LPCWSTR *rgpwszStrings ) { } #endif