www.pudn.com > warsrc.rar > NTSecurityExt.cpp
// NTSecurityExt.cpp : Defines the initialization routines for the DLL. // #include "stdafx.h" #include#include // Unicode API #include // Lan manager API #include "FTPDaemonCore.h" #include "NTSecurityExt.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif static AFX_EXTENSION_MODULE NTSecurityExtDLL = { NULL, NULL }; int CallOnPreFSYSAccess(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnPostFSYSAccess(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnGetSecurityDescriptor(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnConnect(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnReceive(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnSend(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnCommand(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnClose(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnSendCmd(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnSITECmd(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnIdle(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnVerifyIPAddress(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnVerifyUploadedFile(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnVerifyTransferRequest(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); int CallOnSocketIsDestroyed(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); //////////////////////////////////////// // ADDED: This is required for plugin's static CNTSecExt *pMe; extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { TRACE0("NTSECURITYEXT.DLL Initializing!\n"); // Extension DLL one-time initialization AfxInitExtensionModule(NTSecurityExtDLL, hInstance); // Insert this DLL into the resource chain new CDynLinkLibrary(NTSecurityExtDLL); //////////////////////////////////////// // ADDED: This is required for plugin's // Create, Register and set up the dll if (!IsNT()) { CLog *pLog = CLog::GetLog(); if (pLog) pLog->LogMsg(LOGF_ERROR,"CNTSecExt.dll can only run on NT systems."); return 0; // This module can only run on NT systems } pMe = new CNTSecExt; if (pMe->Register("NTSecurityExt") != 0) return 0; // Failure } else if (dwReason == DLL_PROCESS_DETACH) { //////////////////////////////////////// // ADDED: This is required for plugin's if (pMe) delete pMe; TRACE0("NTSECURITYEXT.DLL Terminating!\n"); } return 1; // ok } // Initialize the extended COptions variables void CNTSecExt::InitializeCOptions() { DeclOpt("NT User database", m_SystemName, " ", 1, DATATYPE_CSTRING); DeclOpt("Default FTP Access", m_DefaultFTPAccess, TRUE, 2, DATATYPE_BOOL); DeclOpt("Give NT Admins Admin", m_GiveAdminsAdmin, TRUE, 3, DATATYPE_BOOL); } CNTSecExt::CNTSecExt() { } CNTSecExt::~CNTSecExt() { } // Called when a user tries to log on. // What we do here is to check if the user exist in the // NT user database, and is member of the NT user group we have // reserved for War server users. // If the user exist and has login permissions in NT, we // create the user in the war user database (provided that it don't // already exist), and leave's the processessing to the default // implementation. We allow other plugins to process the login // reqest int CNTSecExt::OnLogin(int Event, WPARAM wParam, LPARAM lParam) { int Rval = CFuncList::OkContinue; LogMsg(LOGF_DEBUG, "CNTSecExt::OnLogin(): Called."); USER *pUser = (USER *)wParam; LOGINPRMS *pLP = (LOGINPRMS *)lParam; ASSERT(AfxIsValidAddress(pUser, sizeof(USER))); ASSERT(AfxIsValidAddress(pLP, sizeof(LOGINPRMS))); ASSERT(AfxIsValidString(pLP->UserID)); *pUser = CUsr::FindUser(UT_USER, pLP->UserID); *pUser = CUsr::MapUser(*pUser); LPWSTR NTSystemName = NULL; LPWSTR UserName; NET_API_STATUS rCode; USER_INFO_1 *pUserInfo1 = NULL; // We use the old Lan Manager API to get extended information. We could // use the new NT 3.51 security interafce, but I don't know how to extract // the home directory from that... // The good news is that we get most of the infromation we need. The bad // news is that we have to rewrite this code when NT 5 arrives... // Convert to unicode WORD wSNbuf[64]; WORD wUNbuf[64]; if (m_SystemName != " ") MultiByteToWideChar( CP_ACP, 0,m_SystemName,-1, NTSystemName = (LPWSTR)wSNbuf, sizeof(wSNbuf) / sizeof(WORD)); MultiByteToWideChar( CP_ACP, 0,pLP->UserID,-1, UserName = (LPWSTR)wUNbuf, sizeof(wUNbuf) / sizeof(WORD)); rCode = NetUserGetInfo( NTSystemName, UserName, 1, (LPBYTE *) &pUserInfo1); if (!rCode) { char HomeDir[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, pUserInfo1->usri1_home_dir, -1, HomeDir, MAX_PATH, NULL, NULL); // Check login permissions if (pUserInfo1->usri1_flags & (UF_ACCOUNTDISABLE | UF_LOCKOUT)) { // User has no access LogMsg(LOGF_SECURITY, "OnLogin(%s) - The user's NT account is disabled. Access is denied.", pLP->UserID); Rval = CFuncList::AbortError; goto done; } // Get the NT class USER Class = CUsr::FindUser(UT_CLASS,"(NT_Users)"); if (Class == INVALID_USER_VALUE) { // Create the NT user class! if ((Class = CUsr::AddUser(UT_CLASS,"(NT_Users)", TRUE)) == INVALID_USER_VALUE) { LogMsg(LOGF_SECURITY, "OnLogin(%s) - Failed to create class (NT_Users).", pLP->UserID); Rval = CFuncList::AbortError; goto done; } CUsr::SetParam(Class,"FTP Access", m_DefaultFTPAccess); } if (*pUser == INVALID_USER_VALUE) { // Create the user. We need a daemon user to store extra info if ((*pUser = CUsr::AddUser(UT_USER, pLP->UserID)) != INVALID_USER_VALUE) { LogMsg(LOGF_SYSTEM,"OnLogin(%s) - Created NT user entry in daemon user database.", pLP->UserID); } else { LogMsg(LOGF_WARNINGS, "OnLogin(%s) - The users NT account is OK. Failed to create server user.", pLP->UserID); Rval = CFuncList::AbortError; goto done; } CUsr::SetParam(*pUser,"FTP Access", m_DefaultFTPAccess); } LogMsg(LOGF_DEBUG,"OnLogin(%s) - Converting account to NT user style.", pLP->UserID); CUsr::SetParam(*pUser, "PWmode", PW_NORMAL); if (*HomeDir) CUsr::SetParam(*pUser, "Home", HomeDir); CUsr::SetParam(*pUser,"Class", Class); if (pUserInfo1->usri1_priv == USER_PRIV_ADMIN) { if (m_GiveAdminsAdmin) CUsr::SetParam(*pUser,"Administrator", TRUE); } else if (CUsr::IsAdmin(*pUser)) CUsr::SetParam(*pUser,"Administrator", FALSE); } else { switch(rCode) { case ERROR_ACCESS_DENIED: LogMsg(LOGF_DEBUG,"OnLogin(%s) - NetUserGetInfo() returned: ERROR_ACCESS_DENIED.", pLP->UserID); break; case NERR_InvalidComputer: LogMsg(LOGF_DEBUG,"OnLogin(%s) - NetUserGetInfo() returned: NERR_InvalidComputer.", pLP->UserID); break; case NERR_UserNotFound: LogMsg(LOGF_DEBUG,"OnLogin(%s) - NetUserGetInfo() returned: NERR_UserNotFound.", pLP->UserID); break; default: LogMsg(LOGF_DEBUG,"OnLogin(%s) - NetUserGetInfo() returned unexpected error code: %d. (%s)", pLP->UserID, rCode, GetLastErrorText(rCode)); break; } } done: if (*pUser != INVALID_USER_VALUE) CUsr::SetParam(*pUser, "NT User", (rCode == 0) && (Rval == CFuncList::OkContinue)); // Clean up if (pUserInfo1) NetApiBufferFree(pUserInfo1); return Rval; } int CNTSecExt::OnLogout(int Event, WPARAM wParam, LPARAM lParam) { int Rval = CFuncList::OkContinue; LogMsg(LOGF_DEBUG, "CNTSecExt::OnLogout(): Called."); CTextSock *pSock = (CTextSock *)lParam; DeleteNTProp(pSock); return Rval; } int CNTSecExt::OnPassword(int Event, WPARAM wParam, LPARAM lParam) { int Rval = CFuncList::OkContinue; LogMsg(LOGF_DEBUG, "CNTSecExt::OnPassword(): Called."); USER *pUser = (USER *)wParam; LOGINPRMS *pLP = (LOGINPRMS *)lParam; ASSERT(AfxIsValidAddress(pUser, sizeof(USER))); ASSERT(AfxIsValidAddress(pLP, sizeof(LOGINPRMS))); ASSERT(AfxIsValidString(pLP->UserID)); *pUser = CUsr::FindUser(UT_USER, pLP->UserID); *pUser = CUsr::MapUser(*pUser); HANDLE lh; // Delete any previous logon handle for this connection DeleteNTProp(pLP->Sock); if (CUsr::GetParam(*pUser, "NT User", FALSE)) { // Try to log the user on in NT char SysName[64]; DWORD len = sizeof(SysName); GetComputerName(SysName, &len); LPTSTR System = (LPTSTR) ((m_SystemName == " ") ? SysName : (LPCSTR)m_SystemName); if (LogonUser( (LPTSTR)pLP->UserID, System, (LPTSTR)pLP->Password, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &lh)) { // Store the logon handle for later use CNTProperties *pNT = new CNTProperties; pNT->hLogon = lh; pNT->pSock = pLP->Sock; m_NTprp.AddFirst((LPVOID)pNT); Rval = CFuncList::OkAllDone; LogMsg(LOGF_INOUT,"User %s logged on with NT password.", pLP->UserID); } else { int err = GetLastError(); if (err == ERROR_PRIVILEGE_NOT_HELD) { char AccessName[128] = SE_TCB_NAME; DWORD dw1, dw2; LookupPrivilegeDisplayName(NULL, SE_TCB_NAME, AccessName, &dw1, &dw2); LogMsg(LOGF_ERROR,"The user that run the FTP server must have '%s' access.", AccessName); } LogMsg(LOGF_DEBUG,"OnPassword(%s) - NT logon failed. Error: %s", pLP->UserID, GetLastErrorText(err)); Rval = CFuncList::AbortError; } } return Rval; } // Helper. Delete a NT property based on the connection socket void CNTSecExt::DeleteNTProp(CTextSock *pSock) { for(CLinkedListItem *Item = m_NTprp.First(); Item;) { CLinkedListItem *NextItem = m_NTprp.Next(Item); CNTProperties *pNT = (CNTProperties *)m_NTprp.Ptr(Item); if (pNT->pSock == pSock) { delete pNT; m_NTprp.DeleteItem(Item); } Item = NextItem; } } ///////////////////////////////////////////////////////////////////////////// // CNTFTPConn callbacks int CNTFTPConn::OnPreFSYSAccess(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnPostFSYSAccess(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnGetSecurityDescriptor(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnConnect(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnReceive(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnSend(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnCommand(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnClose(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnSendCmd(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnSITECmd(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnIdle(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnVerifyIPAddress(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnVerifyUploadedFile(int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CNTFTPConn::OnVerifyTransferRequest(int Event, WPARAM wParam, LPARAM lParam) { return 0; } // Raw callback support // Reqired function if sockets extentions are used // Creates a new socket derived int CallOnSocketIsDestroyed(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { delete (CNTFTPConn *)Origin; // CSocketAPI destructor will delete references return 0; } int CallOnPreFSYSAccess(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnPreFSYSAccess(Event, wParam, lParam); } int CallOnPostFSYSAccess(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnPostFSYSAccess(Event, wParam, lParam); } int CallOnGetSecurityDescriptor(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnGetSecurityDescriptor(Event, wParam, lParam); } int CallOnConnect(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnConnect(Event, wParam, lParam); } int CallOnReceive(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnReceive(Event, wParam, lParam); } int CallOnSend(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnSend(Event, wParam, lParam); } int CallOnCommand(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnCommand(Event, wParam, lParam); } int CallOnClose(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnClose(Event, wParam, lParam); } int CallOnSendCmd(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnSendCmd(Event, wParam, lParam); } int CallOnSITECmd(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnSITECmd(Event, wParam, lParam); } int CallOnIdle(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnIdle(Event, wParam, lParam); } int CallOnVerifyIPAddress(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnVerifyIPAddress(Event, wParam, lParam); } int CallOnVerifyUploadedFile(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnVerifyUploadedFile(Event, wParam, lParam); } int CallOnVerifyTransferRequest(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTFTPConn *)Origin)->OnVerifyTransferRequest(Event, wParam, lParam); } ///////////////////////////////////////////////////////////////////////////// // Helper (entry point functions) // This is the fuction's the server looks for and calls. These must call our own // functions that do the actual work. int CallOnLogin(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTSecExt *)Origin)->OnLogin(Event, wParam, lParam); } int CallOnLogout(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTSecExt *)Origin)->OnLogout(Event, wParam, lParam); } int CallOnPassword(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTSecExt *)Origin)->OnPassword(Event, wParam, lParam); } // Required function int CallApiInitInstance(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTSecExt *)Origin)->ApiInitInstance(Event, wParam, lParam); } // Required function int CallApiExitInstance(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return ((CNTSecExt *)Origin)->ApiExitInstance(Event, wParam, lParam); } int CallApiNewSocket(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { return 0; } int CallOnPreFTPDAccept(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { CFTPDCoreCtrlSock *pSock = (CFTPDCoreCtrlSock *)wParam; CFTPDCoreListenSock *pListenSock = (CFTPDCoreListenSock *)lParam; return 0; } int CallOnPostFTPDAccept(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { CFTPDCoreCtrlSock *pSock = (CFTPDCoreCtrlSock *)wParam; CFTPDCoreListenSock *pListenSock = (CFTPDCoreListenSock *)lParam; return 0; } void CNTSecExt::LogMsg(int flag, LPCSTR Format, ...) { ASSERT(AfxIsValidAddress(this,sizeof(CNTSecExt))); ASSERT(m_pLog != NULL); ASSERT(AfxIsValidAddress(m_pLog, sizeof(CLog))); if (!ShouldLog(m_pLog, flag)) return; { CString cBuf; ASSERT(AfxIsValidString(Format, FALSE)); cBuf.Format("(CNTSecExt) %s", Format); va_list argList; va_start(argList, Format); m_pLog->LogMsgV(flag, cBuf, argList); va_end(argList); } } CNTProperties::CNTProperties() { hLogon = NULL; pSock = NULL; } CNTProperties::~CNTProperties() { if (hLogon) CloseHandle(hLogon); } ////////////////////////////////////////////////////////////////////////////////// // Socket connector subsystem. These functions will create a CSockAPI derived // object (of our choise) for Sockey level notifications. // Delete the calls you don't need, or add the On*Socket handler to create // the object. // Called from the CSock constructor // int CallOnNewSocket(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { CSock *pSock = (CSock *)lParam; return 0; } int CallOnNewTextSocket(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { CTextSock *pSock = (CTextSock *)lParam; // Create a new CNTFTPConn object and link it to the calls we will use. CDllInfo *pDLL = pMe->GetDLLInfo(); ASSERT(pDLL != NULL); if (pDLL == NULL) return 0; CNTFTPConn *pConn = new CNTFTPConn; pConn->pSock = pSock; // Required pSock->m_Funcs[CSock::iOnSocketIsDestroyed].AddLast(pDLL, CSock::iOnSocketIsDestroyed, pConn, CallOnSocketIsDestroyed); pSock->m_Funcs[CSock::OnPreFSYSAccess].AddLast(pDLL, CSock::OnPreFSYSAccess, pConn, CallOnPreFSYSAccess); pSock->m_Funcs[CSock::OnPostFSYSAccess].AddLast(pDLL, CSock::OnPostFSYSAccess, pConn, CallOnPostFSYSAccess); pSock->m_Funcs[CSock::OnGetSecurityDescriptor].AddLast(pDLL, CSock::OnGetSecurityDescriptor, pConn, CallOnGetSecurityDescriptor); pSock->m_Funcs[CSock::iOnConnect].AddLast(pDLL, CSock::iOnConnect, pConn, CallOnConnect); pSock->m_Funcs[CSock::iOnReceive].AddLast(pDLL, CSock::iOnReceive, pConn, CallOnReceive); pSock->m_Funcs[CSock::iOnSend].AddLast(pDLL, CSock::iOnSend, pConn, CallOnSend); pSock->m_Funcs[CSock::iOnCommand].AddLast(pDLL, CSock::iOnCommand, pConn, CallOnCommand); pSock->m_Funcs[CSock::iOnClose].AddLast(pDLL, CSock::iOnClose, pConn, CallOnClose); pSock->m_Funcs[CSock::iSendCtrlMsg].AddLast(pDLL, CSock::iSendCtrlMsg, pConn, CallOnSendCmd); pSock->m_Funcs[CSock::iOnSITECmd].AddLast(pDLL, CSock::iOnSITECmd, pConn, CallOnSITECmd); pSock->m_Funcs[CSock::iOnIdle].AddLast(pDLL, CSock::iOnIdle, pConn, CallOnIdle); pSock->m_Funcs[CSock::iOnVerifyIPAddress].AddLast(pDLL, CSock::iOnVerifyIPAddress, pConn, CallOnVerifyIPAddress); pSock->m_Funcs[CSock::iOnVerifyUploadedFile].AddLast(pDLL, CSock::iOnVerifyUploadedFile, pConn, CallOnVerifyUploadedFile); pSock->m_Funcs[CSock::iOnVerifyTransferRequest].AddLast(pDLL, CSock::iOnVerifyTransferRequest, pConn, CallOnVerifyTransferRequest); return 0; } int CallOnNewFTPDataSocket(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { CFTPDataSock *pSock = (CFTPDataSock *)lParam; return 0; } int CallOnFTPDCoreCtrlSock(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) { CFTPDCoreCtrlSock *pSock = (CFTPDCoreCtrlSock *)lParam; return 0; }