static void handle_mdtm(struct vsf_session* p_sess) { 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 modification time."); } else { static struct mystr s_mdtm_res_str; str_alloc_text(&s_mdtm_res_str, vsf_sysutil_statbuf_get_numeric_date( s_p_statbuf, tunable_use_localtime)); vsf_cmdio_write_str(p_sess, FTP_MDTMOK, &s_mdtm_res_str); } }
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); } }
static void handle_rnfr(struct vsf_session* p_sess) { static struct vsf_sysutil_statbuf* p_statbuf; int retval; /* Clear old value */ str_free(&p_sess->rnfr_filename_str); if (!vsf_access_check_file(&p_sess->ftp_arg_str)) { vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied."); return; } /* Does it exist? */ retval = str_stat(&p_sess->ftp_arg_str, &p_statbuf); if (retval == 0) { /* Yes */ str_copy(&p_sess->rnfr_filename_str, &p_sess->ftp_arg_str); vsf_cmdio_write(p_sess, FTP_RNFROK, "Ready for RNTO."); } else { vsf_cmdio_write(p_sess, FTP_FILEFAIL, "RNFR command failed."); } }
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); if (!vsf_sysutil_retval_is_error(retval)) { /* Security - file ownership check now in vsf_parseconf_load_file() */ vsf_parseconf_load_file(str_getbuf(&filename_str), 1); } else if (vsf_sysutil_get_error() != kVSFSysUtilErrNOENT) { die("error opening per-user config file"); } str_free(&filename_str); vsf_sysutil_free(p_statbuf); }
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 get_unique_filename(struct mystr* p_outstr, const struct mystr* p_base_str) { /* Use silly wu-ftpd algorithm for compatibility */ static struct vsf_sysutil_statbuf* s_p_statbuf; unsigned int suffix = 1; int retval; while (1) { str_copy(p_outstr, p_base_str); str_append_char(p_outstr, '.'); str_append_ulong(p_outstr, suffix); retval = str_stat(p_outstr, &s_p_statbuf); if (vsf_sysutil_retval_is_error(retval)) { return; } ++suffix; } }
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); } }