示例#1
0
static void
handle_size(struct vsf_session* p_sess)
{
  /* Note - in ASCII mode, are supposed to return the size after taking into
   * account ASCII linefeed conversions. At least this is what wu-ftpd does in
   * version 2.6.1. Proftpd-1.2.0pre fails to do this.
   * I will not do it because it is a potential I/O DoS.
   */
  static struct vsf_sysutil_statbuf* s_p_statbuf;
  int retval;
  if (!vsf_access_check_file(&p_sess->ftp_arg_str))
  {
    vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied.");
    return;
  }
  retval = str_stat(&p_sess->ftp_arg_str, &s_p_statbuf);
  if (retval != 0 || !vsf_sysutil_statbuf_is_regfile(s_p_statbuf))
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Could not get file size.");
  }
  else
  {
    static struct mystr s_size_res_str;
    str_alloc_filesize_t(&s_size_res_str,
                         vsf_sysutil_statbuf_get_size(s_p_statbuf));
    vsf_cmdio_write_str(p_sess, FTP_SIZEOK, &s_size_res_str);
  }
}
示例#2
0
文件: filestr.c 项目: AllardJ/Tomato
int
str_fileread(struct mystr* p_str, const char* p_filename, unsigned int maxsize)
{
  int fd;
  int retval = 0;
  filesize_t size;
  char* p_sec_buf = 0;
  struct vsf_sysutil_statbuf* p_stat = 0;
  /* In case we fail, make sure we return an empty string */
  str_empty(p_str);
  fd = vsf_sysutil_open_file(p_filename, kVSFSysUtilOpenReadOnly);
  if (vsf_sysutil_retval_is_error(fd))
  {
    return fd;
  }
  vsf_sysutil_fstat(fd, &p_stat);
  if (vsf_sysutil_statbuf_is_regfile(p_stat))
  {
    size = vsf_sysutil_statbuf_get_size(p_stat);
    if (size > maxsize)
    {
      size = maxsize;
    }
    vsf_secbuf_alloc(&p_sec_buf, (unsigned int) size);

    retval = vsf_sysutil_read_loop(fd, p_sec_buf, (unsigned int) size);
    if (vsf_sysutil_retval_is_error(retval))
    {
      goto free_out;
    }
    else if ((unsigned int) retval != size)
    {
      die("read size mismatch");
    }
    str_alloc_memchunk(p_str, p_sec_buf, size);
  }
free_out:
  vsf_sysutil_free(p_stat);
  vsf_secbuf_free(&p_sec_buf);
  vsf_sysutil_close(fd);
  return retval;
}
示例#3
0
static filesize_t
calc_num_send(int file_fd, filesize_t init_offset)
{
  static struct vsf_sysutil_statbuf* s_p_statbuf;
  filesize_t bytes_to_send;
  /* Work out how many bytes to send based on file size minus current offset */
  vsf_sysutil_fstat(file_fd, &s_p_statbuf);
  bytes_to_send = vsf_sysutil_statbuf_get_size(s_p_statbuf);
  if (init_offset < 0 || bytes_to_send < 0)
  {
    die("calc_num_send: negative file offset or send count");
  }
  /* Don't underflow if some bonehead sets a REST greater than the file size */
  if (init_offset > bytes_to_send)
  {
    bytes_to_send = 0;
  }
  else
  {
    bytes_to_send -= init_offset;
  }
  return bytes_to_send;
}
示例#4
0
static void
handle_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 retval;
  int remote_fd;
  int opened_file;
  int is_ascii = 0;
  filesize_t offset = p_sess->restart_pos;
  p_sess->restart_pos = 0;
  if (!pasv_active(p_sess) && !port_active(p_sess))
  {
    vsf_cmdio_write(p_sess, FTP_BADSENDCONN, "Use PORT or PASV first.");
    return;
  }
  if (p_sess->is_ascii && offset != 0)
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL,
                    "No support for resume of ASCII transfer.");
    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;
  }
  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.");
    goto file_close_out;
  }
  /* 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);
  }
  remote_fd = get_remote_transfer_fd(p_sess);
  if (vsf_sysutil_retval_is_error(remote_fd))
  {
    goto port_pasv_cleanup_out;
  }
  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);
  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).");
  vsf_cmdio_write_str(p_sess, FTP_DATACONN, &s_mark_str);
  trans_ret = vsf_ftpdataio_transfer_file(p_sess, remote_fd,
                                          opened_file, 0, is_ascii);
  p_sess->transfer_size = trans_ret.transferred;
  retval = dispose_remote_transfer_fd(p_sess);
  /* Log _after_ the blocking dispose call, so we get transfer times right */
  if (trans_ret.retval == 0 && retval == 0)
  {
    vsf_log_do_log(p_sess, 1);
  }
  else
  {
    vsf_log_do_log(p_sess, 0);
  }
