bool SSH2Channel::eof(ExceptionSink *xsink) { AutoLocker al(parent->m); if (check_open(xsink)) return true; return (bool)libssh2_channel_eof(channel); }
static int mx_channel_netconf_read_hello (mx_channel_t *mcp) { mx_buffer_t *mbp = mcp->mc_rbufp; int len; for (;;) { if (mbp->mb_start + mbp->mb_len == mbp->mb_size) { mx_buffer_t *newp = mx_buffer_create(0); if (newp == NULL) { mx_log("C%u cannot extend buffer", mcp->mc_id); return TRUE; } mbp->mb_next = newp; mbp = newp; } len = mx_channel_read(mcp, mbp->mb_data + mbp->mb_start + mbp->mb_len, mbp->mb_size - (mbp->mb_start + mbp->mb_len)); if (libssh2_channel_eof(mcp->mc_channel)) { DBG_POLL("C%u eof during read_hello", mcp->mc_id); return FALSE; } if (len == LIBSSH2_ERROR_EAGAIN) { /* Nothing to read, nothing to write; move on */ DBG_POLL("C%u is drained", mcp->mc_id); #if 0 break; #else sleep(1); continue; #endif } if (len < 0) return TRUE; mbp->mb_len += len; DBG_POLL("C%u read %d", mcp->mc_id, len); if (mx_channel_netconf_has_marker(mcp)) { mx_log("C%u found end-of-frame; len %lu, discarding", mcp->mc_id, mcp->mc_rbufp->mb_len); mbp->mb_len = mbp->mb_start = 0; if (mbp->mb_next) { mx_buffer_free(mbp->mb_next); mbp->mb_next = NULL; } return TRUE; } } return FALSE; }
void cql_ccm_bridge_t::wait_for_shell_prompth() { const char SHELL_PROMPTH_CHARACTER = '$'; while (!_esc_remover_stdout.ends_with_character(SHELL_PROMPTH_CHARACTER)) { if (libssh2_channel_eof(_ssh_internals->_channel)) { throw cql_ccm_bridge_exception_t("connection closed by remote host"); } terminal_read_stream(_esc_remover_stdout, SSH_STDOUT); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); } }
static int php_ssh2_channel_stream_close(php_stream *stream, int close_handle TSRMLS_DC) { php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract; if (!abstract->refcount || (--(*(abstract->refcount)) == 0)) { /* Last one out, turn off the lights */ if (abstract->refcount) { efree(abstract->refcount); } libssh2_channel_eof(abstract->channel); libssh2_channel_free(abstract->channel); zend_list_delete(abstract->session_rsrc); } efree(abstract); return 0; }
/* * Get DNS query using SSH transport layer. */ static ssize_t dig_ssh_request(struct ssh_session *ssh_info, char *buf, size_t buf_size, ssize_t len) { int ret; ssize_t recv_size; do { ret = libssh2_channel_write(ssh_info->channel, buf, len); if (ret < 0) { ERR("libssh2_channel_write: %d", ret); goto error; } DBG("DNS request of size %ld sent to ssh channel", len); recv_size = libssh2_channel_read(ssh_info->channel, buf, buf_size); if (recv_size < 0) { char *buf; ERR("SSH channel read failed"); libssh2_session_last_error(ssh_info->session, &buf, NULL, 0); ERR("Failure: %s", buf); } else if (recv_size == 0) { ret = libssh2_channel_eof(ssh_info->channel); if (ret) { DBG("SSH server disconnected!"); libssh2_channel_close(ssh_info->channel); libssh2_channel_free(ssh_info->channel); /* Create new channel */ ret = ssh_setup_tunnel(ssh_info, dns_ip); if (ret < 0) { goto error; } } } else { DBG("DNS reply red from ssh channel (size: %ld)", recv_size); goto end; } } while (1); end: return recv_size; error: return -1; }
int detail::process_impl::read_some( char* data, size_t len, int stream_id ){ if( !sshc->my->session ) { FC_THROW( "Session closed" ); } int rc; char* buf = data; size_t buflen = len; do { rc = sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_read_ex, chan, stream_id, buf, buflen), "read failed: ${message}"); if( rc > 0 ) { buf += rc; buflen -= rc; return buf-data; } else if( rc == 0 ) { if( libssh2_channel_eof( chan ) ) return -1; // eof sshc->my->wait_on_socket(); } } while( rc >= 0 && buflen); return buf-data; }
ShellChannel::ReadReply ShellChannel::readUntil(const QByteArray& marker) { ReadReply result; result.readAgain = false; // Check if the buffer is already loaded and ready to go. int markerIndex = mReadBuffer.indexOf(marker); if (markerIndex == -1) { // Actually do the read int rc = libssh2_channel_read(mHandle, mScratchBuffer, SSH_SHELL_BUFFER_SIZE); if (rc > 0) mReadBuffer.append(mScratchBuffer, rc); else if (rc == LIBSSH2_ERROR_EAGAIN) { result.readAgain = true; return result; } else if (rc == 0) { if (libssh2_channel_eof(mHandle)) criticalError("Connection closed unexpectedly"); } else criticalError("Failed to read from host"); // Check again to see if the buffer is ready to go. markerIndex = mReadBuffer.indexOf(marker); } // If there's data ready to go, pack it into the reply. if (markerIndex > -1) { result.data = mReadBuffer.left(markerIndex); mReadBuffer = mReadBuffer.right(mReadBuffer.size() - (markerIndex + marker.length())); } return result; }
int process_d::read_some( char* data, size_t len, int stream_id ) { if( !sshc->my->m_session ) { MACE_SSH_THROW( "Session closed\n" ); } int rc; char* buf = data; size_t buflen = len; do { rc = libssh2_channel_read_ex( chan, stream_id, buf, buflen ); if( rc > 0 ) { buf += rc; buflen -= rc; return buf-data; } else if( rc == 0 ) { if( libssh2_channel_eof( chan ) ) { return -1; // eof } sshc->my->wait_on_socket(); } else { if( rc == LIBSSH2_ERROR_EAGAIN ) { if( 0 < (buf-data) ) { return buf-data; } else { sshc->my->wait_on_socket(); rc = 0; continue; } } else { char* msg; if( !sshc || !sshc->my || !sshc->my->m_session ) { MACE_SSH_THROW( "Session closed" ); } slog( "my: %1%", sshc->my ); rc = libssh2_session_last_error( sshc->my->m_session, &msg, 0, 0 ); MACE_SSH_THROW( "read failed: %1% - %2%", %rc %msg ); return buf-data; } } } while( rc >= 0 && buflen); return buf-data; }
static size_t php_ssh2_channel_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) { php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract; ssize_t readstate; LIBSSH2_SESSION *session; stream->eof = libssh2_channel_eof(abstract->channel); libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking); session = (LIBSSH2_SESSION *)zend_fetch_resource(NULL TSRMLS_CC, abstract->session_rsrc, PHP_SSH2_SESSION_RES_NAME, NULL, 1, le_ssh2_session); #ifdef PHP_SSH2_SESSION_TIMEOUT if (abstract->is_blocking) { libssh2_session_set_timeout(session, abstract->timeout); } #endif readstate = libssh2_channel_read_ex(abstract->channel, abstract->streamid, buf, count); #ifdef PHP_SSH2_SESSION_TIMEOUT if (abstract->is_blocking) { libssh2_session_set_timeout(session, 0); } #endif if (readstate == LIBSSH2_ERROR_EAGAIN) { readstate = 0; } if (readstate < 0) { char *error_msg = NULL; if (libssh2_session_last_error(session, &error_msg, NULL, 0) == readstate) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure '%s' (%ld)", error_msg, readstate); } stream->eof = 1; readstate = 0; } return readstate; }
void* ssh_client_thread(void* data) { guac_client* client = (guac_client*) data; ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; guac_socket* socket = client->socket; char buffer[8192]; pthread_t input_thread; /* Init SSH base libraries */ if (guac_common_ssh_init(client)) return NULL; /* Get user and credentials */ client_data->user = guac_ssh_get_user(client); /* Send new name */ char name[1024]; snprintf(name, sizeof(name)-1, "%s@%s", client_data->username, client_data->hostname); guac_protocol_send_name(socket, name); /* Open SSH session */ client_data->session = guac_common_ssh_create_session(client, client_data->hostname, client_data->port, client_data->user); if (client_data->session == NULL) { /* Already aborted within guac_common_ssh_create_session() */ return NULL; } pthread_mutex_init(&client_data->term_channel_lock, NULL); /* Open channel for terminal */ client_data->term_channel = libssh2_channel_open_session(client_data->session->session); if (client_data->term_channel == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to open terminal channel."); return NULL; } #ifdef ENABLE_SSH_AGENT /* Start SSH agent forwarding, if enabled */ if (client_data->enable_agent) { libssh2_session_callback_set(client_data->session, LIBSSH2_CALLBACK_AUTH_AGENT, (void*) ssh_auth_agent_callback); /* Request agent forwarding */ if (libssh2_channel_request_auth_agent(client_data->term_channel)) guac_client_log(client, GUAC_LOG_ERROR, "Agent forwarding request failed"); else guac_client_log(client, GUAC_LOG_INFO, "Agent forwarding enabled."); } client_data->auth_agent = NULL; #endif /* Start SFTP session as well, if enabled */ if (client_data->enable_sftp) { /* Create SSH session specific for SFTP */ guac_client_log(client, GUAC_LOG_DEBUG, "Reconnecting for SFTP..."); client_data->sftp_session = guac_common_ssh_create_session(client, client_data->hostname, client_data->port, client_data->user); if (client_data->sftp_session == NULL) { /* Already aborted within guac_common_ssh_create_session() */ return NULL; } /* Request SFTP */ client_data->sftp_filesystem = guac_common_ssh_create_sftp_filesystem( client_data->sftp_session, "/"); /* Set generic (non-filesystem) file upload handler */ client->file_handler = guac_sftp_file_handler; /* Init handlers for Guacamole-specific console codes */ client_data->term->upload_path_handler = guac_sftp_set_upload_path; client_data->term->file_download_handler = guac_sftp_download_file; guac_client_log(client, GUAC_LOG_DEBUG, "SFTP session initialized"); } /* Request PTY */ if (libssh2_channel_request_pty_ex(client_data->term_channel, "linux", sizeof("linux")-1, NULL, 0, client_data->term->term_width, client_data->term->term_height, 0, 0)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to allocate PTY."); return NULL; } /* Request shell */ if (libssh2_channel_shell(client_data->term_channel)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to associate shell with PTY."); return NULL; } /* Logged in */ guac_client_log(client, GUAC_LOG_INFO, "SSH connection successful."); /* Start input thread */ if (pthread_create(&(input_thread), NULL, ssh_input_thread, (void*) client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread"); return NULL; } /* Set non-blocking */ libssh2_session_set_blocking(client_data->session->session, 0); /* While data available, write to terminal */ int bytes_read = 0; for (;;) { /* Track total amount of data read */ int total_read = 0; pthread_mutex_lock(&(client_data->term_channel_lock)); /* Stop reading at EOF */ if (libssh2_channel_eof(client_data->term_channel)) { pthread_mutex_unlock(&(client_data->term_channel_lock)); break; } /* Read terminal data */ bytes_read = libssh2_channel_read(client_data->term_channel, buffer, sizeof(buffer)); pthread_mutex_unlock(&(client_data->term_channel_lock)); /* Attempt to write data received. Exit on failure. */ if (bytes_read > 0) { int written = guac_terminal_write_stdout(client_data->term, buffer, bytes_read); if (written < 0) break; total_read += bytes_read; } else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN) break; #ifdef ENABLE_SSH_AGENT /* If agent open, handle any agent packets */ if (client_data->auth_agent != NULL) { bytes_read = ssh_auth_agent_read(client_data->auth_agent); if (bytes_read > 0) total_read += bytes_read; else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN) client_data->auth_agent = NULL; } #endif /* Wait for more data if reads turn up empty */ if (total_read == 0) { fd_set fds; struct timeval timeout; FD_ZERO(&fds); FD_SET(client_data->session->fd, &fds); /* Wait for one second */ timeout.tv_sec = 1; timeout.tv_usec = 0; if (select(client_data->session->fd + 1, &fds, NULL, NULL, &timeout) < 0) break; } } /* Kill client and Wait for input thread to die */ guac_client_stop(client); pthread_join(input_thread, NULL); pthread_mutex_destroy(&client_data->term_channel_lock); guac_client_log(client, GUAC_LOG_INFO, "SSH connection ended."); return NULL; }
void* ssh_client_thread(void* data) { guac_client* client = (guac_client*) data; ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; char name[1024]; guac_socket* socket = client->socket; char buffer[8192]; int bytes_read = -1234; int socket_fd; int stdout_fd = client_data->term->stdout_pipe_fd[1]; pthread_t input_thread; libssh2_init(0); /* Get username */ if (client_data->username[0] == 0) prompt(client, "Login as: ", client_data->username, sizeof(client_data->username), true); /* Send new name */ snprintf(name, sizeof(name)-1, "%s@%s", client_data->username, client_data->hostname); guac_protocol_send_name(socket, name); /* If key specified, import */ if (client_data->key_base64[0] != 0) { /* Attempt to read key without passphrase */ client_data->key = ssh_key_alloc(client_data->key_base64, strlen(client_data->key_base64), ""); /* On failure, attempt with passphrase */ if (client_data->key == NULL) { /* Prompt for passphrase if missing */ if (client_data->key_passphrase[0] == 0) prompt(client, "Key passphrase: ", client_data->key_passphrase, sizeof(client_data->key_passphrase), false); /* Import key with passphrase */ client_data->key = ssh_key_alloc(client_data->key_base64, strlen(client_data->key_base64), client_data->key_passphrase); /* If still failing, give up */ if (client_data->key == NULL) { guac_client_log_error(client, "Auth key import failed."); return NULL; } } /* end decrypt key with passphrase */ /* Success */ guac_client_log_info(client, "Auth key successfully imported."); } /* end if key given */ /* Otherwise, get password if not provided */ else if (client_data->password[0] == 0) prompt(client, "Password: "******"\x1B[H\x1B[J", 6); /* Open SSH session */ client_data->session = __guac_ssh_create_session(client, &socket_fd); if (client_data->session == NULL) { /* Already aborted within __guac_ssh_create_session() */ return NULL; } /* Open channel for terminal */ client_data->term_channel = libssh2_channel_open_session(client_data->session); if (client_data->term_channel == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to open terminal channel."); return NULL; } #ifdef ENABLE_SSH_AGENT /* Start SSH agent forwarding, if enabled */ if (client_data->enable_agent) { libssh2_session_callback_set(client_data->session, LIBSSH2_CALLBACK_AUTH_AGENT, (void*) ssh_auth_agent_callback); /* Request agent forwarding */ if (libssh2_channel_request_auth_agent(client_data->term_channel)) guac_client_log_error(client, "Agent forwarding request failed"); else guac_client_log_info(client, "Agent forwarding enabled."); } client_data->auth_agent = NULL; #endif /* Start SFTP session as well, if enabled */ if (client_data->enable_sftp) { /* Create SSH session specific for SFTP */ guac_client_log_info(client, "Reconnecting for SFTP..."); client_data->sftp_ssh_session = __guac_ssh_create_session(client, NULL); if (client_data->sftp_ssh_session == NULL) { /* Already aborted within __guac_ssh_create_session() */ return NULL; } /* Request SFTP */ client_data->sftp_session = libssh2_sftp_init(client_data->sftp_ssh_session); if (client_data->sftp_session == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to start SFTP session."); return NULL; } /* Set file handler */ client->file_handler = guac_sftp_file_handler; guac_client_log_info(client, "SFTP session initialized"); } /* Request PTY */ if (libssh2_channel_request_pty_ex(client_data->term_channel, "linux", sizeof("linux")-1, NULL, 0, client_data->term->term_width, client_data->term->term_height, 0, 0)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to allocate PTY."); return NULL; } /* Request shell */ if (libssh2_channel_shell(client_data->term_channel)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to associate shell with PTY."); return NULL; } /* Logged in */ guac_client_log_info(client, "SSH connection successful."); /* Start input thread */ if (pthread_create(&(input_thread), NULL, ssh_input_thread, (void*) client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread"); return NULL; } /* Set non-blocking */ libssh2_session_set_blocking(client_data->session, 0); /* While data available, write to terminal */ bytes_read = 0; while (!libssh2_channel_eof(client_data->term_channel)) { /* Track total amount of data read */ int total_read = 0; /* Read terminal data */ bytes_read = libssh2_channel_read(client_data->term_channel, buffer, sizeof(buffer)); /* Attempt to write data received. Exit on failure. */ if (bytes_read > 0) { int written = guac_terminal_write_all(stdout_fd, buffer, bytes_read); if (written < 0) break; total_read += bytes_read; } else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN) break; #ifdef ENABLE_SSH_AGENT /* If agent open, handle any agent packets */ if (client_data->auth_agent != NULL) { bytes_read = ssh_auth_agent_read(client_data->auth_agent); if (bytes_read > 0) total_read += bytes_read; else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN) client_data->auth_agent = NULL; } #endif /* Wait for more data if reads turn up empty */ if (total_read == 0) { fd_set fds; struct timeval timeout; FD_ZERO(&fds); FD_SET(socket_fd, &fds); /* Wait for one second */ timeout.tv_sec = 1; timeout.tv_usec = 0; if (select(socket_fd+1, &fds, NULL, NULL, &timeout) < 0) break; } } /* Kill client and Wait for input thread to die */ guac_client_stop(client); pthread_join(input_thread, NULL); guac_client_log_info(client, "SSH connection ended."); return NULL; }
int Parser::runCommand(QString command) { // command channel //------------setup channel ---------------------- LIBSSH2_CHANNEL *channel = NULL; channel = libssh2_channel_open_session(session_); if ( channel == NULL ) { qDebug()<<"Failed to open a new channel\n"; socket_->disconnectFromHost(); return -1; } /* Force Data to on STDOUT and STDERR to be on seperate channels * read individually with *_read and *_read_stderr functions */ libssh2_channel_handle_extended_data(channel,LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL); libssh2_channel_set_blocking(channel, 1); { int rc; while ((rc=libssh2_channel_exec(channel, command.toLocal8Bit().constData()))==LIBSSH2_ERROR_EAGAIN ); if (rc) { return -1; } //-------read channel----------- int read; QString stdout_str; QString stderr_str; while(true) { //qDebug("libssh2_channel_read() >>>"); { QByteArray byte_array; byte_array.resize(4096); char* buffer=byte_array.data(); int buffer_size=byte_array.size(); read = libssh2_channel_read(channel, buffer, buffer_size-10); if(read>0) { QByteArray debug = QByteArray(buffer, read); stdout_str.append(debug); } if(LIBSSH2_ERROR_EAGAIN == read) { qDebug("LIBSSH2_ERROR_EAGAIN"); break; } else if(read < 0) { qDebug(" error reading from std channel"); closeChannel(channel); goto next_channel; } } { QByteArray byte_array; byte_array.resize(4096); char* buffer=byte_array.data(); int buffer_size=byte_array.size(); read = libssh2_channel_read_stderr(channel, buffer, buffer_size-10); if(read>0) { QByteArray debug = QByteArray(buffer, read); stderr_str.append(debug); } if(LIBSSH2_ERROR_EAGAIN == read) { qDebug("LIBSSH2_ERROR_EAGAIN"); break; } else if(read < 0) { qDebug(" error reading from stderr channel"); closeChannel(channel); goto next_channel; } } int i = libssh2_channel_eof(channel); if(i) { //qDebug("libssh2_channel_eof %i", i); closeChannel(channel); goto next_channel; } } next_channel: if(!stdout_str.isEmpty()) { qDebug()<<"STDOUT:\n"<<stdout_str; } if(!stderr_str.isEmpty()) { qDebug()<<"STDERR:\n"<<stderr_str; } } return 1; }
bool detail::process_istream::eof()const { return 0 != libssh2_channel_eof( proc.chan ); }
void* ssh_client_thread(void* data) { guac_client* client = (guac_client*) data; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_ssh_settings* settings = ssh_client->settings; char buffer[8192]; pthread_t input_thread; /* Init SSH base libraries */ if (guac_common_ssh_init(client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "SSH library initialization failed"); return NULL; } /* Set up screen recording, if requested */ if (settings->recording_path != NULL) { guac_common_recording_create(client, settings->recording_path, settings->recording_name, settings->create_recording_path); } /* Create terminal */ ssh_client->term = guac_terminal_create(client, settings->font_name, settings->font_size, settings->resolution, settings->width, settings->height, settings->color_scheme); /* Fail if terminal init failed */ if (ssh_client->term == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Terminal initialization failed"); return NULL; } /* Set up typescript, if requested */ if (settings->typescript_path != NULL) { guac_terminal_create_typescript(ssh_client->term, settings->typescript_path, settings->typescript_name, settings->create_typescript_path); } /* Get user and credentials */ ssh_client->user = guac_ssh_get_user(client); /* Open SSH session */ ssh_client->session = guac_common_ssh_create_session(client, settings->hostname, settings->port, ssh_client->user); if (ssh_client->session == NULL) { /* Already aborted within guac_common_ssh_create_session() */ return NULL; } pthread_mutex_init(&ssh_client->term_channel_lock, NULL); /* Open channel for terminal */ ssh_client->term_channel = libssh2_channel_open_session(ssh_client->session->session); if (ssh_client->term_channel == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to open terminal channel."); return NULL; } #ifdef ENABLE_SSH_AGENT /* Start SSH agent forwarding, if enabled */ if (ssh_client->enable_agent) { libssh2_session_callback_set(ssh_client->session, LIBSSH2_CALLBACK_AUTH_AGENT, (void*) ssh_auth_agent_callback); /* Request agent forwarding */ if (libssh2_channel_request_auth_agent(ssh_client->term_channel)) guac_client_log(client, GUAC_LOG_ERROR, "Agent forwarding request failed"); else guac_client_log(client, GUAC_LOG_INFO, "Agent forwarding enabled."); } ssh_client->auth_agent = NULL; #endif /* Start SFTP session as well, if enabled */ if (settings->enable_sftp) { /* Create SSH session specific for SFTP */ guac_client_log(client, GUAC_LOG_DEBUG, "Reconnecting for SFTP..."); ssh_client->sftp_session = guac_common_ssh_create_session(client, settings->hostname, settings->port, ssh_client->user); if (ssh_client->sftp_session == NULL) { /* Already aborted within guac_common_ssh_create_session() */ return NULL; } /* Request SFTP */ ssh_client->sftp_filesystem = guac_common_ssh_create_sftp_filesystem( ssh_client->sftp_session, "/"); /* Expose filesystem to connection owner */ guac_client_for_owner(client, guac_common_ssh_expose_sftp_filesystem, ssh_client->sftp_filesystem); /* Init handlers for Guacamole-specific console codes */ ssh_client->term->upload_path_handler = guac_sftp_set_upload_path; ssh_client->term->file_download_handler = guac_sftp_download_file; guac_client_log(client, GUAC_LOG_DEBUG, "SFTP session initialized"); } /* Request PTY */ if (libssh2_channel_request_pty_ex(ssh_client->term_channel, "linux", sizeof("linux")-1, NULL, 0, ssh_client->term->term_width, ssh_client->term->term_height, 0, 0)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to allocate PTY."); return NULL; } /* If a command is specified, run that instead of a shell */ if (settings->command != NULL) { if (libssh2_channel_exec(ssh_client->term_channel, settings->command)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to execute command."); return NULL; } } /* Otherwise, request a shell */ else if (libssh2_channel_shell(ssh_client->term_channel)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to associate shell with PTY."); return NULL; } /* Logged in */ guac_client_log(client, GUAC_LOG_INFO, "SSH connection successful."); /* Start input thread */ if (pthread_create(&(input_thread), NULL, ssh_input_thread, (void*) client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread"); return NULL; } /* Set non-blocking */ libssh2_session_set_blocking(ssh_client->session->session, 0); /* While data available, write to terminal */ int bytes_read = 0; for (;;) { /* Track total amount of data read */ int total_read = 0; pthread_mutex_lock(&(ssh_client->term_channel_lock)); /* Stop reading at EOF */ if (libssh2_channel_eof(ssh_client->term_channel)) { pthread_mutex_unlock(&(ssh_client->term_channel_lock)); break; } /* Read terminal data */ bytes_read = libssh2_channel_read(ssh_client->term_channel, buffer, sizeof(buffer)); pthread_mutex_unlock(&(ssh_client->term_channel_lock)); /* Attempt to write data received. Exit on failure. */ if (bytes_read > 0) { int written = guac_terminal_write_stdout(ssh_client->term, buffer, bytes_read); if (written < 0) break; total_read += bytes_read; } else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN) break; #ifdef ENABLE_SSH_AGENT /* If agent open, handle any agent packets */ if (ssh_client->auth_agent != NULL) { bytes_read = ssh_auth_agent_read(ssh_client->auth_agent); if (bytes_read > 0) total_read += bytes_read; else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN) ssh_client->auth_agent = NULL; } #endif /* Wait for more data if reads turn up empty */ if (total_read == 0) { fd_set fds; struct timeval timeout; FD_ZERO(&fds); FD_SET(ssh_client->session->fd, &fds); /* Wait for one second */ timeout.tv_sec = 1; timeout.tv_usec = 0; if (select(ssh_client->session->fd + 1, &fds, NULL, NULL, &timeout) < 0) break; } } /* Kill client and Wait for input thread to die */ guac_client_stop(client); pthread_join(input_thread, NULL); pthread_mutex_destroy(&ssh_client->term_channel_lock); guac_client_log(client, GUAC_LOG_INFO, "SSH connection ended."); return NULL; }
void * CSubThread::Entry() { fd_set fds; struct timeval tv; ssize_t len, wr; char buf[20480]; int rc, i = 0; const char *shost = inet_ntoa(m_sin.sin_addr); unsigned int sport = ntohs(m_sin.sin_port); wxLogInfo(wxT("Forwarding connection from %s:%d to %s:%d"), wxString(inet_ntoa(m_sin.sin_addr), wxConvLibc).c_str(), sport, m_remote_desthost.c_str(), m_remote_destport); /* Must use blocking here to avoid connect errors */ //libssh2_session_set_blocking(m_subThreadSession, 1); while((m_channel = libssh2_channel_direct_tcpip_ex(m_subThreadSession, m_remote_desthost.mb_str(), m_remote_destport, shost, sport)) == NULL) { rc = libssh2_session_last_error(m_subThreadSession, NULL, NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) Sleep(10); else break; } /* Must use non-blocking IO hereafter due to the current libssh2 API */ libssh2_session_set_blocking(m_subThreadSession, 0); if (!m_channel) { wxLogInfo(_("SSH error: Could not open a direct-tcpip channel!")); goto shutdown; } while (1) { FD_ZERO(&fds); FD_SET(m_forwardsock, &fds); tv.tv_sec = 0; tv.tv_usec = 100000; rc = select(m_forwardsock + 1, &fds, NULL, NULL, &tv); memset(buf, 0, sizeof(buf)); if (-1 == rc) { wxLogInfo(_("SSH error: select failed with error code %d"), wxSysErrorCode()); goto shutdown; } if (rc && FD_ISSET(m_forwardsock, &fds)) { len = recv(m_forwardsock, buf, sizeof(buf), 0); if (len < 0) { wxLogInfo(_("SSH error: read failed with error code %d"), wxSysErrorCode()); goto shutdown; } else if (0 == len) { wxLogInfo(_("The client at %s:%d disconnected!"), wxString(inet_ntoa(m_sin.sin_addr), wxConvLibc).c_str(), sport); goto shutdown; } wr = 0; do { i = libssh2_channel_write(m_channel, buf, len); if (i < 0) { wxLogInfo(_("SSH error: libssh2_channel_write with error code %d"), i); goto shutdown; } wr += i; } while (i > 0 && wr < len); } while (1) { len = libssh2_channel_read(m_channel, buf, sizeof(buf)); if (LIBSSH2_ERROR_EAGAIN == len) break; else if (len < 0) { wxLogInfo(_("SSH error: libssh2_channel_read with error code %d"), (int)len); goto shutdown; } wr = 0; while (wr < len) { i = send(m_forwardsock, buf + wr, len - wr, 0); if (i <= 0) { wxLogInfo(_("SSH error: write failed with error code %d"), wxSysErrorCode()); goto shutdown; } wr += i; } if (libssh2_channel_eof(m_channel)) { wxLogInfo(_("Connection at %s:%d disconnected by server"), wxString(inet_ntoa(m_sin.sin_addr), wxConvLibc).c_str(), sport); goto shutdown; } } } shutdown: #ifdef WIN32 closesocket(m_forwardsock); #else close(m_forwardsock); #endif if (m_channel) { libssh2_channel_close(m_channel); libssh2_channel_free(m_channel); m_channel = NULL; } return NULL; }
/* * scp_recv * * Open a channel and request a remote file via SCP * */ static LIBSSH2_CHANNEL * scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb) { int cmd_len; int rc; int tmp_err_code; const char *tmp_err_msg; if (session->scpRecv_state == libssh2_NB_state_idle) { session->scpRecv_mode = 0; session->scpRecv_size = 0; session->scpRecv_mtime = 0; session->scpRecv_atime = 0; session->scpRecv_command_len = _libssh2_shell_quotedsize(path) + sizeof("scp -f ") + (sb?1:0); session->scpRecv_command = LIBSSH2_ALLOC(session, session->scpRecv_command_len); if (!session->scpRecv_command) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a command buffer for " "SCP session"); return NULL; } snprintf((char *)session->scpRecv_command, session->scpRecv_command_len, "scp -%sf ", sb?"p":""); cmd_len = strlen((char *)session->scpRecv_command); (void) shell_quotearg(path, &session->scpRecv_command[cmd_len], session->scpRecv_command_len - cmd_len); _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Opening channel for SCP receive"); session->scpRecv_state = libssh2_NB_state_created; } if (session->scpRecv_state == libssh2_NB_state_created) { /* Allocate a channel */ session->scpRecv_channel = _libssh2_channel_open(session, "session", sizeof("session") - 1, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0); if (!session->scpRecv_channel) { if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) { LIBSSH2_FREE(session, session->scpRecv_command); session->scpRecv_command = NULL; session->scpRecv_state = libssh2_NB_state_idle; } else { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block starting up channel"); } return NULL; } session->scpRecv_state = libssh2_NB_state_sent; } if (session->scpRecv_state == libssh2_NB_state_sent) { /* Request SCP for the desired file */ rc = _libssh2_channel_process_startup(session->scpRecv_channel, "exec", sizeof("exec") - 1, (char *) session->scpRecv_command, session->scpRecv_command_len); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting SCP startup"); return NULL; } else if (rc) { LIBSSH2_FREE(session, session->scpRecv_command); session->scpRecv_command = NULL; goto scp_recv_error; } LIBSSH2_FREE(session, session->scpRecv_command); session->scpRecv_command = NULL; _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sending initial wakeup"); /* SCP ACK */ session->scpRecv_response[0] = '\0'; session->scpRecv_state = libssh2_NB_state_sent1; } if (session->scpRecv_state == libssh2_NB_state_sent1) { rc = _libssh2_channel_write(session->scpRecv_channel, 0, session->scpRecv_response, 1); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending initial wakeup"); return NULL; } else if (rc != 1) { goto scp_recv_error; } /* Parse SCP response */ session->scpRecv_response_len = 0; session->scpRecv_state = libssh2_NB_state_sent2; } if ((session->scpRecv_state == libssh2_NB_state_sent2) || (session->scpRecv_state == libssh2_NB_state_sent3)) { while (sb && (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN)) { unsigned char *s, *p; if (session->scpRecv_state == libssh2_NB_state_sent2) { rc = _libssh2_channel_read(session->scpRecv_channel, 0, (char *) session-> scpRecv_response + session->scpRecv_response_len, 1); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for SCP response"); return NULL; } else if (rc < 0) { /* error, give up */ _libssh2_error(session, rc, "Failed reading SCP response"); goto scp_recv_error; } else if(rc == 0) goto scp_recv_empty_channel; session->scpRecv_response_len++; if (session->scpRecv_response[0] != 'T') { size_t err_len; char *err_msg; /* there can be 01 for warnings 02 for errors The following string MUST be newline terminated */ err_len = _libssh2_channel_packet_data_len(session-> scpRecv_channel, 0); err_msg = LIBSSH2_ALLOC(session, err_len + 1); if (!err_msg) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Failed to get memory "); goto scp_recv_error; } /* Read the remote error message */ (void)_libssh2_channel_read(session->scpRecv_channel, 0, err_msg, err_len); /* If it failed for any reason, we ignore it anyway. */ /* zero terminate the error */ err_msg[err_len]=0; _libssh2_debug(session, LIBSSH2_TRACE_SCP, "got %02x %s", session->scpRecv_response[0], err_msg); _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Failed to recv file"); LIBSSH2_FREE(session, err_msg); goto scp_recv_error; } if ((session->scpRecv_response_len > 1) && ((session-> scpRecv_response[session->scpRecv_response_len - 1] < '0') || (session-> scpRecv_response[session->scpRecv_response_len - 1] > '9')) && (session-> scpRecv_response[session->scpRecv_response_len - 1] != ' ') && (session-> scpRecv_response[session->scpRecv_response_len - 1] != '\r') && (session-> scpRecv_response[session->scpRecv_response_len - 1] != '\n')) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid data in SCP response"); goto scp_recv_error; } if ((session->scpRecv_response_len < 9) || (session-> scpRecv_response[session->scpRecv_response_len - 1] != '\n')) { if (session->scpRecv_response_len == LIBSSH2_SCP_RESPONSE_BUFLEN) { /* You had your chance */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Unterminated response from SCP server"); goto scp_recv_error; } /* Way too short to be an SCP response, or not done yet, short circuit */ continue; } /* We're guaranteed not to go under response_len == 0 by the logic above */ while ((session-> scpRecv_response[session->scpRecv_response_len - 1] == '\r') || (session-> scpRecv_response[session->scpRecv_response_len - 1] == '\n')) session->scpRecv_response_len--; session->scpRecv_response[session->scpRecv_response_len] = '\0'; if (session->scpRecv_response_len < 8) { /* EOL came too soon */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, " "too short" ); goto scp_recv_error; } s = session->scpRecv_response + 1; p = (unsigned char *) strchr((char *) s, ' '); if (!p || ((p - s) <= 0)) { /* No spaces or space in the wrong spot */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, " "malformed mtime"); goto scp_recv_error; } *(p++) = '\0'; /* Make sure we don't get fooled by leftover values */ session->scpRecv_mtime = strtol((char *) s, NULL, 10); s = (unsigned char *) strchr((char *) p, ' '); if (!s || ((s - p) <= 0)) { /* No spaces or space in the wrong spot */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, malformed mtime.usec"); goto scp_recv_error; } /* Ignore mtime.usec */ s++; p = (unsigned char *) strchr((char *) s, ' '); if (!p || ((p - s) <= 0)) { /* No spaces or space in the wrong spot */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, too short or malformed"); goto scp_recv_error; } *p = '\0'; /* Make sure we don't get fooled by leftover values */ session->scpRecv_atime = strtol((char *) s, NULL, 10); /* SCP ACK */ session->scpRecv_response[0] = '\0'; session->scpRecv_state = libssh2_NB_state_sent3; } if (session->scpRecv_state == libssh2_NB_state_sent3) { rc = _libssh2_channel_write(session->scpRecv_channel, 0, session->scpRecv_response, 1); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting to send SCP ACK"); return NULL; } else if (rc != 1) { goto scp_recv_error; } _libssh2_debug(session, LIBSSH2_TRACE_SCP, "mtime = %ld, atime = %ld", session->scpRecv_mtime, session->scpRecv_atime); /* We *should* check that atime.usec is valid, but why let that stop use? */ break; } } session->scpRecv_state = libssh2_NB_state_sent4; } if (session->scpRecv_state == libssh2_NB_state_sent4) { session->scpRecv_response_len = 0; session->scpRecv_state = libssh2_NB_state_sent5; } if ((session->scpRecv_state == libssh2_NB_state_sent5) || (session->scpRecv_state == libssh2_NB_state_sent6)) { while (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) { char *s, *p, *e = NULL; if (session->scpRecv_state == libssh2_NB_state_sent5) { rc = _libssh2_channel_read(session->scpRecv_channel, 0, (char *) session-> scpRecv_response + session->scpRecv_response_len, 1); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for SCP response"); return NULL; } else if (rc < 0) { /* error, bail out*/ _libssh2_error(session, rc, "Failed reading SCP response"); goto scp_recv_error; } else if(rc == 0) goto scp_recv_empty_channel; session->scpRecv_response_len++; if (session->scpRecv_response[0] != 'C') { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server"); goto scp_recv_error; } if ((session->scpRecv_response_len > 1) && (session-> scpRecv_response[session->scpRecv_response_len - 1] != '\r') && (session-> scpRecv_response[session->scpRecv_response_len - 1] != '\n') && (session-> scpRecv_response[session->scpRecv_response_len - 1] < 32)) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid data in SCP response"); goto scp_recv_error; } if ((session->scpRecv_response_len < 7) || (session-> scpRecv_response[session->scpRecv_response_len - 1] != '\n')) { if (session->scpRecv_response_len == LIBSSH2_SCP_RESPONSE_BUFLEN) { /* You had your chance */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Unterminated response from SCP server"); goto scp_recv_error; } /* Way too short to be an SCP response, or not done yet, short circuit */ continue; } /* We're guaranteed not to go under response_len == 0 by the logic above */ while ((session-> scpRecv_response[session->scpRecv_response_len - 1] == '\r') || (session-> scpRecv_response[session->scpRecv_response_len - 1] == '\n')) { session->scpRecv_response_len--; } session->scpRecv_response[session->scpRecv_response_len] = '\0'; if (session->scpRecv_response_len < 6) { /* EOL came too soon */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, too short"); goto scp_recv_error; } s = (char *) session->scpRecv_response + 1; p = strchr(s, ' '); if (!p || ((p - s) <= 0)) { /* No spaces or space in the wrong spot */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, malformed mode"); goto scp_recv_error; } *(p++) = '\0'; /* Make sure we don't get fooled by leftover values */ session->scpRecv_mode = strtol(s, &e, 8); if (e && *e) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, invalid mode"); goto scp_recv_error; } s = strchr(p, ' '); if (!s || ((s - p) <= 0)) { /* No spaces or space in the wrong spot */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, too short or malformed"); goto scp_recv_error; } *s = '\0'; /* Make sure we don't get fooled by leftover values */ session->scpRecv_size = scpsize_strtol(p, &e, 10); if (e && *e) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, invalid size"); goto scp_recv_error; } /* SCP ACK */ session->scpRecv_response[0] = '\0'; session->scpRecv_state = libssh2_NB_state_sent6; } if (session->scpRecv_state == libssh2_NB_state_sent6) { rc = _libssh2_channel_write(session->scpRecv_channel, 0, session->scpRecv_response, 1); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending SCP ACK"); return NULL; } else if (rc != 1) { goto scp_recv_error; } _libssh2_debug(session, LIBSSH2_TRACE_SCP, "mode = 0%lo size = %ld", session->scpRecv_mode, session->scpRecv_size); /* We *should* check that basename is valid, but why let that stop us? */ break; } } session->scpRecv_state = libssh2_NB_state_sent7; } if (sb) { memset(sb, 0, sizeof(struct stat)); sb->st_mtime = session->scpRecv_mtime; sb->st_atime = session->scpRecv_atime; sb->st_size = session->scpRecv_size; sb->st_mode = session->scpRecv_mode; } session->scpRecv_state = libssh2_NB_state_idle; return session->scpRecv_channel; scp_recv_empty_channel: /* the code only jumps here as a result of a zero read from channel_read() so we check EOF status to avoid getting stuck in a loop */ if(libssh2_channel_eof(session->scpRecv_channel)) _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Unexpected channel close"); else return session->scpRecv_channel; /* fall-through */ scp_recv_error: tmp_err_code = session->err_code; tmp_err_msg = session->err_msg; while (libssh2_channel_free(session->scpRecv_channel) == LIBSSH2_ERROR_EAGAIN); session->err_code = tmp_err_code; session->err_msg = tmp_err_msg; session->scpRecv_channel = NULL; session->scpRecv_state = libssh2_NB_state_idle; return NULL; }
/** * loop_and_copy (int infd, int outfd, struct seashell_connection* conn) * Copies data to/from the file descriptors and socket. * * * Arguments: * infd, outfd - input/output file descriptors. * conn - Seashell connection object. * * Returns: * 0 on clean disconnect, nonzero value otherwise. */ int loop_and_copy(int infd, int outfd, struct seashell_connection* conn) { struct timeval timeout; fd_set readfds; char buffer[4096]; ssize_t start = 0, len = 0, rc = 0; int nfds = 1 + MAX(infd, conn->sockfd); while (1) { FD_ZERO(&readfds); FD_SET(conn->sockfd, &readfds); FD_SET(infd, &readfds); timeout.tv_sec = 10; timeout.tv_usec = 0; if (select(nfds, &readfds, NULL, NULL, &timeout) > 0) { /** We're OK only when we have something to read from and something to write to. */ /** * Something to read from remote - might block on write, this is OK. * Time permitting, it might be nice to have a write queue and * go through the select loop again for fairness, * but it really doesn't matter. */ if (FD_ISSET(conn->sockfd, &readfds)) { /** Do our reads in nonblocking mode as we may get payload data for * some other stream. */ seashell_set_nonblocking(conn); len = libssh2_channel_read(conn->channel, buffer, sizeof(buffer)); seashell_set_blocking(conn); if (len == LIBSSH2_ERROR_EAGAIN) { } else if (len < 0) { return len; } else if (len > 0) { start = 0; while (len) { rc = write(outfd, buffer + start, len); if (rc < 0) { return rc; } len -= rc; start += rc; } } /** Drain stderr. */ seashell_set_nonblocking(conn); len = libssh2_channel_read_stderr(conn->channel, buffer, sizeof(buffer)); seashell_set_blocking(conn); if (len == LIBSSH2_ERROR_EAGAIN) { } else if (len < 0) { return len; } else if (len > 0) { start = 0; while (len) { rc = write(2, buffer + start, len); if (rc < 0) { return rc; } len -= rc; start += rc; } } } /** * Something to read from local - might block on write, this is OK. * See above for rationale, and libssh2_channel_write doesn't seem * to block nicely. Oh well. */ if (FD_ISSET(infd, &readfds)) { len = read(infd, buffer, sizeof(buffer)); if (len < 0) { return len; } else if (len == 0) { return 0; } else { start = 0; while (len) { rc = libssh2_channel_write(conn->channel, buffer + start, len); if (rc < 0) { return rc; } len -= rc; start += rc; } } } } /** * And if we died... */ if (libssh2_channel_eof(conn->channel) == 1) { return 0; } } }
int ssh2_forward_port(const char *hostip, const char *username, const char *password, int listenport, const char *desthost, int destport, int *initialized, int *finished, char **errmsg) { int rc, sock = -1, listensock = -1, forwardsock = -1, i; struct sockaddr_in sin; socklen_t sinlen; LIBSSH2_SESSION *session; LIBSSH2_CHANNEL *channel = NULL; const char *shost; unsigned int sport; fd_set fds; struct timeval tv; ssize_t len, wr; char buf[16384]; struct StringBuffer *sberrmsg = new_string_buffer(); #ifdef WIN32 char sockopt; WSADATA wsadata; WSAStartup(MAKEWORD(2,0), &wsadata); #else int sockopt; #endif rc = libssh2_init (0); if (rc != 0) { sbprintf (sberrmsg, "libssh2 initialization failed (%d)\n", rc); return 1; } /* Connect to SSH server */ sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(hostip))) { perror("inet_addr"); return -1; } sin.sin_port = htons(22); if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { sbprintf(sberrmsg, "failed to connect!\n"); return -1; } /* Create a session instance */ session = libssh2_session_init(); if(!session) { sbprintf(sberrmsg, "Could not initialize SSH session!\n"); return -1; } /* ... start it up. This will trade welcome banners, exchange keys, * and setup crypto, compression, and MAC layers */ rc = libssh2_session_handshake(session, sock); if(rc) { sbprintf(sberrmsg, "Error when starting up SSH session: %d\n", rc); return -1; } if (libssh2_userauth_password(session, username, password)) { sbprintf(sberrmsg, "Authentication by password failed.\n"); goto shutdown; } listensock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); sin.sin_family = AF_INET; sin.sin_port = htons(listenport); if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr("127.0.0.1"))) { sbprintf(sberrmsg, "inet_addr: %s.", strerror(errno)); goto shutdown; } sockopt = 1; setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)); sinlen=sizeof(sin); if (-1 == bind(listensock, (struct sockaddr *)&sin, sinlen)) { sbprintf(sberrmsg, "bind: %s.", strerror(errno)); goto shutdown; } if (-1 == listen(listensock, 2)) { sbprintf(sberrmsg, "listen: %s.", strerror(errno)); goto shutdown; } printf("Waiting for TCP connection on %s:%d...\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); *initialized = 1; forwardsock = accept(listensock, (struct sockaddr *)&sin, &sinlen); if (-1 == forwardsock) { sbprintf(sberrmsg, "accept: %s.", strerror(errno)); goto shutdown; } shost = inet_ntoa(sin.sin_addr); sport = ntohs(sin.sin_port); printf("Forwarding connection from %s:%d here to remote %s:%d\n", shost, sport, desthost, destport); channel = libssh2_channel_direct_tcpip_ex(session, desthost, destport, shost, sport); if (!channel) { sbprintf(sberrmsg, "Could not open the direct-tcpip channel!\n" "(Note that this can be a problem at the server!" " Please review the server logs.)\n"); goto shutdown; } /* Must use non-blocking IO hereafter due to the current libssh2 API */ libssh2_session_set_blocking(session, 0); while (1) { if(*finished) libssh2_channel_send_eof(channel); FD_ZERO(&fds); FD_SET(forwardsock, &fds); tv.tv_sec = 0; tv.tv_usec = 100000; rc = select(forwardsock + 1, &fds, NULL, NULL, &tv); if (-1 == rc) { sbprintf(sberrmsg, "select: %s.", strerror(errno)); goto shutdown; } if (rc && FD_ISSET(forwardsock, &fds)) { len = recv(forwardsock, buf, sizeof(buf), 0); if (len < 0) { perror("read"); goto shutdown; } else if (0 == len) { printf("The client at %s:%d disconnected!\n", shost, sport); goto shutdown; } wr = 0; do { i = libssh2_channel_write(channel, buf, len); if (i < 0) { sbprintf(sberrmsg, "libssh2_channel_write: %d\n", i); goto shutdown; } wr += i; } while(i > 0 && wr < len); } while (1) { len = libssh2_channel_read(channel, buf, sizeof(buf)); if (LIBSSH2_ERROR_EAGAIN == len) break; else if (len < 0) { sbprintf(sberrmsg, "libssh2_channel_read: %d", (int)len); goto shutdown; } wr = 0; while (wr < len) { i = send(forwardsock, buf + wr, len - wr, 0); if (i <= 0) { perror("write"); goto shutdown; } wr += i; } if (libssh2_channel_eof(channel)) { printf("The server at %s:%d disconnected!\n", desthost, destport); goto shutdown; } } } shutdown: fprintf(stderr, "finished = %d\n", *finished); #ifdef WIN32 closesocket(forwardsock); closesocket(listensock); #else close(forwardsock); close(listensock); #endif if (channel) libssh2_channel_free(channel); libssh2_session_disconnect(session, "Client disconnecting normally"); libssh2_session_free(session); #ifdef WIN32 closesocket(sock); #else close(sock); #endif libssh2_exit(); if(string_buffer_is_empty(sberrmsg)) { free_string_buffer(sberrmsg, 1); return 0; } *errmsg = free_string_buffer(sberrmsg, 0); return 1; }
/* * scp_send() * * Send a file using SCP * */ static LIBSSH2_CHANNEL * scp_send(LIBSSH2_SESSION * session, const char *path, int mode, libssh2_int64_t size, time_t mtime, time_t atime) { int cmd_len; int rc; int tmp_err_code; const char *tmp_err_msg; if (session->scpSend_state == libssh2_NB_state_idle) { session->scpSend_command_len = _libssh2_shell_quotedsize(path) + sizeof("scp -t ") + ((mtime || atime)?1:0); session->scpSend_command = LIBSSH2_ALLOC(session, session->scpSend_command_len); if (!session->scpSend_command) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a command buffer for scp session"); return NULL; } snprintf((char *)session->scpSend_command, session->scpSend_command_len, "scp -%st ", (mtime || atime)?"p":""); cmd_len = strlen((char *)session->scpSend_command); (void)shell_quotearg(path, &session->scpSend_command[cmd_len], session->scpSend_command_len - cmd_len); session->scpSend_command[session->scpSend_command_len - 1] = '\0'; _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Opening channel for SCP send"); /* Allocate a channel */ session->scpSend_state = libssh2_NB_state_created; } if (session->scpSend_state == libssh2_NB_state_created) { session->scpSend_channel = _libssh2_channel_open(session, "session", sizeof("session") - 1, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0); if (!session->scpSend_channel) { if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) { /* previous call set libssh2_session_last_error(), pass it through */ LIBSSH2_FREE(session, session->scpSend_command); session->scpSend_command = NULL; session->scpSend_state = libssh2_NB_state_idle; } else { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block starting up channel"); } return NULL; } session->scpSend_state = libssh2_NB_state_sent; } if (session->scpSend_state == libssh2_NB_state_sent) { /* Request SCP for the desired file */ rc = _libssh2_channel_process_startup(session->scpSend_channel, "exec", sizeof("exec") - 1, (char *) session->scpSend_command, session->scpSend_command_len); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting SCP startup"); return NULL; } else if (rc) { /* previous call set libssh2_session_last_error(), pass it through */ LIBSSH2_FREE(session, session->scpSend_command); session->scpSend_command = NULL; _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Unknown error while getting error string"); goto scp_send_error; } LIBSSH2_FREE(session, session->scpSend_command); session->scpSend_command = NULL; session->scpSend_state = libssh2_NB_state_sent1; } if (session->scpSend_state == libssh2_NB_state_sent1) { /* Wait for ACK */ rc = _libssh2_channel_read(session->scpSend_channel, 0, (char *) session->scpSend_response, 1); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response from remote"); return NULL; } else if (rc < 0) { _libssh2_error(session, rc, "SCP failure"); goto scp_send_error; } else if(!rc) /* remain in the same state */ goto scp_send_empty_channel; else if (session->scpSend_response[0] != 0) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote"); goto scp_send_error; } if (mtime || atime) { /* Send mtime and atime to be used for file */ session->scpSend_response_len = snprintf((char *) session->scpSend_response, LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n", (long)mtime, (long)atime); _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s", session->scpSend_response); } session->scpSend_state = libssh2_NB_state_sent2; } /* Send mtime and atime to be used for file */ if (mtime || atime) { if (session->scpSend_state == libssh2_NB_state_sent2) { rc = _libssh2_channel_write(session->scpSend_channel, 0, session->scpSend_response, session->scpSend_response_len); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending time data for SCP file"); return NULL; } else if (rc != (int)session->scpSend_response_len) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send time data for SCP file"); goto scp_send_error; } session->scpSend_state = libssh2_NB_state_sent3; } if (session->scpSend_state == libssh2_NB_state_sent3) { /* Wait for ACK */ rc = _libssh2_channel_read(session->scpSend_channel, 0, (char *) session->scpSend_response, 1); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response"); return NULL; } else if (rc < 0) { _libssh2_error(session, rc, "SCP failure"); goto scp_send_error; } else if(!rc) /* remain in the same state */ goto scp_send_empty_channel; else if (session->scpSend_response[0] != 0) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid SCP ACK response"); goto scp_send_error; } session->scpSend_state = libssh2_NB_state_sent4; } } else { if (session->scpSend_state == libssh2_NB_state_sent2) { session->scpSend_state = libssh2_NB_state_sent4; } } if (session->scpSend_state == libssh2_NB_state_sent4) { /* Send mode, size, and basename */ const char *base = strrchr(path, '/'); if (base) base++; else base = path; session->scpSend_response_len = snprintf((char *) session->scpSend_response, LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %" LIBSSH2_INT64_T_FORMAT " %s\n", mode, size, base); _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s", session->scpSend_response); session->scpSend_state = libssh2_NB_state_sent5; } if (session->scpSend_state == libssh2_NB_state_sent5) { rc = _libssh2_channel_write(session->scpSend_channel, 0, session->scpSend_response, session->scpSend_response_len); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block send core file data for SCP file"); return NULL; } else if (rc != (int)session->scpSend_response_len) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send core file data for SCP file"); goto scp_send_error; } session->scpSend_state = libssh2_NB_state_sent6; } if (session->scpSend_state == libssh2_NB_state_sent6) { /* Wait for ACK */ rc = _libssh2_channel_read(session->scpSend_channel, 0, (char *) session->scpSend_response, 1); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response"); return NULL; } else if (rc < 0) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote"); goto scp_send_error; } else if (rc == 0) goto scp_send_empty_channel; else if (session->scpSend_response[0] != 0) { size_t err_len; char *err_msg; err_len = _libssh2_channel_packet_data_len(session->scpSend_channel, 0); err_msg = LIBSSH2_ALLOC(session, err_len + 1); if (!err_msg) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "failed to get memory"); goto scp_send_error; } /* Read the remote error message */ rc = _libssh2_channel_read(session->scpSend_channel, 0, err_msg, err_len); if (rc > 0) { err_msg[err_len]=0; _libssh2_debug(session, LIBSSH2_TRACE_SCP, "got %02x %s", session->scpSend_response[0], err_msg); } LIBSSH2_FREE(session, err_msg); _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "failed to send file"); goto scp_send_error; } } session->scpSend_state = libssh2_NB_state_idle; return session->scpSend_channel; scp_send_empty_channel: /* the code only jumps here as a result of a zero read from channel_read() so we check EOF status to avoid getting stuck in a loop */ if(libssh2_channel_eof(session->scpSend_channel)) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Unexpected channel close"); } else return session->scpSend_channel; /* fall-through */ scp_send_error: tmp_err_code = session->err_code; tmp_err_msg = session->err_msg; while (libssh2_channel_free(session->scpSend_channel) == LIBSSH2_ERROR_EAGAIN); session->err_code = tmp_err_code; session->err_msg = tmp_err_msg; session->scpSend_channel = NULL; session->scpSend_state = libssh2_NB_state_idle; return NULL; }
int main(int argc, char *argv[]) { int rc, i, auth = AUTH_NONE; struct sockaddr_in sin; socklen_t sinlen = sizeof(sin); const char *fingerprint; char *userauthlist; LIBSSH2_SESSION *session; LIBSSH2_LISTENER *listener = NULL; LIBSSH2_CHANNEL *channel = NULL; fd_set fds; struct timeval tv; ssize_t len, wr; char buf[16384]; #ifdef WIN32 SOCKET sock = INVALID_SOCKET, forwardsock = INVALID_SOCKET; WSADATA wsadata; int err; err = WSAStartup(MAKEWORD(2,0), &wsadata); if (err != 0) { fprintf(stderr, "WSAStartup failed with error: %d\n", err); return 1; } #else int sock = -1, forwardsock = -1; #endif if (argc > 1) server_ip = argv[1]; if (argc > 2) username = argv[2]; if (argc > 3) password = argv[3]; if (argc > 4) remote_listenhost = argv[4]; if (argc > 5) remote_wantport = atoi(argv[5]); if (argc > 6) local_destip = argv[6]; if (argc > 7) local_destport = atoi(argv[7]); rc = libssh2_init (0); if (rc != 0) { fprintf (stderr, "libssh2 initialization failed (%d)\n", rc); return 1; } /* Connect to SSH server */ sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); #ifdef WIN32 if (sock == INVALID_SOCKET) { fprintf(stderr, "failed to open socket!\n"); return -1; } #else if (sock == -1) { perror("socket"); return -1; } #endif sin.sin_family = AF_INET; if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(server_ip))) { perror("inet_addr"); return -1; } sin.sin_port = htons(22); if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { fprintf(stderr, "failed to connect!\n"); return -1; } /* Create a session instance */ session = libssh2_session_init(); if(!session) { fprintf(stderr, "Could not initialize SSH session!\n"); return -1; } /* ... start it up. This will trade welcome banners, exchange keys, * and setup crypto, compression, and MAC layers */ rc = libssh2_session_handshake(session, sock); if(rc) { fprintf(stderr, "Error when starting up SSH session: %d\n", rc); return -1; } /* At this point we havn't yet authenticated. The first thing to do * is check the hostkey's fingerprint against our known hosts Your app * may have it hard coded, may go to a file, may present it to the * user, that's your call */ fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); fprintf(stderr, "Fingerprint: "); for(i = 0; i < 20; i++) fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]); fprintf(stderr, "\n"); /* check what authentication methods are available */ userauthlist = libssh2_userauth_list(session, username, strlen(username)); fprintf(stderr, "Authentication methods: %s\n", userauthlist); if (strstr(userauthlist, "password")) auth |= AUTH_PASSWORD; if (strstr(userauthlist, "publickey")) auth |= AUTH_PUBLICKEY; /* check for options */ if(argc > 8) { if ((auth & AUTH_PASSWORD) && !strcasecmp(argv[8], "-p")) auth = AUTH_PASSWORD; if ((auth & AUTH_PUBLICKEY) && !strcasecmp(argv[8], "-k")) auth = AUTH_PUBLICKEY; } if (auth & AUTH_PASSWORD) { if (libssh2_userauth_password(session, username, password)) { fprintf(stderr, "Authentication by password failed.\n"); goto shutdown; } } else if (auth & AUTH_PUBLICKEY) { if (libssh2_userauth_publickey_fromfile(session, username, keyfile1, keyfile2, password)) { fprintf(stderr, "\tAuthentication by public key failed!\n"); goto shutdown; } fprintf(stderr, "\tAuthentication by public key succeeded.\n"); } else { fprintf(stderr, "No supported authentication methods found!\n"); goto shutdown; } fprintf(stderr, "Asking server to listen on remote %s:%d\n", remote_listenhost, remote_wantport); listener = libssh2_channel_forward_listen_ex(session, remote_listenhost, remote_wantport, &remote_listenport, 1); if (!listener) { fprintf(stderr, "Could not start the tcpip-forward listener!\n" "(Note that this can be a problem at the server!" " Please review the server logs.)\n"); goto shutdown; } fprintf(stderr, "Server is listening on %s:%d\n", remote_listenhost, remote_listenport); fprintf(stderr, "Waiting for remote connection\n"); channel = libssh2_channel_forward_accept(listener); if (!channel) { fprintf(stderr, "Could not accept connection!\n" "(Note that this can be a problem at the server!" " Please review the server logs.)\n"); goto shutdown; } fprintf(stderr, "Accepted remote connection. Connecting to local server %s:%d\n", local_destip, local_destport); forwardsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); #ifdef WIN32 if (forwardsock == INVALID_SOCKET) { fprintf(stderr, "failed to open forward socket!\n"); goto shutdown; } #else if (forwardsock == -1) { perror("socket"); goto shutdown; } #endif sin.sin_family = AF_INET; sin.sin_port = htons(local_destport); if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(local_destip))) { perror("inet_addr"); goto shutdown; } if (-1 == connect(forwardsock, (struct sockaddr *)&sin, sinlen)) { perror("connect"); goto shutdown; } fprintf(stderr, "Forwarding connection from remote %s:%d to local %s:%d\n", remote_listenhost, remote_listenport, local_destip, local_destport); /* Must use non-blocking IO hereafter due to the current libssh2 API */ libssh2_session_set_blocking(session, 0); while (1) { FD_ZERO(&fds); FD_SET(forwardsock, &fds); tv.tv_sec = 0; tv.tv_usec = 100000; rc = select(forwardsock + 1, &fds, NULL, NULL, &tv); if (-1 == rc) { perror("select"); goto shutdown; } if (rc && FD_ISSET(forwardsock, &fds)) { len = recv(forwardsock, buf, sizeof(buf), 0); if (len < 0) { perror("read"); goto shutdown; } else if (0 == len) { fprintf(stderr, "The local server at %s:%d disconnected!\n", local_destip, local_destport); goto shutdown; } wr = 0; do { i = libssh2_channel_write(channel, buf, len); if (i < 0) { fprintf(stderr, "libssh2_channel_write: %d\n", i); goto shutdown; } wr += i; } while(i > 0 && wr < len); } while (1) { len = libssh2_channel_read(channel, buf, sizeof(buf)); if (LIBSSH2_ERROR_EAGAIN == len) break; else if (len < 0) { fprintf(stderr, "libssh2_channel_read: %d", (int)len); goto shutdown; } wr = 0; while (wr < len) { i = send(forwardsock, buf + wr, len - wr, 0); if (i <= 0) { perror("write"); goto shutdown; } wr += i; } if (libssh2_channel_eof(channel)) { fprintf(stderr, "The remote client at %s:%d disconnected!\n", remote_listenhost, remote_listenport); goto shutdown; } } } shutdown: #ifdef WIN32 closesocket(forwardsock); #else close(forwardsock); #endif if (channel) libssh2_channel_free(channel); if (listener) libssh2_channel_forward_cancel(listener); libssh2_session_disconnect(session, "Client disconnecting normally"); libssh2_session_free(session); #ifdef WIN32 closesocket(sock); #else close(sock); #endif libssh2_exit(); return 0; }
QString Parser::sshRequest(QString commandline) { QString host_ip(this->sharedHost); QString user_name=this->sharedUser; QString pass_word=this->sharedPass; //---------- connection -------------- int libssh2_error = libssh2_init(0); if(libssh2_error) { qDebug("libssh2_init() error: %d", libssh2_error); //return -2; } QTcpSocket socket; socket.connectToHost(host_ip, 22); if(!socket.waitForConnected()) { qDebug("Error connecting to host %s", host_ip.toLocal8Bit().constData()); //return -1; } LIBSSH2_SESSION *session = libssh2_session_init(); if(!session) { qDebug("libssh2_session_init() failed"); //return -2; } libssh2_error = libssh2_session_startup(session, socket.socketDescriptor()); if(libssh2_error) { qDebug("libssh2_session_startup() error: %d", libssh2_error); //return -3; } { /* At this point we havn't yet authenticated. The first thing to do * is check the hostkey's fingerprint against our known hosts Your app * may have it hard coded, may go to a file, may present it to the * user, that's your call */ const char *fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); } libssh2_userauth_list(session, user_name.toLocal8Bit().constData(), user_name.toLocal8Bit().length()); if(libssh2_userauth_password( session, user_name.toLocal8Bit().constData(), pass_word.toLocal8Bit().constData() )) { qDebug("Password authentication failed"); socket.disconnectFromHost(); libssh2_session_disconnect(session, "Client disconnecting for error"); libssh2_session_free(session); libssh2_exit(); //return -4; } // command channel //------------setup channel ---------------------- LIBSSH2_CHANNEL *channel = NULL; channel = libssh2_channel_open_session(session); int rc; if ( channel == NULL ) { qDebug()<<"Failed to open a new channel\n"; socket.disconnectFromHost(); //return -1; } libssh2_channel_set_blocking(channel, 1); while ((rc=libssh2_channel_exec(channel, commandline.toLocal8Bit().constData()))==LIBSSH2_ERROR_EAGAIN ); if (rc) { //return -1; } //-------read channel----------- int read; QByteArray byte_array; byte_array.resize(4096); char* buffer=byte_array.data(); int buffer_size=byte_array.size(); QString myOutPut; while(true) { { read = libssh2_channel_read(channel, buffer, buffer_size); QByteArray debug = QByteArray(buffer, read); //qDebug()<<"STDOUT: "<<debug.constData(); myOutPut = debug.constData(); qDebug() << myOutPut; if(LIBSSH2_ERROR_EAGAIN == read) { qDebug("LIBSSH2_ERROR_EAGAIN"); break; } else if(read < 0) { qDebug(" error reading from channel"); closeChannel(channel); goto next_channel; } } { read = libssh2_channel_read_stderr(channel, buffer, buffer_size); QByteArray debug = QByteArray(buffer, read); qDebug()<<"STDERR: "<<debug.constData(); if(LIBSSH2_ERROR_EAGAIN == read) { qDebug("LIBSSH2_ERROR_EAGAIN"); break; } else if(read < 0) { qDebug(" error reading from channel"); closeChannel(channel); goto next_channel; } } int i=0; i = libssh2_channel_eof(channel); if(i) { qDebug("libssh2_channel_eof %i", i); closeChannel(channel); goto next_channel; } } next_channel: //------------ clean session socket.disconnectFromHost(); libssh2_session_disconnect(session, "Client disconnecting normally"); libssh2_session_free(session); libssh2_exit(); return myOutPut; }