Beispiel #1
0
void
vsf_privop_do_file_chown(struct vsf_session* p_sess, int fd)
{
  static struct vsf_sysutil_statbuf* s_p_statbuf;
  vsf_sysutil_fstat(fd, &s_p_statbuf);
  /* Do nothing if it is already owned by the desired user. */
  if (vsf_sysutil_statbuf_get_uid(s_p_statbuf) ==
      p_sess->anon_upload_chown_uid)
  {
    return;
  }
  /* Drop it like a hot potato unless it's a regular file owned by
   * the the anonymous ftp user
   */
  if (p_sess->anon_upload_chown_uid == -1 ||
      !vsf_sysutil_statbuf_is_regfile(s_p_statbuf) ||
      (vsf_sysutil_statbuf_get_uid(s_p_statbuf) != p_sess->anon_ftp_uid &&
       vsf_sysutil_statbuf_get_uid(s_p_statbuf) != p_sess->guest_user_uid))
  {
    die("invalid fd in cmd_process_chown");
  }
  /* SECURITY! You need an OS which strips SUID/SGID bits on chown(),
   * otherwise a compromise of the FTP user will lead to compromise of
   * the "anon_upload_chown_uid" user (think chmod +s).
   */
  vsf_sysutil_fchown(fd, p_sess->anon_upload_chown_uid, -1);
}
static void
handle_per_user_config(const struct mystr* p_user_str)
{
  struct mystr filename_str = INIT_MYSTR;
  struct vsf_sysutil_statbuf* p_statbuf = 0;
  struct str_locate_result loc_result;
  int retval;
  if (!tunable_user_config_dir)
  {
    return;
  }
  /* Security paranoia - ignore if user has a / in it. */
  loc_result = str_locate_char(p_user_str, '/');
  if (loc_result.found)
  {
    return;
  }
  str_alloc_text(&filename_str, tunable_user_config_dir);
  str_append_char(&filename_str, '/');
  str_append_str(&filename_str, p_user_str);
  retval = str_stat(&filename_str, &p_statbuf);
  /* Security - ignore unless owned by root */
  if (!vsf_sysutil_retval_is_error(retval) &&
      vsf_sysutil_statbuf_get_uid(p_statbuf) == VSFTP_ROOT_UID)
  {
    vsf_parseconf_load_file(str_getbuf(&filename_str), 1);
  }
  str_free(&filename_str);
  vsf_sysutil_free(p_statbuf);
}
static void
handle_per_user_config(const struct mystr* p_user_str)
{
  if (tunable_user_config_dir)
  {
    struct mystr filename_str = INIT_MYSTR;
    struct vsf_sysutil_statbuf* p_statbuf = 0;
    int retval;
    str_alloc_text(&filename_str, tunable_user_config_dir);
    str_append_char(&filename_str, '/');
    str_append_str(&filename_str, p_user_str);
    retval = str_stat(&filename_str, &p_statbuf);
    /* Security - ignore unless owned by root */
    if (!vsf_sysutil_retval_is_error(retval) &&
        vsf_sysutil_statbuf_get_uid(p_statbuf) == VSFTP_ROOT_UID)
    {
      vsf_parseconf_load_file(str_getbuf(&filename_str));
    }
    str_free(&filename_str);
    vsf_sysutil_free(p_statbuf);
  }
}
Beispiel #4
0
void
vsf_parseconf_load_file(const char* p_filename, int errs_fatal)
{
  struct mystr config_file_str = INIT_MYSTR;
  struct mystr config_setting_str = INIT_MYSTR;
  struct mystr config_value_str = INIT_MYSTR;
  unsigned int str_pos = 0;
  int retval;
  if (!p_filename)
  {
    p_filename = s_p_saved_filename;
  }
  else
  {
    if (s_p_saved_filename)
    {
      vsf_sysutil_free((char*)s_p_saved_filename);
    }
    s_p_saved_filename = vsf_sysutil_strdup(p_filename);
  }
  if (!p_filename)
  {
    bug("null filename in vsf_parseconf_load_file");
  }
  retval = str_fileread(&config_file_str, p_filename, VSFTP_CONF_FILE_MAX);
  if (vsf_sysutil_retval_is_error(retval))
  {
    if (errs_fatal)
    {
      die2("cannot read config file: ", p_filename);
    }
    else
    {
      str_free(&config_file_str);
      return;
    }
  }
  {
    struct vsf_sysutil_statbuf* p_statbuf = 0;
    retval = vsf_sysutil_stat(p_filename, &p_statbuf);
    /* Security: check current user owns the config file. These are sanity
     * checks for the admin, and are NOT designed to be checks safe from
     * race conditions.
     */
    if (vsf_sysutil_retval_is_error(retval) ||
        vsf_sysutil_statbuf_get_uid(p_statbuf) != vsf_sysutil_getuid() ||
        !vsf_sysutil_statbuf_is_regfile(p_statbuf))
    {
      die("config file not owned by correct user, or not a file");
    }
    vsf_sysutil_free(p_statbuf);
  }
  while (str_getline(&config_file_str, &config_setting_str, &str_pos))
  {
    if (str_isempty(&config_setting_str) ||
        str_get_char_at(&config_setting_str, 0) == '#' ||
        str_all_space(&config_setting_str))
    {
      continue;
    }
    vsf_parseconf_load_setting(str_getbuf(&config_setting_str), errs_fatal);
  }
  str_free(&config_file_str);
  str_free(&config_setting_str);
  str_free(&config_value_str);
}
Beispiel #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");
}