port_pasv_cleanup_out:
  port_cleanup(p_sess);
  pasv_cleanup(p_sess);
file_close_out:
  vsf_sysutil_close(opened_file);
}
示例#5
0
static void
build_dir_line(struct mystr* p_str, const struct mystr* p_filename_str,
               const struct vsf_sysutil_statbuf* p_stat, long curr_time)
{
    static struct mystr s_tmp_str;
    char *tmp_filename=NULL;
    filesize_t size = vsf_sysutil_statbuf_get_size(p_stat);
    /* Permissions */
    str_alloc_text(p_str, vsf_sysutil_statbuf_get_perms(p_stat));
    str_append_char(p_str, ' ');
    /* Hard link count */
    str_alloc_ulong(&s_tmp_str, vsf_sysutil_statbuf_get_links(p_stat));
    str_lpad(&s_tmp_str, 4);
    str_append_str(p_str, &s_tmp_str);
    str_append_char(p_str, ' ');
    /* User */
    if (tunable_hide_ids)
    {
        str_alloc_text(&s_tmp_str, "ftp");
    }
    else
    {
        int uid = vsf_sysutil_statbuf_get_uid(p_stat);
        struct vsf_sysutil_user* p_user = 0;
        if (tunable_text_userdb_names)
        {
            p_user = vsf_sysutil_getpwuid(uid);
        }
        if (p_user == 0)
        {
            str_alloc_ulong(&s_tmp_str, (unsigned long) uid);
        }
        else
        {
            str_alloc_text(&s_tmp_str, vsf_sysutil_user_getname(p_user));
        }
    }
    str_rpad(&s_tmp_str, 8);
    str_append_str(p_str, &s_tmp_str);
    str_append_char(p_str, ' ');
    /* Group */
    if (tunable_hide_ids)
    {
        str_alloc_text(&s_tmp_str, "ftp");
    }
    else
    {
        int gid = vsf_sysutil_statbuf_get_gid(p_stat);
        struct vsf_sysutil_group* p_group = 0;
        if (tunable_text_userdb_names)
        {
            p_group = vsf_sysutil_getgrgid(gid);
        }
        if (p_group == 0)
        {
            str_alloc_ulong(&s_tmp_str, (unsigned long) gid);
        }
        else
        {
            str_alloc_text(&s_tmp_str, vsf_sysutil_group_getname(p_group));
        }
    }
    str_rpad(&s_tmp_str, 8);
    str_append_str(p_str, &s_tmp_str);
    str_append_char(p_str, ' ');
    /* Size in bytes */
    str_alloc_filesize_t(&s_tmp_str, size);
    str_lpad(&s_tmp_str, 8);
    str_append_str(p_str, &s_tmp_str);
    str_append_char(p_str, ' ');
    /* Date stamp */
    str_append_text(p_str, vsf_sysutil_statbuf_get_date(p_stat,
                    tunable_use_localtime,
                    curr_time));
    str_append_char(p_str, ' ');
    /* Filename */
    tmp_filename = local2remote(str_getbuf(p_filename_str));
    if (tmp_filename == NULL)
        str_append_str(p_str, p_filename_str);
    else {
        str_append_text(p_str, tmp_filename);
        vsf_sysutil_free(tmp_filename);
    }
    str_append_text(p_str, "\r\n");
}