📄 warsvrprotocolftp.cpp
字号:
mFtpStat.AddValue((WarSvrProtocolFtpStat::StatItemE) (WarSvrProtocolFtpStat::ST_FILETRANS_FILES_IN + st_offset), 1); } } catch(WarException) { ; } // Reply try { if (status) { if (debug_log) { status_text = "failed with error; "; status_text += status.Explain(); } // Failed switch(status.LocalError()) { case WAR_ERR_VERSION: case WAR_ERR_USAGE: mReply << SM_GENERIC_FAIL << FTPR_ABORT_451; break; case WAR_ERR_NAME_EXIST: mReply << SM_NAME_EXIST_DENIED_ACCESS << FTPR_ACCESS_DENIED_550; break; case WAR_ERR_OBJECT_NOT_FOUND: case WAR_FERR_NO_SUCH_PATH: case WAR_ERR_ACCESS_DENIED: mReply << SM_NO_FILE_OR_N0_ACCESS << FTPR_ACCESS_DENIED_550; break; case WAR_FERR_PATH_IS_A_DIR: mReply << SM_GENERIC_FAIL << status.Explain() << FTPR_ACCESS_DENIED_550; break; case WAR_FERR_RECURSIVE_LISTINGS_FORBIDDEN: mReply << SM_RECURSIVE_LISTINGS_FORBIDDEN << FTPR_ACCESS_DENIED_550; break; case WAR_ERR_INVALID_PATH: mReply << SM_ILLEGAL_PATH << FTPR_ARG_SYNTAX_501; break; case WAR_FTPDERR_NOASCIIREST: mReply << SM_NO_ASCII_RESTART << FTPR_ACCESS_DENIED_550; break; case WAR_FTPDERR_REST_OUT_OF_RANGE: mReply << SM_RESTART_OUT_OF_RANGE << FTPR_ACCESS_DENIED_550; break; case WAR_FTPERR_BAD_SEQUENCE_OF_CMDS: mReply << SM_BAD_SEQ_OF_CMDS << FTPR_BAD_SEQ_503; break; case WAR_FTPDERR_ABORTED: mReply << SM_ABOR_INTERRUPTED << FTPR_TRANSFER_ABORTED_DATACONN_CLOSED_426; break; default: switch(GetConnectionState()) { case GETFILE: case PUTFILE: mReply << SM_TRANSFER_FAILED << FTPR_TRANSFER_ABORTED_DATACONN_CLOSED_426; break; default: mReply << SM_GENERIC_FAIL << status << FTPR_ABORT_451; break; } } } else { // Transfer successful status_text = "successfully completed."; mReply << SM_TRANSFER_DONE_OK << FTPR_TRANSFER_OK_226; } } catch(WarException) { ; // The reply will throw an expection if the connection is lost } // Write log entries try { if (mDataConnectionPtr) { if ((mDataConnectionPtr->GetFileFlags() & WarFile::F_TEMPORARY)) { st_offset += 8; // tmp file goto db_log; } switch(state) { case GETFILE: case PUTFILE: { trans_log << "Transfer of \"" << mCurrentFile.GetUrl().GetUrl() << "\" " << status_text << war_endl; } break; default:db_log: if (debug_log) { debug_log << "Transfer of \"" << mCurrentFile.GetUrl().GetUrl() << "\" " << status_text << war_endl; } break; } } else { st_offset = -1; // Disable debug_log << "Transfer of uninitalized file " << status_text << war_endl; } } catch(WarException) { ; } // Reset transfer parameters mTransferMode.mConnectionType = CONN_ACTIVE; mTransferMode.mTransferOperation = TROP_NORMAL; mTransferMode.mPortAddress = mRemoteAddress; mTransferMode.mPortAddress.SetPort(mLocalAddress.GetPort()); mTransferMode.mRestartPos = 0; SetConnectionState(IDLE); if (mDataConnectionPtr) mDataConnectionPtr = NULL;}void WarSvrProtocolFtp::OnSent(const WarError& status, war_transfer_buffer_ptr_t& buffer){ AUTO_LOCK // Update statistics mFtpStat.AddValue(WarSvrProtocolFtpStat::ST_CNTR_BYTES_OUT, buffer->GetBytesUsed()); WarSvrProtocol::OnSent(status, buffer);}/////////////////////////////// PROTECTED ///////////////////////////////////void WarSvrProtocolFtp::OnClientConnect(){ AUTO_LOCK // Update internal variables // and start receiving commands from the user try { WarSvrProtocol::OnClientConnect(); } catch(WarException& ex) { switch(ex.LocalError()) { case WAR_ERR_IP_IS_DENIED: mReply << SM_BAD_IP << FTPR_BYE_421; break; case WAR_ERR_ACCESS_DENIED: mReply << SM_ACCESS_DENIED << FTPR_BYE_421; break; default: mReply << SM_GENERIC_FAIL << FTPR_BYE_421; break; } CloseConnection(ex, false); throw ex; } // Install a callback timer mIdleTimeSeconds = WarMax(GetIntOption("ftpd_IDLETIME"), 10); WarTime first_run; first_run.mTime += (mIdleTimeSeconds * 1000); mTimerPtr = new timer_class_t(this, first_run, WarTimerEvent::TIMER_LOOP_RELATIVE, mIdleTimeSeconds * 1000); WarTimer::GetTimer().AddEvent((WarPtrWrapper<class WarTimerEvent>&)mTimerPtr); // RFC 959 3.2 Default data port for the user-process mTransferMode.mPortAddress = mRemoteAddress; mTransferMode.mPortAddress.SetPort(mLocalAddress.GetPort()); // Local address for outgoing connections (PORT) mTransferMode.mLocalAddress = mLocalAddress; int my_port = GetIntOption("ftpd_BINDDATA"); if (my_port == -1) my_port = mTransferMode.mLocalAddress.GetPort() -1; if ((my_port < 0) || (my_port > 0xffff)) { WarLog error_log(WARLOG_ERROR, "WarSvrProtocolFtp::OnClientConnect()", this); error_log << "Configuration error. ftpd_BINDDATA has an invalid value. Setting local port to the default." << war_endl; my_port = mTransferMode.mLocalAddress.GetPort() -1; if (my_port < 0) my_port = 0; // Just in case. Should never happen. } mTransferMode.mLocalAddress.SetPort((war_port_t)my_port); if (GetBoolOption("ftpd_STELTHSYST")) mReply << SM_WELCOME_STELTH << FTPR_READY_220; else mReply << SM_WELCOME << FTPR_READY_220;}#define GETC() (mCurrentpendingBytes ? \ mPendingBytes[mCurrentpendingBytes--] \ : (p < end_of_buffer) ? *p++ : EOF)// Using reverse order to keep it simple !!!#define UNGETC(ch) \{\ if ((MAX_PENDING_BYTES -1) <= mCurrentpendingBytes) \ goto buffer_exploit;\ mPendingBytes[mCurrentpendingBytes++] = (char)(ch & 0xff);\}void WarSvrProtocolFtp::OnReceived(const WarError& status, war_transfer_buffer_ptr_t& buffer){ AUTO_LOCK war_authdata_ptr_t my_auth = GetLoginAuthData(); WarUserAuthImpersonate my_impersonation(my_auth); // Update statistics mFtpStat.AddValue(WarSvrProtocolFtpStat::ST_CNTR_BYTES_IN, buffer->GetBytesUsed()); WarSvrProtocol::OnReceived(status, buffer); if (status) { WarLog error_log(WARLOG_ERROR, "WarSvrProtocolFtp::OnReceived()", this); error_log << "Error on input. Closing connection" << status << war_endl; try { CloseConnection(status); } catch(WarException) { return; } } war_ccstr_t p = buffer->GetBuffer(); const war_ccstr_t end_of_buffer = p + buffer->GetBytesUsed(); int ch = EOF; while((ch = GETC()) != EOF) { ch &= 0377; switch(ch) { case '\n': if (mCurrentInputBytes && (mInputData[mCurrentInputBytes -1] == '\r')) { mInputData[--mCurrentInputBytes] = 0; OnCommand(mInputData, mCurrentInputBytes); mCurrentInputBytes = 0; } break; case IAC: // Telnet if ((ch = GETC()) == EOF) { UNGETC(IAC); goto end_of_input; } ch &= 0377; switch(ch) { case WILL: case WONT: if ((ch = GETC()) == EOF) { UNGETC(WILL); // Reverse order UNGETC(IAC); // Reverse order goto end_of_input; } { char telnet_buf[4]; sprintf(telnet_buf, "%c%c%c", IAC, DONT, 0377&ch); Send(telnet_buf, 3); FlushOut(); } continue; case DO: case DONT: if ((ch = GETC()) == EOF) { UNGETC(DO); // Reverse order UNGETC(IAC); // Reverse order goto end_of_input; } { char telnet_buf[4]; sprintf(telnet_buf, "%c%c%c", IAC, WONT, 0377&ch); Send(telnet_buf, 3); FlushOut(); } continue; case IAC: break; default: continue; /* ignore command */ } break; // case IAC // Fall trough default: if ((MAX_INPUT_BUFFER - 1) <= mCurrentInputBytes) goto buffer_exploit; mInputData[mCurrentInputBytes] = (char)ch; mCurrentInputBytes++; } }end_of_input: if (IsOpen() && mIoInBufferPtr) { mIoInBufferPtr->Reset(); RecvWithCallback(mIoInBufferPtr); } return;buffer_exploit: mReply << SM_HACKER_BUFFER_ATTACK << FTPR_BYE_421; try { CloseConnection(WarError(WAR_ERR_SECURITY_VIOLATION), false); } catch(WarException) { return; }}void WarSvrProtocolFtp::OnCommand(war_ccstr_t cmdBuffer, const size_t bufferLength) throw(WarException){ WarLog debug_log(WARLOG_DEBUG, "WarSvrProtocolFtp::OnCommand()", this); char cmd_name[MAX_FTP_CMD_LEN + 1]; char *pp = cmd_name; const war_ccstr_t buffer_limit = cmd_name + MAX_FTP_CMD_LEN; war_ccstr_t p = cmdBuffer; prot_cmd_prp_t prepare_cmd(this); // Allocates and deallocates resources while(*p && (*p != ' ')) { if (buffer_limit <= pp) { mReply << SM_UNKNOWN_CMD << FTPR_SYNTAX_ERR_500; return; } *pp++ = toupper(*p++); } *pp = 0; if (debug_log) { if (!strcmp(cmd_name, "PASS")) debug_log << cmd_name << " ********" << war_endl; else debug_log << "FTP command: " << cmdBuffer << war_endl; } if ((pp - cmd_name) < MIN_FTP_CMD_LEN) { mReply << SM_UNKNOWN_CMD << FTPR_SYNTAX_ERR_500; return; } mFtpCommands.OnCommand(cmd_name, cmdBuffer, bufferLength);}#undef GETC#undef UNGETCvoid WarSvrProtocolFtp::DoResolvPath(war_ccstr_t filePath, war_svrpath_t& path) const throw(WarException){#if WAR_RFC2640 war_ccstr_t p = filePath; size_t str_len = 0; bool is_ascii = true; while(*p) { ++str_len; if (*p++ & 0x80) { is_ascii = false; while(*p++) ++str_len; break; } } if (!is_ascii) { if (war_utf8_valid((const unsigned char *)filePath, str_len)) { // Use UTF8 conversion path << WarUtf8(filePath).GetUnicode(); } else { // Try default character converison WarCollector<wchar_t> wide_buf = filePath; path << wide_buf.GetValue(); } } else { WarSvrProtocol::DoResolvPath(filePath, path); }#else path << filePath;#endif}/////////////////////////////// PRIVATE ///////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -