int ftp_getline(struct vsf_session* p_sess, struct mystr* p_str, char* p_buf) { if (p_sess->control_use_ssl && p_sess->ssl_slave_active) { int ret; priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_GET_USER_CMD); ret = priv_sock_get_int(p_sess->ssl_consumer_fd); if (ret >= 0) { priv_sock_get_str(p_sess->ssl_consumer_fd, p_str); } return ret; } else { str_netfd_read_t p_peek = plain_peek_adapter; str_netfd_read_t p_read = plain_read_adapter; if (p_sess->control_use_ssl) { p_peek = ssl_peek_adapter; p_read = ssl_read_adapter; } return str_netfd_alloc(p_sess, p_str, '\n', p_buf, VSFTP_MAX_COMMAND_LINE, p_peek, p_read); } }
void ftp_getline(const struct vsf_session* p_sess, struct mystr* p_str, char* p_buf) { if (p_sess->control_use_ssl && p_sess->ssl_slave_active) { priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_GET_USER_CMD); priv_sock_get_str(p_sess->ssl_consumer_fd, p_str); } else if (p_sess->control_use_ssl) { ssl_getline(p_sess, p_str, '\n', p_buf, VSFTP_MAX_COMMAND_LINE); } else { str_netfd_alloc( p_str, VSFTP_COMMAND_FD, '\n', p_buf, VSFTP_MAX_COMMAND_LINE); } }
static void process_ssl_slave_req(struct vsf_session* p_sess) { while (1) { char cmd = priv_sock_get_cmd(p_sess->ssl_slave_fd); int retval; if (cmd == PRIV_SOCK_GET_USER_CMD) { ftp_getline(p_sess, &p_sess->ftp_cmd_str, p_sess->p_control_line_buf); 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); retval = ftp_write_str(p_sess, &p_sess->ftp_cmd_str, kVSFRWControl); priv_sock_send_int(p_sess->ssl_slave_fd, retval); } else { die("bad request in process_ssl_slave_req"); } } }
static void process_login_req(struct vsf_session* p_sess) { enum EVSFPrivopLoginResult e_login_result = kVSFLoginNull; /* Blocks */ if (priv_sock_get_cmd(p_sess) != 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)) { die("cannot open chroot() user 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 */ }
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"); } } }
//static Kitsune void process_login_req(struct vsf_session* p_sess) { enum EVSFPrivopLoginResult e_login_result = kVSFLoginNull; char cmd; if (!kitsune_is_updating()) { /* Kitsune */ vsf_sysutil_unblock_sig(kVSFSysUtilSigCHLD); /* Blocks */ cmd = priv_sock_get_cmd(p_sess->parent_fd); vsf_sysutil_block_sig(kVSFSysUtilSigCHLD); if (cmd != PRIV_SOCK_LOGIN) { die("bad request"); } } /* Kitsune, update point */ kitsune_update("twoprocess.c"); /* Kitsune, allow updating from blocking loop */ vsf_sysutil_kitsune_set_update_point("twoprocess.c"); /* Get username and password - we must distrust these */ { struct mystr password_str = INIT_MYSTR; priv_sock_get_str(p_sess->parent_fd, &p_sess->user_str); priv_sock_get_str(p_sess->parent_fd, &password_str); p_sess->control_use_ssl = priv_sock_get_int(p_sess->parent_fd); p_sess->data_use_ssl = priv_sock_get_int(p_sess->parent_fd); if (!tunable_ssl_enable) { p_sess->control_use_ssl = 0; p_sess->data_use_ssl = 0; } 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->parent_fd, 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 */ }