windows-nt/Source/XPSP1/NT/ds/security/gina/msgina/authmon.cxx
2020-09-26 16:20:57 +08:00

863 lines
18 KiB
C++

#ifdef SMARTCARD_DOGFOOD
#include "msgina.h"
#include <stdio.h>
#include <Wincrypt.h>
#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