rendered paste body// This is the main DLL file.#include "stdafx.h"#include <stdio.h>#include <string>#include <atlbase.h>#include "PasswordFilter.h"using namespace std;#define LOGFILE "c:\\users\\admin\\FilterLog.txt"#define PASSWD_FLTR_REG_KEY "SYSTEM\\CurrentControlSet\\Control\\Lsa\\passwordfilter"#define REG_VALUE_MAX_LEN 256// Default DllMain implementationBOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE;}void WriteToLog(const char* str){ if (NULL == str) { return; } return; FILE* log; log = fopen(LOGFILE, "a+"); if (NULL == log) { return; } fprintf(log, "%s\r\n", str); fclose(log); return;}char *escape_slashes(char *str){ int count = 0; unsigned int i; int j=0; char *ret; for(i=0;i<strlen(str);i++) if(str[i]=='\\') count++; ret = (char *) calloc(1, strlen(str)+count+1); for(i=0; i<strlen(str); i++) { if(str[i]=='\\') ret[j++]='\\'; ret[j++]=str[i]; } return ret;}/////////////////////////////////////////////// Exported function// -----------------// Initialization of Password filter.// This implementation just returns TRUE// to let LSA know everything is fineBOOLEAN __stdcall InitializeChangeNotify(void){ return TRUE;}////////////////////////////////////////////// Exported function// -----------------// This function is called by LSA when password// was successfully changed.//// This implementation just returns 0 (Success)NTSTATUS __stdcall PasswordChangeNotify( PUNICODE_STRING usernameUniStr, ULONG RelativeId, PUNICODE_STRING passwordUniStr ){ WriteToLog("InitializeChangeNotify()"); ConfigStruct c; char *username, *password; char *lpBuf, *urlencodedStr=NULL; DWORD NumberOfBytesWritten = 0; DWORD HeapSize; DWORD exitCode = 0; DWORD ret, readRetVal; DWORD szBufSize = REG_VALUE_MAX_LEN; HKEY hk; STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; CHAR szBuf[REG_VALUE_MAX_LEN+1];/** searching for the key in registry*/ if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, PASSWD_FLTR_REG_KEY, 0, KEY_QUERY_VALUE, &hk) != ERROR_SUCCESS ) { return 1; }/** reading value for workindir*/ readRetVal = RegQueryValueEx(hk, "workingdir", NULL, NULL, (LPBYTE)szBuf, &szBufSize); if( readRetVal != ERROR_SUCCESS ) { return 1; } c.workingDir = escape_slashes(szBuf); memset(szBuf, 0, sizeof(szBuf)); szBufSize = REG_VALUE_MAX_LEN;/** reading value for interpreter pass*/ readRetVal = RegQueryValueEx(hk, "interpreterpath", NULL, NULL, (LPBYTE)szBuf, &szBufSize); if( readRetVal != ERROR_SUCCESS ) { return 1; } c.postChangeProg = escape_slashes(szBuf); memset(szBuf, 0, sizeof(szBuf)); szBufSize = REG_VALUE_MAX_LEN;/** reading value for interpreter args (actual script name)*/ readRetVal = RegQueryValueEx(hk, "args", NULL, NULL, (LPBYTE)szBuf, &szBufSize); if( readRetVal != ERROR_SUCCESS ) { return 1; } c.postChangeProgArgs = escape_slashes(szBuf); memset(szBuf, 0, sizeof(szBuf)); szBufSize = REG_VALUE_MAX_LEN; c.postChangeProgWait = 0; username = (char*) calloc(1, (usernameUniStr->Length/2)+1); password = (char*) calloc(1, (passwordUniStr->Length/2)+1); WriteToLog("step1"); wcstombs(username, usernameUniStr->Buffer, (usernameUniStr->Length/2)); wcstombs(password, passwordUniStr->Buffer, (passwordUniStr->Length/2)); WriteToLog(username); WriteToLog(password); /* If no command is specified, say that we succeeded */ WriteToLog("step2"); if( strlen(c.postChangeProg) == 0 && strlen(c.postChangeProgArgs) == 0 ) return 0; WriteToLog("step3"); HeapSize = strlen(username) + strlen(password) + strlen(c.postChangeProg) + strlen(c.postChangeProgArgs) + 32; WriteToLog("step4"); memset( &si, 0, sizeof(si) ); memset( &pi, 0, sizeof(pi) ); memset( &sa, 0, sizeof(sa) ); si.cb = sizeof(si); WriteToLog("step5"); if( c.inheritParentHandles ) { si.dwFlags |= STARTF_USESTDHANDLES; si.hStdOutput = c.hChildSTDOUT; si.hStdError = c.hChildSTDERR; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; } WriteToLog("step6"); lpBuf = (char *) calloc(1, HeapSize); memset( lpBuf, 0, HeapSize ); WriteToLog("step6.5"); _snprintf(lpBuf, HeapSize -1, "\"%s\" %s %s %s", c.postChangeProg, c.postChangeProgArgs, username, password ); WriteToLog("step7"); memset(username, 0, strlen(username)); memset(password, 0, strlen(password)); free(username); free(password); WriteToLog("step8"); ret = CreateProcess( NULL, lpBuf, NULL, NULL, FALSE, 0, NULL, c.workingDir, &si, &pi ); /* if we fail and we care about printing errors ** then do it */ if( ! ret ) { char *fm_buf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &fm_buf, 0, NULL ); WriteToLog(fm_buf ); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); return 1; } memset(lpBuf, 0, HeapSize); free(lpBuf); WriteToLog("step11"); /* Wait for the process the alotted time */ ret = WaitForSingleObject( pi.hProcess, c.postChangeProgWait ); if( ret == WAIT_FAILED ) { WriteToLog("step12"); return 1; } else if( ret == WAIT_TIMEOUT ) { WriteToLog("step13"); return 1; } WriteToLog("step14"); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); WriteToLog("step15"); return 0;}////////////////////////////////////////////// Exported function// -----------------// This function actually validates// a new password.// LSA calls this function when a password is assign to a new user// or password is changed on exisiting user.// // This function return TRUE is password meets requirements// that filter checks; FALSE is password does NOT meet these requirements//// In our implementation, specified Regular Expression must match new passwordBOOLEAN __stdcall PasswordFilter( PUNICODE_STRING AccountName, PUNICODE_STRING FullName, PUNICODE_STRING Password, BOOLEAN SetOperation){ return TRUE;}