void begin_session(session_t *sess) { /*开启接收带外数据*/ activate_oobinline(sess->ctrl_fd); /* int sockfds[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds) < 0) { ERR_EXIT("socketpair"); } */ /*初始化内部进程间通讯通道*/ priv_sock_init(sess); pid_t pid; pid = fork(); if (pid < 0) { ERR_EXIT("fork"); } if (pid == 0) { //ftp服务进程 /* close(sockfds[0]); sess->child_fd = sockfds[1]; */ /*设置子进程环境*/ priv_sock_set_child_context(sess); handle_child(sess); } else { //nobody进程 /* close(sockfds[1]); sess->parent_fd = sockfds[0]; */ /*设置父进程环境*/ priv_sock_set_parent_context(sess); handle_parent(sess); } }
void begin_session(session_t* psess) { priv_sock_init(psess); pid_t pid = fork(); if (pid == -1) ERR_EXIT("fork"); if (pid == 0) {//服务进程 priv_sock_set_child_context(psess); handle_child(psess); } else if(pid > 0) {//nobody进程 priv_sock_set_parent_context(psess); handle_parent(psess); } }
void begin_session(session_t *sess) { activate_oobinline(sess->ctrl_fd); priv_sock_init(sess); pid_t pid; pid = fork(); if(pid < 0) ERR_EXIT("fork"); if(pid == 0) { /* ftp process */ priv_sock_set_child_context(sess); handle_child(sess); }else { /* nobody process */ priv_sock_set_parent_context(sess); handle_parent(sess); } }
void begin_session(session_t *sess) { /* struct passwd *pw = getpwnam("nobody"); if(pw == NULL) return; if(setegid(pw->pw_gid) < 0) ERR_EXIT("setegid"); if(seteuid(pw->pw_uid) < 0) ERR_EXIT("seteuid");*/ int sockfds[2]; if(socketpair(PF_UNIX, SOCK_STREAM, 0, sockfds) < 0) ERR_EXIT("sockpair"); priv_sock_init(sess); pid_t pid; pid = fork(); if(pid < 0) ERR_EXIT("fork"); if (pid == 0) { /* close(sockfds[0]); sess->parent_fd = sockfds[1];*/ priv_sock_set_child_context(sess); handle_child(sess); } else { /* close(sockfds[1]); sess->child_fd = sockfds[0];*/ priv_sock_set_parent_context(sess); handle_parent(sess); } }
void vsf_two_process_start(struct vsf_session* p_sess) { vsf_sysutil_install_sighandler(kVSFSysUtilSigTERM, handle_sigterm, 0, 1); /* Overrides the SIGKILL setting set by the standalone listener. */ vsf_set_term_if_parent_dies(); /* Create the comms channel between privileged parent and no-priv child */ priv_sock_init(p_sess); if (tunable_ssl_enable) { /* Create the comms channel between the no-priv SSL child and the low-priv * protocol handling child. */ ssl_comm_channel_init(p_sess); } vsf_sysutil_install_sighandler(kVSFSysUtilSigCHLD, handle_sigchld, 0, 1); { int newpid; if (tunable_isolate_network) { newpid = vsf_sysutil_fork_newnet(); } else { newpid = vsf_sysutil_fork(); } if (newpid != 0) { priv_sock_set_parent_context(p_sess); if (tunable_ssl_enable) { ssl_comm_channel_set_consumer_context(p_sess); } /* Parent - go into pre-login parent process mode */ while (1) { process_login_req(p_sess); } } } /* Child process - time to lose as much privilege as possible and do the * login processing */ vsf_set_die_if_parent_dies(); priv_sock_set_child_context(p_sess); if (tunable_ssl_enable) { ssl_comm_channel_set_producer_context(p_sess); } if (tunable_local_enable && tunable_userlist_enable) { int retval = str_fileread(&p_sess->userlist_str, tunable_userlist_file, VSFTP_CONF_FILE_MAX); if (vsf_sysutil_retval_is_error(retval)) { die2("cannot read user list file:", tunable_userlist_file); } } drop_all_privs(); init_connection(p_sess); /* NOTREACHED */ }
static void common_do_login(struct vsf_session* p_sess, const struct mystr* p_user_str, int do_chroot, int anon) { int was_anon = anon; const struct mystr* p_orig_user_str = p_user_str; int newpid; vsf_sysutil_install_null_sighandler(kVSFSysUtilSigCHLD); /* Tells the pre-login child all is OK (it may exit in response) */ priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK); if (!p_sess->control_use_ssl) { (void) vsf_sysutil_wait(); } else { p_sess->ssl_slave_active = 1; } /* Handle loading per-user config options */ handle_per_user_config(p_user_str); /* Set this before we fork */ p_sess->is_anonymous = anon; priv_sock_close(p_sess); priv_sock_init(p_sess); vsf_sysutil_install_sighandler(kVSFSysUtilSigCHLD, handle_sigchld, 0, 1); if (tunable_isolate_network && !tunable_port_promiscuous) { newpid = vsf_sysutil_fork_newnet(); } else { newpid = vsf_sysutil_fork(); } if (newpid == 0) { struct mystr guest_user_str = INIT_MYSTR; struct mystr chroot_str = INIT_MYSTR; struct mystr chdir_str = INIT_MYSTR; struct mystr userdir_str = INIT_MYSTR; unsigned int secutil_option = VSF_SECUTIL_OPTION_USE_GROUPS | VSF_SECUTIL_OPTION_NO_PROCS; /* Child - drop privs and start proper FTP! */ /* This PR_SET_PDEATHSIG doesn't work for all possible process tree setups. * The other cases are taken care of by a shutdown() of the command * connection in our SIGTERM handler. */ vsf_set_die_if_parent_dies(); priv_sock_set_child_context(p_sess); if (tunable_guest_enable && !anon) { p_sess->is_guest = 1; /* Remap to the guest user */ str_alloc_text(&guest_user_str, tunable_guest_username); p_user_str = &guest_user_str; if (!tunable_virtual_use_local_privs) { anon = 1; do_chroot = 1; } } if (do_chroot) { secutil_option |= VSF_SECUTIL_OPTION_CHROOT; } if (!anon) { secutil_option |= VSF_SECUTIL_OPTION_CHANGE_EUID; } calculate_chdir_dir(was_anon, &userdir_str, &chroot_str, &chdir_str, p_user_str, p_orig_user_str); vsf_secutil_change_credentials(p_user_str, &userdir_str, &chroot_str, 0, secutil_option); if (!str_isempty(&chdir_str)) { (void) str_chdir(&chdir_str); } str_free(&guest_user_str); str_free(&chroot_str); str_free(&chdir_str); str_free(&userdir_str); p_sess->is_anonymous = anon; process_post_login(p_sess); bug("should not get here: common_do_login"); } /* Parent */ priv_sock_set_parent_context(p_sess); if (tunable_ssl_enable) { ssl_comm_channel_set_producer_context(p_sess); } vsf_priv_parent_postlogin(p_sess); bug("should not get here in common_do_login"); }
void ssl_slave(struct vsf_session* p_sess) { struct mystr data_str = INIT_MYSTR; str_reserve(&data_str, VSFTP_DATA_BUFSIZE); /* Before becoming the slave, clear the alarm for the FTP protocol. */ vsf_sysutil_clear_alarm(); /* No need for any further communications with the privileged parent. */ priv_sock_set_parent_context(p_sess); if (tunable_setproctitle_enable) { vsf_sysutil_setproctitle("SSL handler"); } while (1) { char cmd = priv_sock_get_cmd(p_sess->ssl_slave_fd); int ret; if (cmd == PRIV_SOCK_GET_USER_CMD) { ret = ftp_getline(p_sess, &p_sess->ftp_cmd_str, p_sess->p_control_line_buf); priv_sock_send_int(p_sess->ssl_slave_fd, ret); if (ret >= 0) { priv_sock_send_str(p_sess->ssl_slave_fd, &p_sess->ftp_cmd_str); } } else if (cmd == PRIV_SOCK_WRITE_USER_RESP) { priv_sock_get_str(p_sess->ssl_slave_fd, &p_sess->ftp_cmd_str); ret = ftp_write_str(p_sess, &p_sess->ftp_cmd_str, kVSFRWControl); priv_sock_send_int(p_sess->ssl_slave_fd, ret); } else if (cmd == PRIV_SOCK_DO_SSL_HANDSHAKE) { char result = PRIV_SOCK_RESULT_BAD; if (p_sess->data_fd != -1 || p_sess->p_data_ssl != 0) { bug("state not clean"); } p_sess->data_fd = priv_sock_recv_fd(p_sess->ssl_slave_fd); ret = ssl_accept(p_sess, p_sess->data_fd); if (ret == 1) { result = PRIV_SOCK_RESULT_OK; } else { vsf_sysutil_close(p_sess->data_fd); p_sess->data_fd = -1; } priv_sock_send_result(p_sess->ssl_slave_fd, result); } else if (cmd == PRIV_SOCK_DO_SSL_READ) { str_trunc(&data_str, VSFTP_DATA_BUFSIZE); ret = ssl_read_into_str(p_sess, p_sess->p_data_ssl, &data_str); priv_sock_send_int(p_sess->ssl_slave_fd, ret); priv_sock_send_str(p_sess->ssl_slave_fd, &data_str); } else if (cmd == PRIV_SOCK_DO_SSL_WRITE) { priv_sock_get_str(p_sess->ssl_slave_fd, &data_str); ret = ssl_write(p_sess->p_data_ssl, str_getbuf(&data_str), str_getlen(&data_str)); priv_sock_send_int(p_sess->ssl_slave_fd, ret); } else if (cmd == PRIV_SOCK_DO_SSL_CLOSE) { char result = PRIV_SOCK_RESULT_BAD; if (p_sess->data_fd == -1 && p_sess->p_data_ssl == 0) { result = PRIV_SOCK_RESULT_OK; } else { ret = ssl_data_close(p_sess); if (ret == 1) { result = PRIV_SOCK_RESULT_OK; } vsf_sysutil_close(p_sess->data_fd); p_sess->data_fd = -1; } priv_sock_send_result(p_sess->ssl_slave_fd, result); } else { die("bad request in process_ssl_slave_req"); } } }