static void process_post_login_req(struct vsf_session* p_sess) { char cmd; vsf_sysutil_unblock_sig(kVSFSysUtilSigCHLD); vsf_sysutil_kitsune_set_update_point(NULL); /* Kitsune */ /* Blocks */ cmd = priv_sock_get_cmd(p_sess->parent_fd); vsf_sysutil_block_sig(kVSFSysUtilSigCHLD); if (tunable_chown_uploads && cmd == PRIV_SOCK_CHOWN) { cmd_process_chown(p_sess); } else if (tunable_connect_from_port_20 && cmd == PRIV_SOCK_GET_DATA_SOCK) { cmd_process_get_data_sock(p_sess); } else { die("bad request in process_post_login_req"); } }
struct vsf_client_launch vsf_standalone_main(void) { struct vsf_sysutil_sockaddr* p_accept_addr = 0; int listen_sock = -1; int retval; s_ipaddr_size = vsf_sysutil_get_ipaddr_size(); if (tunable_listen && tunable_listen_ipv6) { die("run two copies of vsftpd for IPv4 and IPv6"); } if (tunable_background) { int forkret = vsf_sysutil_fork(); if (forkret > 0) { /* Parent, just exit */ vsf_sysutil_exit(0); } vsf_sysutil_make_session_leader(); } if (tunable_listen) { listen_sock = vsf_sysutil_get_ipv4_sock(); } else { listen_sock = vsf_sysutil_get_ipv6_sock(); } vsf_sysutil_activate_reuseaddr(listen_sock); s_p_ip_count_hash = hash_alloc(256, s_ipaddr_size, sizeof(unsigned int), hash_ip); s_p_pid_ip_hash = hash_alloc(256, sizeof(int), s_ipaddr_size, hash_pid); if (tunable_setproctitle_enable) { vsf_sysutil_setproctitle("LISTENER"); } vsf_sysutil_install_async_sighandler(kVSFSysUtilSigCHLD, handle_sigchld); vsf_sysutil_install_async_sighandler(kVSFSysUtilSigHUP, handle_sighup); if (tunable_listen) { struct vsf_sysutil_sockaddr* p_sockaddr = 0; vsf_sysutil_sockaddr_alloc_ipv4(&p_sockaddr); vsf_sysutil_sockaddr_set_port(p_sockaddr, tunable_listen_port); if (!tunable_listen_address) { vsf_sysutil_sockaddr_set_any(p_sockaddr); } else { if (!vsf_sysutil_inet_aton(tunable_listen_address, p_sockaddr)) { die2("bad listen_address: ", tunable_listen_address); } } retval = vsf_sysutil_bind(listen_sock, p_sockaddr); vsf_sysutil_free(p_sockaddr); if (vsf_sysutil_retval_is_error(retval)) { die("could not bind listening IPv4 socket"); } } else { struct vsf_sysutil_sockaddr* p_sockaddr = 0; vsf_sysutil_sockaddr_alloc_ipv6(&p_sockaddr); vsf_sysutil_sockaddr_set_port(p_sockaddr, tunable_listen_port); if (!tunable_listen_address6) { vsf_sysutil_sockaddr_set_any(p_sockaddr); } else { struct mystr addr_str = INIT_MYSTR; const unsigned char* p_raw_addr; str_alloc_text(&addr_str, tunable_listen_address6); p_raw_addr = vsf_sysutil_parse_ipv6(&addr_str); str_free(&addr_str); if (!p_raw_addr) { die2("bad listen_address6: ", tunable_listen_address6); } vsf_sysutil_sockaddr_set_ipv6addr(p_sockaddr, p_raw_addr); } retval = vsf_sysutil_bind(listen_sock, p_sockaddr); vsf_sysutil_free(p_sockaddr); if (vsf_sysutil_retval_is_error(retval)) { die("could not bind listening IPv6 socket"); } } vsf_sysutil_listen(listen_sock, VSFTP_LISTEN_BACKLOG); vsf_sysutil_sockaddr_alloc(&p_accept_addr); while (1) { struct vsf_client_launch child_info; void* p_raw_addr; int new_child; int new_client_sock; vsf_sysutil_unblock_sig(kVSFSysUtilSigCHLD); vsf_sysutil_unblock_sig(kVSFSysUtilSigHUP); new_client_sock = vsf_sysutil_accept_timeout( listen_sock, p_accept_addr, 0); vsf_sysutil_block_sig(kVSFSysUtilSigCHLD); vsf_sysutil_block_sig(kVSFSysUtilSigHUP); if (vsf_sysutil_retval_is_error(new_client_sock)) { continue; } ++s_children; child_info.num_children = s_children; child_info.num_this_ip = 0; p_raw_addr = vsf_sysutil_sockaddr_get_raw_addr(p_accept_addr); child_info.num_this_ip = handle_ip_count(p_raw_addr); new_child = vsf_sysutil_fork_failok(); if (new_child != 0) { /* Parent context */ vsf_sysutil_close(new_client_sock); if (new_child > 0) { hash_add_entry(s_p_pid_ip_hash, (void*)&new_child, p_raw_addr); } else { /* fork() failed, clear up! */ --s_children; drop_ip_count(p_raw_addr); } /* Fall through to while() loop and accept() again */ } else { /* Child context */ vsf_sysutil_close(listen_sock); prepare_child(new_client_sock); /* By returning here we "launch" the child process with the same * contract as xinetd would provide. */ return child_info; } } }
static void process_login_req(struct vsf_session* p_sess) { enum EVSFPrivopLoginResult e_login_result = kVSFLoginNull; char cmd; vsf_sysutil_unblock_sig(kVSFSysUtilSigCHLD); /* Blocks */ cmd = priv_sock_get_cmd(p_sess); vsf_sysutil_block_sig(kVSFSysUtilSigCHLD); if (cmd != PRIV_SOCK_LOGIN) { die("bad request"); } /* Get username and password - we must distrust these */ { struct mystr password_str = INIT_MYSTR; priv_sock_get_str(p_sess, &p_sess->user_str); priv_sock_get_str(p_sess, &password_str); e_login_result = vsf_privop_do_login(p_sess, &password_str); str_free(&password_str); } switch (e_login_result) { case kVSFLoginFail: priv_sock_send_result(p_sess, PRIV_SOCK_RESULT_BAD); return; break; case kVSFLoginAnon: str_alloc_text(&p_sess->user_str, tunable_ftp_username); common_do_login(p_sess, &p_sess->user_str, 1, 1); break; case kVSFLoginReal: { int do_chroot = 0; if (tunable_chroot_local_user) { do_chroot = 1; } if (tunable_chroot_list_enable) { struct mystr chroot_list_file = INIT_MYSTR; int retval = str_fileread(&chroot_list_file, tunable_chroot_list_file, VSFTP_CONF_FILE_MAX); if (vsf_sysutil_retval_is_error(retval)) { die2("could not open chroot() list file:", tunable_chroot_list_file); } if (str_contains_line(&chroot_list_file, &p_sess->user_str)) { if (do_chroot) { do_chroot = 0; } else { do_chroot = 1; } } str_free(&chroot_list_file); } common_do_login(p_sess, &p_sess->user_str, do_chroot, 0); } break; default: bug("weird state in process_login_request"); break; } /* NOTREACHED */ }