📄 warsvrprotocolftpcmdall.cpp
字号:
#include "StdAfx.h"#include "WarSvrProtocolFtpCmdAll.h" // classes implemented#ifndef WAR_LOG_H# include "WarLog.h"#endif#ifndef WAR_USER_ENGINE_H# include "WarUserEngine.h"#endif#ifndef WAR_SVR_PROTOCOL_FTP_DATA_CONN_H# include "WarSvrProtocolFtpDataConn.h"#endif#ifndef WAR_SVR_DIR_LISTING_H# include "WarSvrDirListing.h"#endif#ifndef WAR_DIRFMT_UNIX_LS_H# include "WarDirfmtUnixLs.h"#endif#ifndef WAR_ARGS_H# include "WarArgs.h"#endif#ifndef WAR_ATOI_H# include "WarAtoi.h"#endif#ifndef WAR_AUTO_LOCK_H# include "WarAutoLock.h"#endif#ifndef WAR_FSYS_H# include "WarFsys.h"#endif#ifndef WAR_OS_H# include "WarOs.h"#endif#include <fstream>using namespace std;#define AUTO_DATA_LOCK \ WarAutoLock my_lock(GetServer().mFtpDataLock);#if 0 // Impl. template/////////////////////////////// XX ///////////////////////////////////////XX::XX(WarSvrProtocolFtp& serverCompanion): WarSvrProtocolFtpCmd("COMMAND", "commandExplanation", "commandSyntax", "commandReference", serverCompanion){}WarSvrProtocolFtpCmd::LastCommandresultE XX::ExecuteCommand(){ return CMD_SUCCESS;}#endif // 0/////////////////////////////// USER AND PASS ///////////////////////////////////////FtpCmdAuthBase::FtpCmdAuthBase(war_ccstr_t commandName, war_ccstr_t commandExplanation, /* Human help*/ war_ccstr_t commandSyntax, /* Formal */ war_ccstr_t commandReference, /* RFC */ WarSvrProtocolFtp& serverCompanion) :WarSvrProtocolFtpCmd(commandName, commandExplanation, commandSyntax, commandReference, serverCompanion){}bool FtpCmdAuthBase::Login(war_ccstr_t virtualHost, war_ccstr_t userName, war_ccstr_t userPasswd){ WarLog err_log(WARLOG_ERROR, "FtpCmdAuthBase::Login()"); war_auth_ptr_t auth_module_ptr; war_authdata_ptr_t session_data_ptr; WarLoginResultE result = GetServer().Login(virtualHost, userName, userPasswd); switch(result) { case LF_OK: { WarLog auth_log(WARLOG_LOGIN, "FtpCmdAuthBase::Login()"); try { GetServer().SetCwd(); } catch(WarException& ex) { err_log << "Failed to login after a successful authentication " "because it was impossible to set the users current " "(home) directory. Please verify the user_HOME option for " "this user." << ex << war_endl; *mpReply << SM_GENERIC_FAIL << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; } auth_log << GetServer() << " User logged in." << war_endl; *mpReply << SM_LOGGED_IN << FTPR_LOGIN_OK_230; GetServer().SetConnectionState(IDLE); } return true; case LF_NEED_PASSWORD:fool_me: *mpReply << SM_NEED_PASSWD << FTPR_NEED_PASSWORD_331; break; case LF_NEED_EMAIL_AS_PWD: *mpReply << SM_NEED_EMAIL << FTPR_NEED_PASSWORD_331; break; case LF_TOO_LONG_USERNAME: case LF_TOO_LONG_PASSWORD: case LF_TOO_LONG_HOSTNAME: case LF_INTERNAL_ERROR: err_log << GetArgument() << " - Login() failed due to error FtpSvrMsgsE::SM_#" << (int)result << war_endl; *mpReply << SM_ERR_BYE << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_THROW_USER_OFF: *mpReply << SM_DONT_KNOW_YOU << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_TIME_OF_DAY_DENIAL: *mpReply << SM_RIGHT_PLACE_WRONG_TIME << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_IP_SHITLISTED: *mpReply << SM_BAD_IP << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_IP_MARKED_AS_HACKER: *mpReply << SM_HACKERS_NOT_WELCOME << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_TOO_MANY_FAILED_LOGINS: *mpReply << SM_TOO_MANY_FAILED_LOGINS << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_TOO_MANY_CONNECTIONS: *mpReply << SM_TMC_ACCOUNT << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_TOO_MANY_CONNECTIONS_TOTAL: *mpReply << SM_TMC_ACCOUNT << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_TOO_MANY_CONNECTIONS_FROM_IP: *mpReply << SM_TMC_IP << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_SYSTEM_SHUTDOWN: *mpReply << SM_SHUTTING_DOWN << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_NO_ANONYMOUS_USERS: *mpReply << SM_ANON_DENIED << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_CONFIGURATION_ERROR: *mpReply << SM_SERVER_CONFIGURATION_ERROR << FTPR_BYE_421; GetServer().CloseConnection(WarError(), false); break; case LF_CALLER_NOT_AUTHENTICATED: default: if (userPasswd) *mpReply << SM_PASSWD_NOT_ACCEPTED << FTPR_NOT_LOGGED_IN_530; else goto fool_me; break; } return false;}/////////////////////////////// USER ///////////////////////////////////////FtpCmdUser::FtpCmdUser(WarSvrProtocolFtp& serverCompanion): FtpCmdAuthBase("USER", "Log on with username", "USER <SP> <username> <CRLF>", "RFC 959", serverCompanion){}WarSvrProtocolFtpCmd::LastCommandresultE FtpCmdUser::ExecuteCommand(){ if (Login(NULL, GetArgument(), NULL)) { return CMD_SUCCESS; } return CMD_FAIL;}/////////////////////////////// PASS ///////////////////////////////////////FtpCmdPass::FtpCmdPass(WarSvrProtocolFtp& serverCompanion): FtpCmdAuthBase("PASS", "Login with password", "PASS <SP> <password> <CRLF>", "RFC 959", serverCompanion){}WarSvrProtocolFtpCmd::LastCommandresultE FtpCmdPass::ExecuteCommand(){ FtpCmdUser *pUserCmd = (FtpCmdUser *)GetServer().GetCmdPtr("USER"); if (!pUserCmd) WarThrow(WarError(WAR_ERR_INTERNAL_DATA_NOT_INITIALIZED), "missing FtpCmdUser"); if (Login(NULL, pUserCmd->GetArgument(), GetArgument())) { return CMD_SUCCESS; } return CMD_FAIL;}/////////////////////////////// PORT ///////////////////////////////////////FtpCmdPort::FtpCmdPort(WarSvrProtocolFtp& serverCompanion): WarSvrProtocolFtpCmd("PORT", "Data port", "<SP> <host-port> <CRLF>", "RFC 959", serverCompanion){}WarSvrProtocolFtpCmd::LastCommandresultE FtpCmdPort::ExecuteCommand(){ if (!GetServer().GetBoolOption("ftpd_DOPORT")) { if (GetServer().GetBoolOption("ftpd_DOPASV")) *mpReply << SM_PORT_DISABLED << FTPR_NOT_IMPL_502; else { *mpReply << "Server misconfiguration. PORT and PASV commands are both disabled." << FTPR_NOT_IMPL_502; WarLog err_log(WARLOG_ERROR, "FtpCmdPort::ExecuteCommand()"); err_log << "***SERVER MISCONFIGURATION. Both PORT and PASV commands are disabled. Please enable at least one of the modes! No files can be transfered until the error is corrected!" << war_endl; } return CMD_FAIL; } sockaddr Sockaddr; memset(&Sockaddr, 0, sizeof(Sockaddr)); sockaddr_in *s_in = (sockaddr_in *)&Sockaddr; int i1, i2, i3, i4, i5, i6; if (sscanf(GetArgument(),"%d,%d,%d,%d,%d,%d", &i1, &i2, &i3, &i4, &i5, &i6) != 6) { *mpReply << GetArgument() << ": Must be 6 digits. (IPv4)" << FTPR_ARG_SYNTAX_501; return CMD_FAIL; } unsigned char *p = (unsigned char *)&s_in->sin_addr; *p++ = (unsigned char)i1; *p++ = (unsigned char)i2; *p++ = (unsigned char)i3; *p++ = (unsigned char)i4; s_in->sin_port = htons((i5 << 8) | i6); s_in->sin_family = AF_INET;#if WAR_RFC2577 // Check network address if ((htonl(INADDR_ANY) == s_in->sin_addr.s_addr) || (htonl(INADDR_NONE) == s_in->sin_addr.s_addr) || (htonl(INADDR_BROADCAST) == s_in->sin_addr.s_addr)) { WarLog sec_log(WARLOG_SECURITY, "FtpCmdPort::ExecuteCommand()", &GetServer()); sec_log << GetArgument() << ": refused PORT command due to invalid IP address: " << inet_ntoa(s_in->sin_addr) << war_endl; *mpReply << SM_INVALID_IP_ADDRESS << FTPR_CMD_NOT_IMPL_ARG_504; return CMD_FAIL; } const struct in_addr& remote_host = GetServer().GetRemoteAddress().GetInAddr(); if ((s_in->sin_addr.s_addr != remote_host.s_addr) // Special case - on the local machine, the loopback and real address max mix && !((remote_host.s_addr == htonl(INADDR_LOOPBACK)) && GetServer().IsLocalAddress(s_in->sin_addr)) && !GetServer().GetBoolOption("ftpd_ALLOWFTPPROXY")) { WarLog sec_log(WARLOG_SECURITY, "FtpCmdPort::ExecuteCommand()", &GetServer()); sec_log << GetArgument() << ": refused PORT command. Server to server (proxy) is disabled (ftpd_ALLOWFTPPROXY option): " << inet_ntoa(s_in->sin_addr) << war_endl; *mpReply << SM_NO_FTP_PROXY << FTPR_CMD_NOT_IMPL_ARG_504; return CMD_FAIL; } // Check port if (GetServer().GetBoolOption("ftpd_DOPRIVPORT") && ((ntohs(s_in->sin_port) < 1024))) { WarLog sec_log(WARLOG_SECURITY, "FtpCmdPort::ExecuteCommand()", &GetServer()); sec_log << GetArgument() << ": refused PORT command due to ftpd_DOPRIVPORT setting" << war_endl; *mpReply << SM_PORT_RESTRICTED << FTPR_CMD_NOT_IMPL_ARG_504; return CMD_FAIL; }#endif // WAR_RFC2577 *mpReply << SM_PORT_OK << FTPR_OK_200; GetServer().mTransferMode.mPortAddress.AssignSockaddr( &Sockaddr, sizeof(Sockaddr)); GetServer().mTransferMode.mConnectionType = CONN_ACTIVE; WarLog debug_log(WARLOG_DEBUG, "FtpCmdPort::ExecuteCommand()", &GetServer()); if (debug_log) { debug_log << "PORT " << GetServer().mTransferMode.mPortAddress.Explain() << war_endl; } return CMD_SUCCESS;}FtpCmdPasv::FtpCmdPasv(WarSvrProtocolFtp& serverCompanion): WarSvrProtocolFtpCmd("PASV", "Request a passive connection (the server listens for a connection)", "PASV <CRLF>", "RFC 959", serverCompanion){}WarSvrProtocolFtpCmd::LastCommandresultE FtpCmdPasv::ExecuteCommand(){ WarNetAddress local_addr; if (!GetServer().GetBoolOption("ftpd_DOPASV")) { if (GetServer().GetBoolOption("ftpd_DOPORT")) *mpReply << SM_PASV_DISABLED << FTPR_NOT_IMPL_502; else { *mpReply << "Server misconfiguration. PORT and PASV commands are both disabled." << FTPR_NOT_IMPL_502; WarLog err_log(WARLOG_ERROR, "FtpCmdPasv::ExecuteCommand()", &GetServer()); err_log << "***SERVER MISCONFIGURATION. Both PORT and PASV commands are disabled. Please enable at least one of the modes! No files can be transfered until the error is corrected!" << war_endl; } return CMD_FAIL; } if (!GetServer().mDataConnectionPtr.IsEmpty()) { /* Some DOS attacks may involve flooding the server with PASV commands. We will never listen to more than one of these at one time, but creating and setting up listening sockets may be expensive. We will therefore not accept a PASV command until the pervious file transfer has completed, or the passive socket timed out. */ *mpReply << SM_PASV_FLOOD; if (GetServer().GetBoolOption("ftpd_STRICTREPLY")) *mpReply << FTPR_SYNTAX_ERR_500; else *mpReply << FTPR_ABORT_451; // Not RFC 959 return code !! return CMD_FAIL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -