void vsf_ftpdataio_dispose_transfer_fd(struct vsf_session* p_sess) { int retval; if (p_sess->data_fd == -1) { bug("no data descriptor in vsf_ftpdataio_dispose_transfer_fd"); } /* Reset the data connection alarm so it runs anew with the blocking close */ start_data_alarm(p_sess); vsf_sysutil_uninstall_io_handler(); if (p_sess->p_data_ssl != 0) { ssl_data_close(p_sess); } /* This close() blocks because we set SO_LINGER */ retval = vsf_sysutil_close_failok(p_sess->data_fd); if (vsf_sysutil_retval_is_error(retval)) { /* Do it again without blocking. */ vsf_sysutil_deactivate_linger_failok(p_sess->data_fd); (void) vsf_sysutil_close_failok(p_sess->data_fd); } vsf_sysutil_clear_alarm(); p_sess->data_fd = -1; }
int vsf_ftpdataio_dispose_transfer_fd(struct vsf_session* p_sess) { int dispose_ret = 1; int retval; if (p_sess->data_fd == -1) { bug("no data descriptor in vsf_ftpdataio_dispose_transfer_fd"); } vsf_sysutil_uninstall_io_handler(); if (p_sess->data_use_ssl && p_sess->ssl_slave_active) { char result; start_data_alarm(p_sess); priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_CLOSE); result = priv_sock_get_result(p_sess->ssl_consumer_fd); if (result != PRIV_SOCK_RESULT_OK) { dispose_ret = 0; } } else if (p_sess->p_data_ssl) { start_data_alarm(p_sess); dispose_ret = ssl_data_close(p_sess); } if (!p_sess->abor_received && !p_sess->data_timeout && dispose_ret == 1) { /* If we didn't get a failure, linger on the close() in order to get more * accurate transfer times. */ start_data_alarm(p_sess); vsf_sysutil_activate_linger(p_sess->data_fd); } /* This close() blocks because we set SO_LINGER */ retval = vsf_sysutil_close_failok(p_sess->data_fd); if (vsf_sysutil_retval_is_error(retval)) { /* Do it again without blocking. */ vsf_sysutil_deactivate_linger_failok(p_sess->data_fd); (void) vsf_sysutil_close_failok(p_sess->data_fd); } p_sess->data_fd = -1; if (tunable_data_connection_timeout > 0) { vsf_sysutil_clear_alarm(); } if (p_sess->abor_received || p_sess->data_timeout) { dispose_ret = 0; } return dispose_ret; }
void start_data_alarm(struct vsf_session* p_sess) { if (tunable_data_connection_timeout > 0) { vsf_sysutil_install_sighandler(kVSFSysUtilSigALRM, handle_sigalrm, p_sess, 1); vsf_sysutil_set_alarm(tunable_data_connection_timeout); } else if (tunable_idle_session_timeout > 0) { vsf_sysutil_clear_alarm(); } }
void vsf_two_process_login(struct vsf_session* p_sess, const struct mystr* p_pass_str) { char result; priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_LOGIN); priv_sock_send_str(p_sess->child_fd, &p_sess->user_str); priv_sock_send_str(p_sess->child_fd, p_pass_str); priv_sock_send_int(p_sess->child_fd, p_sess->control_use_ssl); priv_sock_send_int(p_sess->child_fd, p_sess->data_use_ssl); result = priv_sock_get_result(p_sess->child_fd); if (result == PRIV_SOCK_RESULT_OK) { /* Miracle. We don't emit the success message here. That is left to * process_post_login(). * Exit normally, unless we are remaining as the SSL read / write child. */ if (!p_sess->control_use_ssl) { vsf_sysutil_exit(0); } else { vsf_sysutil_clear_alarm(); vsf_sysutil_close(p_sess->child_fd); if (tunable_setproctitle_enable) { vsf_sysutil_setproctitle("SSL handler"); } process_ssl_slave_req(p_sess); } /* NOTREACHED */ } else if (result == PRIV_SOCK_RESULT_BAD) { /* Continue the processing loop.. */ return; } else { die("priv_sock_get_result"); } }
int vsf_ftpdataio_dispose_transfer_fd(struct vsf_session* p_sess) { int dispose_ret = 1; int retval; if (p_sess->data_fd == -1) { bug("no data descriptor in vsf_ftpdataio_dispose_transfer_fd"); } /* Reset the data connection alarm so it runs anew with the blocking close */ start_data_alarm(p_sess); vsf_sysutil_uninstall_io_handler(); if (p_sess->data_use_ssl && p_sess->ssl_slave_active) { char result; priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_CLOSE); result = priv_sock_get_result(p_sess->ssl_consumer_fd); if (result != PRIV_SOCK_RESULT_OK) { dispose_ret = 0; } } else if (p_sess->p_data_ssl) { dispose_ret = ssl_data_close(p_sess); } /* This close() blocks because we set SO_LINGER */ retval = vsf_sysutil_close_failok(p_sess->data_fd); if (vsf_sysutil_retval_is_error(retval)) { /* Do it again without blocking. */ vsf_sysutil_deactivate_linger_failok(p_sess->data_fd); (void) vsf_sysutil_close_failok(p_sess->data_fd); } if (tunable_data_connection_timeout > 0) { vsf_sysutil_clear_alarm(); } p_sess->data_fd = -1; return dispose_ret; }
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"); } } }