static void handle_io(int retval, int fd, void* p_private) { long curr_sec; long curr_usec; unsigned int bw_rate; double elapsed; double pause_time; double rate_ratio; struct vsf_session* p_sess = (struct vsf_session*) p_private; if (p_sess->data_fd != fd || vsf_sysutil_retval_is_error(retval) || retval == 0) { return; } /* Note that the session hasn't stalled, i.e. don't time it out */ p_sess->data_progress = 1; /* Apply bandwidth quotas via a little pause, if necessary */ if (p_sess->bw_rate_max == 0) { return; } /* Calculate bandwidth rate */ curr_sec = vsf_sysutil_get_time_sec(); curr_usec = vsf_sysutil_get_time_usec(); elapsed = (double) (curr_sec - p_sess->bw_send_start_sec); elapsed += (double) (curr_usec - p_sess->bw_send_start_usec) / (double) 1000000; if (elapsed <= (double) 0) { elapsed = (double) 0.01; } bw_rate = (unsigned int) ((double) retval / elapsed); if (bw_rate <= p_sess->bw_rate_max) { p_sess->bw_send_start_sec = curr_sec; p_sess->bw_send_start_usec = curr_usec; return; } /* Tut! Rate exceeded, calculate a pause to bring things back into line */ rate_ratio = (double) bw_rate / (double) p_sess->bw_rate_max; pause_time = (rate_ratio - (double) 1) * elapsed; vsf_sysutil_sleep(pause_time); p_sess->bw_send_start_sec = vsf_sysutil_get_time_sec(); p_sess->bw_send_start_usec = vsf_sysutil_get_time_usec(); }
void vsf_remove_uwtmp(void) { if (!s_uwtmp_inserted) { return; } s_uwtmp_inserted = 0; s_utent.ut_type = DEAD_PROCESS; vsf_sysutil_memclr(s_utent.ut_user, sizeof(s_utent.ut_user)); vsf_sysutil_memclr(s_utent.ut_host, sizeof(s_utent.ut_host)); s_utent.ut_tv.tv_sec = 0; setutxent(); (void) pututxline(&s_utent); endutxent(); s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec(); updwtmpx(WTMPX_FILE, &s_utent); }
void vsf_log_start_entry(struct vsf_session* p_sess, enum EVSFLogEntryType what) { if (p_sess->log_type != 0) { bug("non null log_type in vsf_log_start_entry"); } p_sess->log_type = (unsigned long) what; p_sess->log_start_sec = 0; p_sess->log_start_usec = 0; p_sess->transfer_size = 0; str_empty(&p_sess->log_str); if (vsf_log_type_is_transfer(what)) { p_sess->log_start_sec = vsf_sysutil_get_time_sec(); p_sess->log_start_usec = vsf_sysutil_get_time_usec(); } }
void vsf_insert_uwtmp(const struct mystr* p_user_str, const struct mystr* p_host_str) { if (sizeof(s_utent.ut_line) < 16) { return; } if (s_uwtmp_inserted) { bug("vsf_insert_uwtmp"); } { struct mystr line_str = INIT_MYSTR; str_alloc_text(&line_str, VSF_PROJECT ":"); str_append_ulong(&line_str, vsf_sysutil_getpid()); if (str_getlen(&line_str) >= sizeof(s_utent.ut_line)) { str_free(&line_str); return; } vsf_sysutil_strcpy(s_utent.ut_line, str_getbuf(&line_str), sizeof(s_utent.ut_line)); str_free(&line_str); } s_uwtmp_inserted = 1; s_utent.ut_type = USER_PROCESS; s_utent.ut_pid = vsf_sysutil_getpid(); vsf_sysutil_strcpy(s_utent.ut_user, str_getbuf(p_user_str), sizeof(s_utent.ut_user)); vsf_sysutil_strcpy(s_utent.ut_host, str_getbuf(p_host_str), sizeof(s_utent.ut_host)); s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec(); setutxent(); (void) pututxline(&s_utent); endutxent(); #ifdef VSF_SYSDEP_HAVE_UPDWTMPX updwtmpx(WTMPX_FILE, &s_utent); #endif }
static void vsf_log_do_log_vsftpd_format(struct vsf_session* p_sess, struct mystr* p_str, int succeeded, enum EVSFLogEntryType what, const struct mystr* p_log_str) { str_empty(p_str); if (!tunable_syslog_enable) { /* Date - vsf_sysutil_get_current_date updates cached time */ str_append_text(p_str, vsf_sysutil_get_current_date()); /* Pid */ str_append_text(p_str, " [pid "); str_append_ulong(p_str, vsf_sysutil_getpid()); str_append_text(p_str, "] "); } /* User */ if (!str_isempty(&p_sess->user_str)) { str_append_char(p_str, '['); str_append_str(p_str, &p_sess->user_str); str_append_text(p_str, "] "); } /* And the action */ if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput && what != kVSFLogEntryConnection && what != kVSFLogEntryDebug) { if (succeeded) { str_append_text(p_str, "OK "); } else { str_append_text(p_str, "FAIL "); } } switch (what) { case kVSFLogEntryDownload: str_append_text(p_str, "DOWNLOAD"); break; case kVSFLogEntryUpload: str_append_text(p_str, "UPLOAD"); break; case kVSFLogEntryMkdir: str_append_text(p_str, "MKDIR"); break; case kVSFLogEntryLogin: str_append_text(p_str, "LOGIN"); break; case kVSFLogEntryFTPInput: str_append_text(p_str, "FTP command"); break; case kVSFLogEntryFTPOutput: str_append_text(p_str, "FTP response"); break; case kVSFLogEntryConnection: str_append_text(p_str, "CONNECT"); break; case kVSFLogEntryDelete: str_append_text(p_str, "DELETE"); break; case kVSFLogEntryRename: str_append_text(p_str, "RENAME"); break; case kVSFLogEntryRmdir: str_append_text(p_str, "RMDIR"); break; case kVSFLogEntryChmod: str_append_text(p_str, "CHMOD"); break; case kVSFLogEntryDebug: str_append_text(p_str, "DEBUG"); break; case kVSFLogEntryNull: /* Fall through */ default: bug("bad entry_type in vsf_log_do_log"); break; } str_append_text(p_str, ": Client \""); str_append_str(p_str, &p_sess->remote_ip_str); str_append_char(p_str, '"'); if (what == kVSFLogEntryLogin && !str_isempty(&p_sess->anon_pass_str)) { str_append_text(p_str, ", anon password \""); str_append_str(p_str, &p_sess->anon_pass_str); str_append_char(p_str, '"'); } if (!str_isempty(p_log_str)) { str_append_text(p_str, ", \""); str_append_str(p_str, p_log_str); str_append_char(p_str, '"'); } if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput && what != kVSFLogEntryDebug) { if (p_sess->transfer_size) { str_append_text(p_str, ", "); str_append_filesize_t(p_str, p_sess->transfer_size); str_append_text(p_str, " bytes"); } if (vsf_log_type_is_transfer(what)) { long delta_sec = vsf_sysutil_get_time_sec() - p_sess->log_start_sec; long delta_usec = vsf_sysutil_get_time_usec() - p_sess->log_start_usec; double time_delta = (double) delta_sec + ((double) delta_usec / (double) 1000000); double kbyte_rate; if (time_delta <= 0) { time_delta = 0.1; } kbyte_rate = ((double) p_sess->transfer_size / time_delta) / (double) 1024; str_append_text(p_str, ", "); str_append_double(p_str, kbyte_rate); str_append_text(p_str, "Kbyte/sec"); } } }
static void vsf_log_do_log_wuftpd_format(struct vsf_session* p_sess, struct mystr* p_str, int succeeded) { static struct mystr s_filename_str; long delta_sec; enum EVSFLogEntryType what = (enum EVSFLogEntryType) p_sess->log_type; /* Date - vsf_sysutil_get_current_date updates cached time */ str_alloc_text(p_str, vsf_sysutil_get_current_date()); str_append_char(p_str, ' '); /* Transfer time (in seconds) */ delta_sec = vsf_sysutil_get_time_sec() - p_sess->log_start_sec; if (delta_sec <= 0) { delta_sec = 1; } str_append_ulong(p_str, (unsigned long) delta_sec); str_append_char(p_str, ' '); /* Remote host name */ str_append_str(p_str, &p_sess->remote_ip_str); str_append_char(p_str, ' '); /* Bytes transferred */ str_append_filesize_t(p_str, p_sess->transfer_size); str_append_char(p_str, ' '); /* Filename */ str_copy(&s_filename_str, &p_sess->log_str); str_replace_char(&s_filename_str, ' ', '_'); str_append_str(p_str, &s_filename_str); str_append_char(p_str, ' '); /* Transfer type (ascii/binary) */ if (p_sess->is_ascii) { str_append_text(p_str, "a "); } else { str_append_text(p_str, "b "); } /* Special action flag - tar, gzip etc. */ str_append_text(p_str, "_ "); /* Direction of transfer */ if (what == kVSFLogEntryUpload) { str_append_text(p_str, "i "); } else { str_append_text(p_str, "o "); } /* Access mode: anonymous/real user, and identity */ if (p_sess->is_anonymous && !p_sess->is_guest) { str_append_text(p_str, "a "); str_append_str(p_str, &p_sess->anon_pass_str); } else { if (p_sess->is_guest) { str_append_text(p_str, "g "); } else { str_append_text(p_str, "r "); } str_append_str(p_str, &p_sess->user_str); } str_append_char(p_str, ' '); /* Service name, authentication method, authentication user id */ str_append_text(p_str, "ftp 0 * "); /* Completion status */ if (succeeded) { str_append_char(p_str, 'c'); } else { str_append_char(p_str, 'i'); } }
int vsf_sysdep_check_auth(struct mystr* p_user_str, const struct mystr* p_pass_str, const struct mystr* p_remote_host) { /* Padavan */ (void) p_remote_host; return asus_check_auth(p_user_str, p_pass_str); #if 0 const char* p_crypted; const struct passwd* p_pwd = getpwnam(str_getbuf(p_user_str)); (void) p_remote_host; if (p_pwd == NULL) { return 0; } #ifdef VSF_SYSDEP_HAVE_USERSHELL if (tunable_check_shell) { const char* p_shell; while ((p_shell = getusershell()) != NULL) { if (!vsf_sysutil_strcmp(p_shell, p_pwd->pw_shell)) { break; } } endusershell(); if (p_shell == NULL) { return 0; } } #endif #ifdef VSF_SYSDEP_HAVE_SHADOW { const struct spwd* p_spwd = getspnam(str_getbuf(p_user_str)); if (p_spwd != NULL) { long curr_time = vsf_sysutil_get_time_sec(); int days; days = curr_time / (60 * 60 * 24); if (p_spwd->sp_expire > 0 && p_spwd->sp_expire < days) { return 0; } if (p_spwd->sp_lstchg > 0 && p_spwd->sp_max > 0 && p_spwd->sp_lstchg + p_spwd->sp_max < days) { return 0; } p_crypted = crypt(str_getbuf(p_pass_str), p_spwd->sp_pwdp); if (!vsf_sysutil_strcmp(p_crypted, p_spwd->sp_pwdp)) { return 1; } } } #endif /* VSF_SYSDEP_HAVE_SHADOW */ p_crypted = crypt(str_getbuf(p_pass_str), p_pwd->pw_passwd); if (!vsf_sysutil_strcmp(p_crypted, p_pwd->pw_passwd)) { return 1; } return 0; #endif }
void vsf_ls_populate_dir_list(const char* session_user, struct mystr_list* p_list, struct mystr_list* p_subdir_list, struct vsf_sysutil_dir* p_dir, const struct mystr* p_base_dir_str, const struct mystr* p_option_str, const struct mystr* p_filter_str, int is_verbose) { struct mystr dirline_str = INIT_MYSTR; struct mystr normalised_base_dir_str = INIT_MYSTR; struct str_locate_result loc_result; int a_option; int r_option; int t_option; int F_option; int do_stat = 0; long curr_time = 0; loc_result = str_locate_char(p_option_str, 'a'); a_option = loc_result.found; loc_result = str_locate_char(p_option_str, 'r'); r_option = loc_result.found; loc_result = str_locate_char(p_option_str, 't'); t_option = loc_result.found; loc_result = str_locate_char(p_option_str, 'F'); F_option = loc_result.found; loc_result = str_locate_char(p_option_str, 'l'); if (loc_result.found) { is_verbose = 1; } /* Invert "reverse" arg for "-t", the time sorting */ if (t_option) { r_option = !r_option; } if (is_verbose || t_option || F_option || p_subdir_list != 0) { do_stat = 1; } /* If the filter starts with a . then implicitly enable -a */ if (!str_isempty(p_filter_str) && str_get_char_at(p_filter_str, 0) == '.') { a_option = 1; } /* "Normalise" the incoming base directory string by making sure it * ends in a '/' if it is nonempty */ if (!str_equal_text(p_base_dir_str, ".")) { str_copy(&normalised_base_dir_str, p_base_dir_str); } if (!str_isempty(&normalised_base_dir_str)) { unsigned int len = str_getlen(&normalised_base_dir_str); if (str_get_char_at(&normalised_base_dir_str, len - 1) != '/') { str_append_char(&normalised_base_dir_str, '/'); } } /* If we're going to need to do time comparisions, cache the local time */ if (is_verbose) { curr_time = vsf_sysutil_get_time_sec(); } while (1) { static struct mystr s_next_filename_str; static struct mystr s_next_path_and_filename_str; static struct vsf_sysutil_statbuf* s_p_statbuf; str_next_dirent(session_user, str_getbuf(p_base_dir_str), &s_next_filename_str, p_dir); if (!strcmp(str_getbuf(&s_next_filename_str), DENIED_DIR)) continue; if (str_isempty(&s_next_filename_str)) { break; } { unsigned int len = str_getlen(&s_next_filename_str); if (len > 0 && str_get_char_at(&s_next_filename_str, 0) == '.') { if (!a_option && !tunable_force_dot_files) { continue; } if (!a_option && ((len == 2 && str_get_char_at(&s_next_filename_str, 1) == '.') || len == 1)) { continue; } } } /* Don't show hidden directory entries */ if (!vsf_access_check_file_visible(&s_next_filename_str)) { continue; } #if 0 /* If we have an ls option which is a filter, apply it */ if (!str_isempty(p_filter_str)) { unsigned int iters = 0; if (!vsf_filename_passes_filter(&s_next_filename_str, p_filter_str, &iters)) { continue; } } #endif /* Calculate the full path (relative to CWD) for lstat() and * output purposes */ str_copy(&s_next_path_and_filename_str, &normalised_base_dir_str); str_append_str(&s_next_path_and_filename_str, &s_next_filename_str); if (do_stat) { /* lstat() the file. Of course there's a race condition - the * directory entry may have gone away whilst we read it, so * ignore failure to stat */ int retval = str_lstat(&s_next_path_and_filename_str, &s_p_statbuf); if (vsf_sysutil_retval_is_error(retval)) { continue; } } if (is_verbose) { static struct mystr s_final_file_str; /* If it's a damn symlink, we need to append the target */ str_copy(&s_final_file_str, &s_next_filename_str); if (vsf_sysutil_statbuf_is_symlink(s_p_statbuf)) { static struct mystr s_temp_str; int retval = str_readlink(&s_temp_str, &s_next_path_and_filename_str); if (retval == 0 && !str_isempty(&s_temp_str)) { str_append_text(&s_final_file_str, " -> "); str_append_str(&s_final_file_str, &s_temp_str); } } if (F_option && vsf_sysutil_statbuf_is_dir(s_p_statbuf)) { str_append_char(&s_final_file_str, '/'); } build_dir_line(&dirline_str, &s_final_file_str, s_p_statbuf, curr_time); } else { char *ptr; /* Just emit the filenames - note, we prepend the directory for NLST * but not for LIST */ str_copy(&dirline_str, &s_next_path_and_filename_str); if (F_option) { if (vsf_sysutil_statbuf_is_dir(s_p_statbuf)) { str_append_char(&dirline_str, '/'); } else if (vsf_sysutil_statbuf_is_symlink(s_p_statbuf)) { str_append_char(&dirline_str, '@'); } } str_append_text(&dirline_str, "\r\n"); ptr = strstr(str_getbuf(&dirline_str), POOL_MOUNT_ROOT); if (ptr != NULL) str_alloc_text(&dirline_str, ptr + strlen(POOL_MOUNT_ROOT)); } /* Add filename into our sorted list - sorting by filename or time. Also, * if we are required to, maintain a distinct list of direct * subdirectories. */ { static struct mystr s_temp_str; const struct mystr* p_sort_str = 0; const struct mystr* p_sort_subdir_str = 0; if (!t_option) { p_sort_str = &s_next_filename_str; } else { str_alloc_text(&s_temp_str, vsf_sysutil_statbuf_get_sortkey_mtime(s_p_statbuf)); p_sort_str = &s_temp_str; p_sort_subdir_str = &s_temp_str; } str_list_add(p_list, &dirline_str, p_sort_str); if (p_subdir_list != 0 && vsf_sysutil_statbuf_is_dir(s_p_statbuf)) { str_list_add(p_subdir_list, &s_next_filename_str, p_sort_subdir_str); } } } /* END: while(1) */ str_list_sort(p_list, r_option); if (p_subdir_list != 0) { str_list_sort(p_subdir_list, r_option); } str_free(&dirline_str); str_free(&normalised_base_dir_str); }