?? postlogin.c
字號:
* 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; resolve_tilde(&p_sess->ftp_arg_str, p_sess); 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 voidhandle_site(struct vsf_session* p_sess){ static struct mystr s_site_args_str; /* What SITE sub-command is it? */ str_split_char(&p_sess->ftp_arg_str, &s_site_args_str, ' '); str_upper(&p_sess->ftp_arg_str); if (tunable_write_enable && tunable_chmod_enable && str_equal_text(&p_sess->ftp_arg_str, "CHMOD")) { handle_site_chmod(p_sess, &s_site_args_str); } else if (str_equal_text(&p_sess->ftp_arg_str, "UMASK")) { handle_site_umask(p_sess, &s_site_args_str); } else if (str_equal_text(&p_sess->ftp_arg_str, "HELP")) { vsf_cmdio_write(p_sess, FTP_SITEHELP, "CHMOD UMASK HELP"); } else { vsf_cmdio_write(p_sess, FTP_BADCMD, "Unknown SITE command."); }}static voidhandle_site_chmod(struct vsf_session* p_sess, struct mystr* p_arg_str){ static struct mystr s_chmod_file_str; unsigned int perms; int retval; if (str_isempty(p_arg_str)) { vsf_cmdio_write(p_sess, FTP_BADCMD, "SITE CHMOD needs 2 arguments."); return; } str_split_char(p_arg_str, &s_chmod_file_str, ' '); if (str_isempty(&s_chmod_file_str)) { vsf_cmdio_write(p_sess, FTP_BADCMD, "SITE CHMOD needs 2 arguments."); return; } resolve_tilde(&s_chmod_file_str, p_sess); vsf_log_start_entry(p_sess, kVSFLogEntryChmod); str_copy(&p_sess->log_str, &s_chmod_file_str); prepend_path_to_filename(&p_sess->log_str); str_append_char(&p_sess->log_str, ' '); str_append_str(&p_sess->log_str, p_arg_str); if (!vsf_access_check_file(&s_chmod_file_str)) { vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied."); return; } /* Don't worry - our chmod() implementation only allows 0 - 0777 */ perms = str_octal_to_uint(p_arg_str); retval = str_chmod(&s_chmod_file_str, perms); if (vsf_sysutil_retval_is_error(retval)) { vsf_cmdio_write(p_sess, FTP_FILEFAIL, "SITE CHMOD command failed."); } else { vsf_log_do_log(p_sess, 1); vsf_cmdio_write(p_sess, FTP_CHMODOK, "SITE CHMOD command ok."); }}static voidhandle_site_umask(struct vsf_session* p_sess, struct mystr* p_arg_str){ static struct mystr s_umask_resp_str; if (str_isempty(p_arg_str)) { /* Empty arg => report current umask */ str_alloc_text(&s_umask_resp_str, "Your current UMASK is "); str_append_text(&s_umask_resp_str, vsf_sysutil_uint_to_octal(vsf_sysutil_get_umask())); } else { /* Set current umask */ unsigned int new_umask = str_octal_to_uint(p_arg_str); vsf_sysutil_set_umask(new_umask); str_alloc_text(&s_umask_resp_str, "UMASK set to "); str_append_text(&s_umask_resp_str, vsf_sysutil_uint_to_octal(vsf_sysutil_get_umask())); } vsf_cmdio_write_str(p_sess, FTP_UMASKOK, &s_umask_resp_str);}static voidhandle_appe(struct vsf_session* p_sess){ handle_upload_common(p_sess, 1, 0);}static voidhandle_mdtm(struct vsf_session* p_sess){ static struct mystr s_filename_str; static struct vsf_sysutil_statbuf* s_p_statbuf; int do_write = 0; long modtime = 0; struct str_locate_result loc = str_locate_char(&p_sess->ftp_arg_str, ' '); int retval = str_stat(&p_sess->ftp_arg_str, &s_p_statbuf); if (tunable_mdtm_write && retval != 0 && loc.found && vsf_sysutil_isdigit(str_get_char_at(&p_sess->ftp_arg_str, 0))) { if (loc.index == 8 || loc.index == 14 || (loc.index > 15 && str_get_char_at(&p_sess->ftp_arg_str, 14) == '.')) { do_write = 1; } } if (do_write != 0) { str_split_char(&p_sess->ftp_arg_str, &s_filename_str, ' '); modtime = vsf_sysutil_parse_time(str_getbuf(&p_sess->ftp_arg_str)); str_copy(&p_sess->ftp_arg_str, &s_filename_str); } resolve_tilde(&p_sess->ftp_arg_str, p_sess); if (!vsf_access_check_file(&p_sess->ftp_arg_str)) { vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied."); return; } if (do_write && tunable_write_enable && (tunable_anon_other_write_enable || !p_sess->is_anonymous)) { 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 set file modification time."); } else { retval = vsf_sysutil_setmodtime( str_getbuf(&p_sess->ftp_arg_str), modtime, tunable_use_localtime); if (retval != 0) { vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Could not set file modification time."); } else { vsf_cmdio_write(p_sess, FTP_MDTMOK, "File modification time set."); } } } else { 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 voidhandle_eprt(struct vsf_session* p_sess){ static struct mystr s_part1_str; static struct mystr s_part2_str; int proto; int port; const unsigned char* p_raw_addr; int is_ipv6 = vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr); port_cleanup(p_sess); pasv_cleanup(p_sess); str_copy(&s_part1_str, &p_sess->ftp_arg_str); str_split_char(&s_part1_str, &s_part2_str, '|'); if (!str_isempty(&s_part1_str)) { goto bad_eprt; } /* Split out the protocol and check it */ str_split_char(&s_part2_str, &s_part1_str, '|'); proto = str_atoi(&s_part2_str); if (proto < 1 || proto > 2 || (!is_ipv6 && proto == 2)) { vsf_cmdio_write(p_sess, FTP_BADCMD, "Bad EPRT protocol."); return; } /* Split out address and parse it */ str_split_char(&s_part1_str, &s_part2_str, '|'); if (proto == 2) { p_raw_addr = vsf_sysutil_parse_ipv6(&s_part1_str); } else { p_raw_addr = vsf_sysutil_parse_ipv4(&s_part1_str); } if (!p_raw_addr) { goto bad_eprt; } /* Split out port and parse it */ str_split_char(&s_part2_str, &s_part1_str, '|'); if (!str_isempty(&s_part1_str) || str_isempty(&s_part2_str)) { goto bad_eprt; } port = str_atoi(&s_part2_str); if (port < 0 || port > 65535) { goto bad_eprt; } vsf_sysutil_sockaddr_clone(&p_sess->p_port_sockaddr, p_sess->p_local_addr); if (proto == 2) { vsf_sysutil_sockaddr_set_ipv6addr(p_sess->p_port_sockaddr, p_raw_addr); } else { vsf_sysutil_sockaddr_set_ipv4addr(p_sess->p_port_sockaddr, p_raw_addr); } vsf_sysutil_sockaddr_set_port(p_sess->p_port_sockaddr, (unsigned short) port); /* SECURITY: * 1) Reject requests not connecting to the control socket IP * 2) Reject connects to privileged ports */ if (!tunable_port_promiscuous) { if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr, p_sess->p_port_sockaddr) || vsf_sysutil_is_port_reserved(port)) { vsf_cmdio_write(p_sess, FTP_BADCMD, "Illegal EPRT command."); port_cleanup(p_sess); return; } } vsf_cmdio_write(p_sess, FTP_EPRTOK, "EPRT command successful. Consider using EPSV."); return;bad_eprt: vsf_cmdio_write(p_sess, FTP_BADCMD, "Bad EPRT command.");}/* XXX - add AUTH etc. */static voidhandle_help(struct vsf_session* p_sess){ vsf_cmdio_write_hyphen(p_sess, FTP_HELP, "The following commands are recognized."); vsf_cmdio_write_raw(p_sess," ABOR ACCT ALLO APPE CDUP CWD DELE EPRT EPSV FEAT HELP LIST MDTM MKD\r\n"); vsf_cmdio_write_raw(p_sess," MODE NLST NOOP OPTS PASS PASV PORT PWD QUIT REIN REST RETR RMD RNFR\r\n"); vsf_cmdio_write_raw(p_sess," RNTO SITE SIZE SMNT STAT STOR STOU STRU SYST TYPE USER XCUP XCWD XMKD\r\n"); vsf_cmdio_write_raw(p_sess," XPWD XRMD\r\n"); vsf_cmdio_write(p_sess, FTP_HELP, "Help OK.");}static voidhandle_stou(struct vsf_session* p_sess){ handle_upload_common(p_sess, 0, 1);}static voidget_unique_filename(struct mystr* p_outstr, const struct mystr* p_base_str){ /* Use silly wu-ftpd algorithm for compatibility. It has races of course, if * two sessions are using the same file prefix at the same time. */ 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 voidhandle_stat(struct vsf_session* p_sess){ vsf_cmdio_write_hyphen(p_sess, FTP_STATOK, "FTP server status:"); vsf_cmdio_write_raw(p_sess, " Connected to "); vsf_cmdio_write_raw(p_sess, str_getbuf(&p_sess->remote_ip_str)); vsf_cmdio_write_raw(p_sess, "\r\n"); vsf_cmdio_write_raw(p_sess, " Logged in as "); vsf_cmdio_write_raw(p_sess, str_getbuf(&p_sess->user_str)); vsf_cmdio_write_raw(p_sess, "\r\n"); vsf_cmdio_write_raw(p_sess, " TYPE: "); if (p_sess->is_ascii) { vsf_cmdio_write_raw(p_sess, "ASCII\r\n"); } else { vsf_cmdio_write_raw(p_sess, "BINARY\r\n"); } if (p_sess->bw_rate_max == 0) { vsf_cmdio_write_raw(p_sess, " No session bandwidth limit\r\n"); } else { vsf_cmdio_write_raw(p_sess, " Session bandwidth limit in byte/s is "); vsf_cmdio_write_raw(p_sess, vsf_sysutil_ulong_to_str(p_sess->bw_rate_max)); vsf_cmdio_write_raw(p_sess, "\r\n"); } if (tunable_idle_session_timeout == 0) { vsf_cmdio_write_raw(p_sess, " No session timeout\r\n"); } else { vsf_cmdio_write_raw(p_sess, " Session timeout in seconds is "); vsf_cmdio_write_raw(p_sess, vsf_sysutil_ulong_to_str(tunable_idle_session_timeout)); vsf_cmdio_write_raw(p_sess, "\r\n"); } if (p_sess->control_use_ssl) { vsf_cmdio_write_raw(p_sess, " Control connection is encrypted\r\n"); } else { vsf_cmdio_write_raw(p_sess, " Control connection is plain text\r\n"); } if (p_sess->data_use_ssl) { vsf_cmdio_write_raw(p_sess, " Data connections will be encrypted\r\n"); } else { vsf_cmdio_write_raw(p_sess, " Data connections will be plain text\r\n"); } if (p_sess->num_clients > 0) { vsf_cmdio_write_raw(p_sess, " At session startup, client count was "); vsf_cmdio_write_raw(p_sess, vsf_sysutil_ulong_to_str(p_sess->num_clients)); vsf_cmdio_write_raw(p_sess, "\r\n"); } vsf_cmdio_write_raw(p_sess, " vsFTPd " VSF_VERSION " - secure, fast, stable\r\n"); vsf_cmdio_write(p_sess, FTP_STATOK, "End of status");}static voidhandle_stat_file(struct vsf_session* p_sess){ handle_dir_common(p_sess, 1, 1);}static intdata_transfer_checks_ok(struct vsf_session* p_sess){ if (!pasv_active(p_sess) && !port_active(p_sess)) { vsf_cmdio_write(p_sess, FTP_BADSENDCONN, "Use PORT or PASV first."); return 0; } if (tunable_ssl_enable && !p_sess->data_use_ssl && ((tunable_force_local_data_ssl && !p_sess->is_anonymous) || (tunable_force_anon_data_ssl && p_sess->is_anonymous))) { vsf_cmdio_write( p_sess, FTP_NEEDENCRYPT, "Data connections must be encrypted."); return 0; } return 1;}static voidresolve_tilde(struct mystr* p_str, struct vsf_session* p_sess){ unsigned int len = str_getlen(p_str); if (len > 0 && str_get_char_at(p_str, 0) == '~') { static struct mystr s_rhs_str; if (len == 1 || str_get_char_at(p_str, 1) == '/') { str_split_char(p_str, &s_rhs_str, '~'); str_copy(p_str, &p_sess->home_str); str_append_str(p_str, &s_rhs_str); } else if (tunable_tilde_user_enable && len > 1) { static struct mystr s_user_str; struct vsf_sysutil_user* p_user; str_copy(&s_rhs_str, p_str); str_split_char(&s_rhs_str, &s_user_str, '~'); str_split_char(&s_user_str, &s_rhs_str, '/'); p_user = str_getpwnam(&s_user_str); if (p_user != 0) { str_alloc_text(p_str, vsf_sysutil_user_get_homedir(p_user)); if (!str_isempty(&s_rhs_str)) { str_append_char(p_str, '/'); str_append_str(p_str, &s_rhs_str); } } } }}static void handle_logged_in_user(struct vsf_session* p_sess){ if (p_sess->is_anonymous) { vsf_cmdio_write(p_sess, FTP_LOGINERR, "Can't change from guest user."); } else if (str_equal(&p_sess->user_str, &p_sess->ftp_arg_str)) { vsf_cmdio_write(p_sess, FTP_GIVEPWORD, "Any password will do."); } else { vsf_cmdio_write(p_sess, FTP_LOGINERR, "Can't change to another user."); }}static void handle_logged_in_pass(struct vsf_session* p_sess){ vsf_cmdio_write(p_sess, FTP_LOGINOK, "Already logged in.");}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -