#ifdef SMARTCARD_DOGFOOD #include "msgina.h" #include #include #include "tchar.h" #include "authmon.h" #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) _DebugPrint a void __cdecl _DebugPrint( LPCTSTR szFormat, ... ) { TCHAR szBuffer[512]; va_list ap; va_start(ap, szFormat); _vstprintf(szBuffer, szFormat, ap); OutputDebugString(szBuffer); } int debugLine = __LINE__; #define DEBUG_MARKER debugLine = __LINE__ #else #define DebugPrint(a) #define DEBUG_MARKER #endif typedef struct _AUTH_DATA { HANDLE hHeap; BOOL bConsole; WCHAR szUser[64]; AUTH_OPERATION AuthOperation; WCHAR szReader[32]; WCHAR szCard[48]; ULONG StopWatch; NTSTATUS Status; WCHAR szDomain[32]; WCHAR szDC[32]; BYTE pCertBlob[4096]; ULONG uCertBlob; SQLWCHAR szSQLServer[64]; SQLWCHAR szSQLUser[64]; SQLWCHAR szSQLPassword[64]; SQLWCHAR szSQLDatabase[64]; } AUTH_DATA, *PAUTH_DATA; DWORD WINAPI WriteLogonData( PAUTH_DATA pAuthData ) { SQLRETURN RetCode = SQL_SUCCESS; HSTMT hStmt = NULL; HENV hEnv = NULL, hDbc = NULL; BOOL bConnected = FALSE; SQLSMALLINT cbConnect = 0; static SQLWCHAR szConnect[256], szInConnect[256]; __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; } _snwprintf( szInConnect, sizeof(szInConnect) / sizeof(SQLWCHAR), (const wchar_t *) L"DRIVER=SQL Server;Server=%s;UID=%s;PWD=%s;DATABASE=%s", pAuthData->szSQLServer, pAuthData->szSQLUser, pAuthData->szSQLPassword, pAuthData->szSQLDatabase ); RetCode = SQLDriverConnect( hDbc, NULL, szInConnect, SQL_NTS, szConnect, sizeof(szConnect) / sizeof(szConnect[0]), &cbConnect, SQL_DRIVER_NOPROMPT ); if(!SQL_CALL_SUCCESS(RetCode)) { DEBUG_MARKER; __leave; } bConnected = TRUE; RetCode = SQLAllocHandle( SQL_HANDLE_STMT, hDbc, &hStmt ); if(!SQL_CALL_SUCCESS(RetCode)) { DEBUG_MARKER; __leave; } static WCHAR szStatement[] = L"INSERT INTO AuthMonitor (" L"BUILDLAB," L"CARD," L"CERTISSUER," L"DC," L"DOMAIN," L"MACHINENAME," L"READER," L"SESSION," L"STATUS," L"STOPWATCH," L"TIMESTAMP," L"UNLOCK," L"USERNAME" L") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"; RetCode = SQLPrepare( hStmt, szStatement, SQL_NTS ); if(!SQL_CALL_SUCCESS(RetCode)) { DEBUG_MARKER; __leave; } SQLUSMALLINT iParamNo = 1; // // BUILDLAB // HKEY hKey; DWORD dwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey ); static WCHAR szBuild[MAX_PATH]; DWORD cbBuild = sizeof(szBuild); wcscpy(szBuild, L""); if (dwStatus == ERROR_SUCCESS) { DWORD dwType = REG_SZ; dwStatus = RegQueryValueEx( hKey, L"BuildLab", 0, &dwType, (LPBYTE) szBuild, &cbBuild ); if (dwStatus != ERROR_SUCCESS) { dwStatus = RegQueryValueEx( hKey, L"CurrentBuildNumber", 0, &dwType, (LPBYTE) szBuild, &cbBuild ); } RegCloseKey(hKey); } SQLLEN cbBuildLab = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 64, 0, szBuild, 0, &cbBuildLab ); // // CARD // SQLLEN cbCard = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 48, 0, pAuthData->szCard, 0, &cbCard ); // // CERTISSUER // PCERT_CONTEXT pCert = (PCERT_CONTEXT) CertCreateCertificateContext( X509_ASN_ENCODING, pAuthData->pCertBlob, pAuthData->uCertBlob ); WCHAR szIssuer[64] = L""; if (pCert) { // intentionally ignore errors CertGetNameString( pCert, CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, szIssuer, sizeof(szIssuer) / sizeof(szIssuer[0]) ); CertFreeCertificateContext(pCert); } SQLLEN cbIssuer = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 64, 0, szIssuer, 0, &cbIssuer ); // // DC // PDOMAIN_CONTROLLER_INFO pDCInfo = NULL; dwStatus = DsGetDcName( NULL, pAuthData->szDomain, NULL, NULL, DS_IS_FLAT_NAME | DS_RETURN_FLAT_NAME, &pDCInfo ); static WCHAR szDC[MAX_PATH]; wcscpy(szDC, L""); static WCHAR szDomain[sizeof(pAuthData->szDomain)]; wcscpy(szDomain, L""); if (dwStatus == ERROR_SUCCESS) { wcscpy(szDC, pDCInfo->DomainControllerName); wcscpy(szDomain, pDCInfo->DomainName); NetApiBufferFree(pDCInfo); } SQLLEN cbDC = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 32, 0, szDC, 0, &cbDC ); // // DOMAIN // if (pAuthData->szDomain[0] == L'\0') { PWCHAR pszPos; if (pszPos = wcschr(pAuthData->szUser, L'@')) { wcscpy(szDomain, pszPos + 1); if (pszPos = wcschr(szDomain, L'.')) { *pszPos = L'\0'; } } } else { wcscpy(szDomain, pAuthData->szDomain); } SQLLEN cbDomain = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 32, 0, szDomain, 0, &cbDomain ); // // MACHINENAME // static WCHAR szMachineName[MAX_PATH]; wcscpy(szMachineName, L""); DWORD dwMachineName = sizeof(szMachineName)/sizeof(szMachineName[0]); // intentionally ignore any failures GetComputerNameEx( ComputerNameDnsHostname, szMachineName, &dwMachineName ); SQLLEN cbMachineName = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 64, 0, szMachineName, 0, &cbMachineName ); // // READER // SQLLEN cbReader = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 32, 0, pAuthData->szReader, 0, &cbReader ); // // SESSION // SQLLEN cbSession = 0; BOOL bSession = !pAuthData->bConsole; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_SMALLINT, 0, 0, &bSession, 0, &cbSession ); // // STATUS // SQLLEN cbStatus = 0; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &pAuthData->Status, 0, &cbStatus ); // // STOPWATCH // SQLLEN cbStopWatch = 0; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &pAuthData->StopWatch, 0, &cbStopWatch ); // // TIMESTAMP // TIMESTAMP_STRUCT TimeStamp; SYSTEMTIME SystemTime; GetLocalTime(&SystemTime); TimeStamp.day = SystemTime.wDay; TimeStamp.month = SystemTime.wMonth; TimeStamp.year = SystemTime.wYear; TimeStamp.hour = SystemTime.wHour; TimeStamp.minute = SystemTime.wMinute; TimeStamp.second = SystemTime.wSecond; TimeStamp.fraction = 0; SQLLEN cbTimeStamp = 0; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 19, 0, &TimeStamp, 0, &cbTimeStamp ); // // UNLOCK // SQLLEN cbAuthOperation = 0; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_SMALLINT, 0, 0, &pAuthData->AuthOperation, 0, &cbAuthOperation ); // // USERNAME // static WCHAR szUser[sizeof(pAuthData->szUser)]; wcscpy(szUser, pAuthData->szUser); if (PWCHAR pszPos = wcschr(szUser, L'@')) { *pszPos = L'\0'; } SQLLEN cbUserName = SQL_NTS; SQLBindParameter( hStmt, iParamNo++, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 64, 0, szUser, 0, &cbUserName ); RetCode = SQLExecute(hStmt); DEBUG_MARKER; } __finally { } if (!SQL_CALL_SUCCESS(RetCode)) { SDWORD swError; static SQLWCHAR szErrorMsg[SQL_MAX_MESSAGE_LENGTH]; SWORD swErrorMsg; SQLWCHAR szSQLState[50]; SQLError( hEnv, hDbc, hStmt, szSQLState, &swError, szErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &swErrorMsg ); DebugPrint( (L"AuthMonitor: Error WriteLogonData (%d) - %s (%s)\n [%s]", debugLine, szErrorMsg, szSQLState, szInConnect) ); } if (hStmt) { SQLFreeHandle(SQL_HANDLE_STMT, hStmt); hStmt = NULL; } if (hDbc) { if (bConnected) { SQLDisconnect(hDbc); bConnected = FALSE; } SQLFreeHandle(SQL_HANDLE_DBC, hDbc); hDbc = NULL; } if (hEnv) { SQLFreeHandle(SQL_HANDLE_ENV, hEnv); hEnv = NULL; } HeapFree(pAuthData->hHeap, 0, pAuthData); DebugPrint( (L"AuthMonitor: WriteLogonData %s\n", (SQL_CALL_SUCCESS(RetCode) ? L"succeeded" : L"failed")) ); return 0; } EXTERN_C HANDLE AuthMonitor( AUTH_OPERATION AuthOper, BOOL Console, PUNICODE_STRING User, PUNICODE_STRING Domain, PWSTR Card, PWSTR Reader, PKERB_SMART_CARD_PROFILE Profile, DWORD Timer, NTSTATUS Status ) { PAUTH_DATA pAuthData = NULL; HANDLE hHeap = NULL; HANDLE hThread = NULL; HKEY hKey = NULL; LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Policies\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), 0, KEY_READ, &hKey ); if (lResult != ERROR_SUCCESS) { return NULL; } __try { DWORD dwSize, dwType, dwEnabled = 0; dwSize = sizeof(dwEnabled); lResult = RegQueryValueEx( hKey, TEXT("AuthMonEnabled"), 0, &dwType, (PBYTE) &dwEnabled, &dwSize ); if (lResult != ERROR_SUCCESS || dwType != REG_DWORD || dwEnabled == 0) { DEBUG_MARKER; __leave; } hHeap = GetProcessHeap(); if (hHeap == NULL) { DEBUG_MARKER; __leave; } pAuthData = (PAUTH_DATA) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(AUTH_DATA)); if (pAuthData == NULL) { DEBUG_MARKER; __leave; } dwSize = sizeof(pAuthData->szSQLServer); lResult = RegQueryValueEx( hKey, TEXT("AuthMonServer"), 0, &dwType, (PBYTE) &pAuthData->szSQLServer, &dwSize ); if (lResult != ERROR_SUCCESS || dwType != REG_SZ) { DEBUG_MARKER; __leave; } dwSize = sizeof(pAuthData->szSQLUser); lResult = RegQueryValueEx( hKey, TEXT("AuthMonUser"), 0, &dwType, (PBYTE) &pAuthData->szSQLUser, &dwSize ); if (lResult != ERROR_SUCCESS || dwType != REG_SZ) { DEBUG_MARKER; __leave; } dwSize = sizeof(pAuthData->szSQLPassword); lResult = RegQueryValueEx( hKey, TEXT("AuthMonPassword"), 0, &dwType, (PBYTE) &pAuthData->szSQLPassword, &dwSize ); if (lResult != ERROR_SUCCESS || dwType != REG_SZ) { DEBUG_MARKER; __leave; } dwSize = sizeof(pAuthData->szSQLDatabase); lResult = RegQueryValueEx( hKey, TEXT("AuthMonDatabase"), 0, &dwType, (PBYTE) &pAuthData->szSQLDatabase, &dwSize ); if (lResult != ERROR_SUCCESS || dwType != REG_SZ) { DEBUG_MARKER; __leave; } pAuthData->hHeap = hHeap; pAuthData->AuthOperation = AuthOper; pAuthData->bConsole = Console; memcpy(pAuthData->szDomain, Domain->Buffer, Domain->Length); memcpy(pAuthData->szUser, User->Buffer, User->Length); if (Card) { wcscpy(pAuthData->szCard, Card); } if (Reader) { wcscpy(pAuthData->szReader, Reader); } if (Profile && Profile->CertificateData && (Profile->CertificateSize < sizeof(pAuthData->pCertBlob))) { memcpy( pAuthData->pCertBlob, Profile->CertificateData, Profile->CertificateSize ); pAuthData->uCertBlob = Profile->CertificateSize; } pAuthData->StopWatch = Timer; pAuthData->Status = Status; hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) WriteLogonData, pAuthData, 0, NULL ); DEBUG_MARKER; } __finally { if (hKey) { RegCloseKey(hKey); } if (hThread == NULL) { if (pAuthData) { HeapFree(hHeap, 0, pAuthData); } DebugPrint((L"AuthMonitor: Error line %d\n", debugLine)); } #ifndef TEST else { CloseHandle(hThread); hThread = NULL; } #endif } return hThread; } #ifdef TEST _cdecl main() { UNICODE_STRING Domain, User; HANDLE hThread = NULL; RtlInitUnicodeString( &Domain, L"" ); RtlInitUnicodeString( &User, L"Klaus" ); hThread = AuthMonitor( AuthOperLogon, 0, &User, &Domain, L"Gemplus", L"Utimaco", NULL, 10, 0 ); if (hThread) { WaitForSingleObjectEx(hThread, INFINITE, FALSE); } } #endif #endif