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

📄 postlogin.c

📁 文件传输协议linux 下vsftpd2.1.0.tar.gz
💻 C
📖 第 1 页 / 共 4 页
字号:
}static intport_active(struct vsf_session* p_sess){  int ret = 0;  if (p_sess->p_port_sockaddr != 0)  {    ret = 1;    if (pasv_active(p_sess))    {      bug("port and pasv both active");    }  }  return ret;}static intpasv_active(struct vsf_session* p_sess){  int ret = 0;  if (p_sess->pasv_listen_fd != -1)  {    ret = 1;    if (port_active(p_sess))    {      bug("pasv and port both active");    }  }  return ret;}static voidport_cleanup(struct vsf_session* p_sess){  vsf_sysutil_sockaddr_clear(&p_sess->p_port_sockaddr);}static voidpasv_cleanup(struct vsf_session* p_sess){  if (p_sess->pasv_listen_fd != -1)  {    vsf_sysutil_close(p_sess->pasv_listen_fd);    p_sess->pasv_listen_fd = -1;  }}static voidhandle_pasv(struct vsf_session* p_sess, int is_epsv){  static struct mystr s_pasv_res_str;  static struct vsf_sysutil_sockaddr* s_p_sockaddr;  int bind_retries = 10;  unsigned short the_port = 0;  /* IPPORT_RESERVED */  unsigned short min_port = 1024;  unsigned short max_port = 65535;  int is_ipv6 = vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr);  if (is_epsv && !str_isempty(&p_sess->ftp_arg_str))  {    int argval;    str_upper(&p_sess->ftp_arg_str);    if (str_equal_text(&p_sess->ftp_arg_str, "ALL"))    {      p_sess->epsv_all = 1;      vsf_cmdio_write(p_sess, FTP_EPSVALLOK, "EPSV ALL ok.");      return;    }    argval = vsf_sysutil_atoi(str_getbuf(&p_sess->ftp_arg_str));    if (argval < 1 || argval > 2 || (!is_ipv6 && argval == 2))    {      vsf_cmdio_write(p_sess, FTP_EPSVBAD, "Bad network protocol.");      return;    }  }  pasv_cleanup(p_sess);  port_cleanup(p_sess);  if (is_ipv6)  {    p_sess->pasv_listen_fd = vsf_sysutil_get_ipv6_sock();  }  else  {    p_sess->pasv_listen_fd = vsf_sysutil_get_ipv4_sock();  }  vsf_sysutil_activate_reuseaddr(p_sess->pasv_listen_fd);  if (tunable_pasv_min_port > min_port && tunable_pasv_min_port <= max_port)  {    min_port = tunable_pasv_min_port;  }  if (tunable_pasv_max_port >= min_port && tunable_pasv_max_port < max_port)  {    max_port = tunable_pasv_max_port;  }  while (--bind_retries)  {    int retval;    double scaled_port;    the_port = vsf_sysutil_get_random_byte();    the_port <<= 8;    the_port |= vsf_sysutil_get_random_byte();    scaled_port = (double) min_port;    scaled_port += ((double) the_port / (double) 65536) *                   ((double) max_port - min_port + 1);    the_port = (unsigned short) scaled_port;    vsf_sysutil_sockaddr_clone(&s_p_sockaddr, p_sess->p_local_addr);    vsf_sysutil_sockaddr_set_port(s_p_sockaddr, the_port);    retval = vsf_sysutil_bind(p_sess->pasv_listen_fd, s_p_sockaddr);    if (!vsf_sysutil_retval_is_error(retval))    {      retval = vsf_sysutil_listen(p_sess->pasv_listen_fd, 1);      if (!vsf_sysutil_retval_is_error(retval))      {        break;      }    }    /* SELinux systems can give you an inopportune EACCES, it seems. */    if (vsf_sysutil_get_error() == kVSFSysUtilErrADDRINUSE ||        vsf_sysutil_get_error() == kVSFSysUtilErrACCES)    {      continue;    }    die("vsf_sysutil_bind / listen");  }  if (!bind_retries)  {    die("vsf_sysutil_bind");  }  if (is_epsv)  {    str_alloc_text(&s_pasv_res_str, "Entering Extended Passive Mode (|||");    str_append_ulong(&s_pasv_res_str, (unsigned long) the_port);    str_append_text(&s_pasv_res_str, "|).");    vsf_cmdio_write_str(p_sess, FTP_EPSVOK, &s_pasv_res_str);    return;  }  if (tunable_pasv_address != 0)  {    /* Report passive address as specified in configuration */    if (vsf_sysutil_inet_aton(tunable_pasv_address, s_p_sockaddr) == 0)    {      die("invalid pasv_address");    }  }  str_alloc_text(&s_pasv_res_str, "Entering Passive Mode (");  if (!is_ipv6)  {    str_append_text(&s_pasv_res_str, vsf_sysutil_inet_ntop(s_p_sockaddr));  }  else  {    const void* p_v4addr = vsf_sysutil_sockaddr_ipv6_v4(s_p_sockaddr);    if (p_v4addr)    {      str_append_text(&s_pasv_res_str, vsf_sysutil_inet_ntoa(p_v4addr));    }    else    {      str_append_text(&s_pasv_res_str, "0,0,0,0");    }  }  str_replace_char(&s_pasv_res_str, '.', ',');  str_append_text(&s_pasv_res_str, ",");  str_append_ulong(&s_pasv_res_str, the_port >> 8);  str_append_text(&s_pasv_res_str, ",");  str_append_ulong(&s_pasv_res_str, the_port & 255);  str_append_text(&s_pasv_res_str, ").");  vsf_cmdio_write_str(p_sess, FTP_PASVOK, &s_pasv_res_str);}static voidhandle_retr(struct vsf_session* p_sess){  static struct mystr s_mark_str;  static struct vsf_sysutil_statbuf* s_p_statbuf;  struct vsf_transfer_ret trans_ret;  int remote_fd;  int opened_file;  int is_ascii = 0;  filesize_t offset = p_sess->restart_pos;  p_sess->restart_pos = 0;  if (!data_transfer_checks_ok(p_sess))  {    return;  }  if (p_sess->is_ascii && offset != 0)  {    vsf_cmdio_write(p_sess, FTP_FILEFAIL,                    "No support for resume of ASCII transfer.");    return;  }  resolve_tilde(&p_sess->ftp_arg_str, p_sess);  vsf_log_start_entry(p_sess, kVSFLogEntryDownload);  str_copy(&p_sess->log_str, &p_sess->ftp_arg_str);  prepend_path_to_filename(&p_sess->log_str);  if (!vsf_access_check_file(&p_sess->ftp_arg_str))  {    vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied.");    return;  }  opened_file = str_open(&p_sess->ftp_arg_str, kVSFSysStrOpenReadOnly);  if (vsf_sysutil_retval_is_error(opened_file))  {    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file.");    return;  }  /* Lock file if required */  if (tunable_lock_upload_files)  {    vsf_sysutil_lock_file_read(opened_file);  }  vsf_sysutil_fstat(opened_file, &s_p_statbuf);  /* No games please */  if (!vsf_sysutil_statbuf_is_regfile(s_p_statbuf))  {    /* Note - pretend open failed */    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file.");    /* Irritating FireFox does RETR on directories, so avoid logging this     * very common and noisy case.     */    if (vsf_sysutil_statbuf_is_dir(s_p_statbuf))    {      vsf_log_clear_entry(p_sess);    }    goto file_close_out;  }  /* Now deactive O_NONBLOCK, otherwise we have a problem on DMAPI filesystems   * such as XFS DMAPI.   */  vsf_sysutil_deactivate_noblock(opened_file);  /* Optionally, we'll be paranoid and only serve publicly readable stuff */  if (p_sess->is_anonymous && tunable_anon_world_readable_only &&      !vsf_sysutil_statbuf_is_readable_other(s_p_statbuf))  {    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file.");    goto file_close_out;  }  /* Set the download offset (from REST) if any */  if (offset != 0)  {    vsf_sysutil_lseek_to(opened_file, offset);  }  str_alloc_text(&s_mark_str, "Opening ");  if (tunable_ascii_download_enable && p_sess->is_ascii)  {    str_append_text(&s_mark_str, "ASCII");    is_ascii = 1;  }  else  {    str_append_text(&s_mark_str, "BINARY");  }  str_append_text(&s_mark_str, " mode data connection for ");  str_append_str(&s_mark_str, &p_sess->ftp_arg_str);  str_append_text(&s_mark_str, " (");  str_append_filesize_t(&s_mark_str,                        vsf_sysutil_statbuf_get_size(s_p_statbuf));  str_append_text(&s_mark_str, " bytes).");  remote_fd = get_remote_transfer_fd(p_sess, str_getbuf(&s_mark_str));  if (vsf_sysutil_retval_is_error(remote_fd))  {    goto port_pasv_cleanup_out;  }  trans_ret = vsf_ftpdataio_transfer_file(p_sess, remote_fd,                                          opened_file, 0, is_ascii);  if (vsf_ftpdataio_dispose_transfer_fd(p_sess) != 1 && trans_ret.retval == 0)  {    trans_ret.retval = -2;  }  p_sess->transfer_size = trans_ret.transferred;  /* Log _after_ the blocking dispose call, so we get transfer times right */  if (trans_ret.retval == 0)  {    vsf_log_do_log(p_sess, 1);  }  /* Emit status message _after_ blocking dispose call to avoid buggy FTP   * clients truncating the transfer.   */  if (trans_ret.retval == -1)  {    vsf_cmdio_write(p_sess, FTP_BADSENDFILE, "Failure reading local file.");  }  else if (trans_ret.retval == -2)  {    vsf_cmdio_write(p_sess, FTP_BADSENDNET, "Failure writing network stream.");  }  else  {    vsf_cmdio_write(p_sess, FTP_TRANSFEROK, "File send OK.");  }  check_abor(p_sess);port_pasv_cleanup_out:  port_cleanup(p_sess);  pasv_cleanup(p_sess);file_close_out:  vsf_sysutil_close(opened_file);}static voidhandle_list(struct vsf_session* p_sess){  handle_dir_common(p_sess, 1, 0);}static voidhandle_dir_common(struct vsf_session* p_sess, int full_details, int stat_cmd){  static struct mystr s_option_str;  static struct mystr s_filter_str;  static struct mystr s_dir_name_str;  static struct vsf_sysutil_statbuf* s_p_dirstat;  int dir_allow_read = 1;  struct vsf_sysutil_dir* p_dir = 0;  int retval = 0;  int use_control = 0;  str_empty(&s_option_str);  str_empty(&s_filter_str);  /* By default open the current directory */  str_alloc_text(&s_dir_name_str, ".");  if (!stat_cmd && !data_transfer_checks_ok(p_sess))  {    return;  }  /* Do we have an option? Going to be strict here - the option must come   * first. e.g. "ls -a .." fine, "ls .. -a" not fine   */  if (!str_isempty(&p_sess->ftp_arg_str) &&      str_get_char_at(&p_sess->ftp_arg_str, 0) == '-')  {    /* Chop off the '-' */    str_mid_to_end(&p_sess->ftp_arg_str, &s_option_str, 1);    /* A space will separate options from filter (if any) */    str_split_char(&s_option_str, &s_filter_str, ' ');  }  else  {    /* The argument, if any, is just a filter */    str_copy(&s_filter_str, &p_sess->ftp_arg_str);  }  if (!str_isempty(&s_filter_str))  {    resolve_tilde(&s_filter_str, p_sess);    if (!vsf_access_check_file(&s_filter_str))    {      vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied.");      return;    }    /* First check - is it an outright directory, as in "ls /pub" */    p_dir = str_opendir(&s_filter_str);    if (p_dir != 0)    {      /* Listing a directory! */      str_copy(&s_dir_name_str, &s_filter_str);      str_free(&s_filter_str);    }    else    {      struct str_locate_result locate_result =        str_locate_char(&s_filter_str, '/');      if (locate_result.found)      {        /* Includes a path! Reverse scan for / in the arg, to get the         * base directory and filter (if any)         */        str_copy(&s_dir_name_str, &s_filter_str);        str_split_char_reverse(&s_dir_name_str, &s_filter_str, '/');        /* If we have e.g. "ls /.message", we just ripped off the leading         * slash because it is the only one!         */        if (str_isempty(&s_dir_name_str))        {          str_alloc_text(&s_dir_name_str, "/");        }      }    }  }  if (p_dir == 0)  {    /* NOTE - failure check done below, it's not forgotten */    p_dir = str_opendir(&s_dir_name_str);  }  /* Fine, do it */  if (stat_cmd)  {    use_control = 1;    str_append_char(&s_option_str, 'a');    vsf_cmdio_write_hyphen(p_sess, FTP_STATFILE_OK, "Status follows:");  }  else  {    int remote_fd = get_remote_transfer_fd(      p_sess, "Here comes the directory listing.");    if (vsf_sysutil_retval_is_error(remote_fd))    {      goto dir_close_out;    }  }  if (p_sess->is_anonymous && p_dir && tunable_anon_world_readable_only)  {    vsf_sysutil_dir_stat(p_dir, &s_p_dirstat);    if (!vsf_sysutil_statbuf_is_readable_other(s_p_dirstat))    {      dir_allow_read = 0;    }  }  if (p_dir != 0 && dir_allow_read)  {    retval = vsf_ftpdataio_transfer_dir(p_sess, use_control, p_dir,                                        &s_dir_name_str, &s_option_str,                                        &s_filter_str, full_details);  }  if (!stat_cmd)  {    if (vsf_ftpdataio_dispose_transfer_fd(p_sess) != 1 && retval == 0)    {      retval = -1;    }  }  if (stat_cmd)  {    vsf_cmdio_write(p_sess, FTP_STATFILE_OK, "End of status");  }  else if (p_dir == 0 || !dir_allow_read)  {    vsf_cmdio_write(p_sess, FTP_TRANSFEROK,                    "Transfer done (but failed to open directory).");  }  else if (retval == 0)  {    vsf_cmdio_write(p_sess, FTP_TRANSFEROK, "Directory send OK.");  }  else  {    vsf_cmdio_write(p_sess, FTP_BADSENDNET, "Failure writing network stream.");  }  check_abor(p_sess);dir_close_out:  if (p_dir)  {    vsf_sysutil_closedir(p_dir);  }  if (!stat_cmd)  {    port_cleanup(p_sess);    pasv_cleanup(p_sess);  }}static voidhandle_type(struct vsf_session* p_sess){  str_upper(&p_sess->ftp_arg_str);  if (str_equal_text(&p_sess->ftp_arg_str, "I") ||      str_equal_text(&p_sess->ftp_arg_str, "L8") ||      str_equal_text(&p_sess->ftp_arg_str, "L 8"))  {    p_sess->is_ascii = 0;    vsf_cmdio_write(p_sess, FTP_TYPEOK, "Switching to Binary mode.");  }  else if (str_equal_text(&p_sess->ftp_arg_str, "A") ||           str_equal_text(&p_sess->ftp_arg_str, "A N"))  {    p_sess->is_ascii = 1;    vsf_cmdio_write(p_sess, FTP_TYPEOK, "Switching to ASCII mode.");  }  else  {    vsf_cmdio_write(p_sess, FTP_BADCMD, "Unrecognised TYPE command.");  }}static voidhandle_port(struct vsf_session* p_sess){  unsigned short the_port;  unsigned char vals[6];  const unsigned char* p_raw;  pasv_cleanup(p_sess);  port_cleanup(p_sess);  p_raw = vsf_sysutil_parse_uchar_string_sep(&p_sess->ftp_arg_str, ',', vals,                                             sizeof(vals));

⌨️ 快捷键说明

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