⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prelogin.c

📁 文件传输协议linux 下vsftpd2.1.0.tar.gz
💻 C
字号:
/* * Part of Very Secure FTPd * Licence: GPL v2 * Author: Chris Evans * prelogin.c * * Code to parse the FTP protocol prior to a successful login. */#include "prelogin.h"#include "ftpcmdio.h"#include "ftpcodes.h"#include "str.h"#include "vsftpver.h"#include "tunables.h"#include "oneprocess.h"#include "twoprocess.h"#include "sysdeputil.h"#include "sysutil.h"#include "session.h"#include "banner.h"#include "logging.h"#include "ssl.h"#include "features.h"#include "defs.h"#include "opts.h"/* Functions used */static void check_limits(struct vsf_session* p_sess);static void emit_greeting(struct vsf_session* p_sess);static void parse_username_password(struct vsf_session* p_sess);static void handle_user_command(struct vsf_session* p_sess);static void handle_pass_command(struct vsf_session* p_sess);static void check_login_delay();static void check_login_fails(struct vsf_session* p_sess);voidinit_connection(struct vsf_session* p_sess){  if (tunable_setproctitle_enable)  {    vsf_sysutil_setproctitle("not logged in");  }  /* Before we talk to the remote, make sure an alarm is set up in case   * writing the initial greetings should block.   */  vsf_cmdio_set_alarm(p_sess);  /* Check limits before doing an implicit SSL handshake, to avoid DoS   * attacks. This will result in plain text messages being sent to the SSL   * client, but we can live with that.   */  check_limits(p_sess);  if (tunable_ssl_enable && tunable_implicit_ssl)  {    ssl_control_handshake(p_sess);  }  emit_greeting(p_sess);  parse_username_password(p_sess);}static voidcheck_limits(struct vsf_session* p_sess){  struct mystr str_log_line = INIT_MYSTR;  /* Check for client limits (standalone mode only) */  if (tunable_max_clients > 0 &&      p_sess->num_clients > tunable_max_clients)  {    str_alloc_text(&str_log_line, "Connection refused: too many sessions.");    vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);    vsf_cmdio_write_exit(p_sess, FTP_TOO_MANY_USERS,      "There are too many connected users, please try later.");  }  if (tunable_max_per_ip > 0 &&      p_sess->num_this_ip > tunable_max_per_ip)  {    str_alloc_text(&str_log_line,                   "Connection refused: too many sessions for this address.");    vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);    vsf_cmdio_write_exit(p_sess, FTP_IP_LIMIT,      "There are too many connections from your internet address.");  }  if (!p_sess->tcp_wrapper_ok)  {    str_alloc_text(&str_log_line,                   "Connection refused: tcp_wrappers denial.");    vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);    vsf_cmdio_write_exit(p_sess, FTP_IP_DENY, "Service not available.");  }  vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);}static voidemit_greeting(struct vsf_session* p_sess){  if (!str_isempty(&p_sess->banner_str))  {    vsf_banner_write(p_sess, &p_sess->banner_str, FTP_GREET);    str_free(&p_sess->banner_str);    vsf_cmdio_write(p_sess, FTP_GREET, "");  }  else if (tunable_ftpd_banner == 0)  {    vsf_cmdio_write(p_sess, FTP_GREET, "(vsFTPd " VSF_VERSION                     ")");  }  else  {    vsf_cmdio_write(p_sess, FTP_GREET, tunable_ftpd_banner);  }}static voidparse_username_password(struct vsf_session* p_sess){  while (1)  {    vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,                              &p_sess->ftp_arg_str, 1);    if (str_equal_text(&p_sess->ftp_cmd_str, "USER"))    {      handle_user_command(p_sess);    }    else if (str_equal_text(&p_sess->ftp_cmd_str, "PASS"))    {      handle_pass_command(p_sess);    }    else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT"))    {      vsf_cmdio_write(p_sess, FTP_GOODBYE, "Goodbye.");      vsf_sysutil_exit(0);    }    else if (str_equal_text(&p_sess->ftp_cmd_str, "FEAT"))    {      handle_feat(p_sess);    }    else if (str_equal_text(&p_sess->ftp_cmd_str, "OPTS"))    {      handle_opts(p_sess);    }    else if (tunable_ssl_enable &&             str_equal_text(&p_sess->ftp_cmd_str, "AUTH") &&             !p_sess->control_use_ssl)    {      handle_auth(p_sess);    }    else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "PBSZ"))    {      handle_pbsz(p_sess);    }    else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "PROT"))    {      handle_prot(p_sess);    }    else if (str_isempty(&p_sess->ftp_cmd_str) &&             str_isempty(&p_sess->ftp_arg_str))    {      // Deliberately ignore to avoid NAT device bugs. ProFTPd does the same.    }    else    {      vsf_cmdio_write(p_sess, FTP_LOGINERR,                      "Please login with USER and PASS.");    }  }}static voidhandle_user_command(struct vsf_session* p_sess){  /* SECURITY: If we're in anonymous only-mode, immediately reject   * non-anonymous usernames in the hope we save passwords going plaintext   * over the network   */  int is_anon = 1;  str_copy(&p_sess->user_str, &p_sess->ftp_arg_str);  str_upper(&p_sess->ftp_arg_str);  if (!str_equal_text(&p_sess->ftp_arg_str, "FTP") &&      !str_equal_text(&p_sess->ftp_arg_str, "ANONYMOUS"))  {    is_anon = 0;  }  if (!tunable_local_enable && !is_anon)  {    vsf_cmdio_write(      p_sess, FTP_LOGINERR, "This FTP server is anonymous only.");    str_empty(&p_sess->user_str);    return;  }  if (is_anon && p_sess->control_use_ssl && !tunable_allow_anon_ssl &&      !tunable_force_anon_logins_ssl)  {    vsf_cmdio_write(      p_sess, FTP_LOGINERR, "Anonymous sessions may not use encryption.");    str_empty(&p_sess->user_str);    return;  }  if (tunable_ssl_enable && !is_anon && !p_sess->control_use_ssl &&      tunable_force_local_logins_ssl)  {    vsf_cmdio_write(      p_sess, FTP_LOGINERR, "Non-anonymous sessions must use encryption.");    str_empty(&p_sess->user_str);    return;  }  if (tunable_ssl_enable && is_anon && !p_sess->control_use_ssl &&      tunable_force_anon_logins_ssl)  {     vsf_cmdio_write(      p_sess, FTP_LOGINERR, "Anonymous sessions must use encryption.");    str_empty(&p_sess->user_str);    return;  }  if (tunable_userlist_enable)  {    int located = str_contains_line(&p_sess->userlist_str, &p_sess->user_str);    if ((located && tunable_userlist_deny) ||        (!located && !tunable_userlist_deny))    {      vsf_cmdio_write(p_sess, FTP_LOGINERR, "Permission denied.");      check_login_fails(p_sess);      str_empty(&p_sess->user_str);      return;    }  }  if (is_anon && tunable_no_anon_password)  {    /* Fake a password */    str_alloc_text(&p_sess->ftp_arg_str, "<no password>");    handle_pass_command(p_sess);  }  else  {    vsf_cmdio_write(p_sess, FTP_GIVEPWORD, "Please specify the password.");  }}static voidhandle_pass_command(struct vsf_session* p_sess){  if (str_isempty(&p_sess->user_str))  {    vsf_cmdio_write(p_sess, FTP_NEEDUSER, "Login with USER first.");    return;  }  /* These login calls never return if successful */  if (tunable_one_process_model)  {    vsf_one_process_login(p_sess, &p_sess->ftp_arg_str);  }  else  {    vsf_two_process_login(p_sess, &p_sess->ftp_arg_str);  }  check_login_delay();  vsf_cmdio_write(p_sess, FTP_LOGINERR, "Login incorrect.");  check_login_fails(p_sess);  str_empty(&p_sess->user_str);  /* FALLTHRU if login fails */}static void check_login_delay(){  if (tunable_delay_failed_login)  {    vsf_sysutil_sleep((double) tunable_delay_failed_login);  }}static void check_login_fails(struct vsf_session* p_sess){  if (++p_sess->login_fails >= tunable_max_login_fails)  {    vsf_sysutil_exit(0);  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -