int open_shell(LIBSSH2_SESSION *session, LIBSSH2_CHANNEL **channel, int sock) { int rc; //while((*channel = libssh2_channel_open_session(session)) == NULL && libssh2_session_last_error(session,NULL,NULL,0) == LIBSSH2_ERROR_EAGAIN ) waitsocket(sock, session); *channel = libssh2_channel_open_session(session); if( *channel == NULL ) { fprintf(stderr,"Error\n"); exit(1); } // while((rc=libssh2_channel_request_pty(*channel, "vanilla")) == LIBSSH2_ERROR_EAGAIN ) waitsocket(sock, session); rc=libssh2_channel_request_pty(*channel, "vanilla"); if( rc != 0 ) { fprintf(stderr,"get pty Error %d\n", rc); exit(1); } // while((rc=libssh2_channel_shell(*channel)) == LIBSSH2_ERROR_EAGAIN ) waitsocket(sock, session); rc=libssh2_channel_shell(*channel); if( rc != 0 ) { fprintf(stderr,"get shell Error %d\n", rc); exit(1); } return rc; }
int SSH2Utils::exec(const char *cmd) { m_execResultStr.clear(); int rc = -1; LIBSSH2_CHANNEL *channel; /* Exec non-blocking on the remove host */ while ((channel = libssh2_channel_open_session(m_session)) == NULL && libssh2_session_last_error(m_session, NULL, NULL, 0) == LIBSSH2_ERROR_EAGAIN) { waitsocket(); } if (channel == NULL) { fprintf(stderr, "Channel Error\n"); m_errCode = 9; return -1; } /* Request a terminal with 'vanilla' terminal emulation * See /etc/termcap for more options */ if (libssh2_channel_request_pty(channel, "vanilla")) { fprintf(stderr, "Failed requesting pty\n"); } /* Open a SHELL on that pty */ if (libssh2_channel_shell(channel)) { fprintf(stderr, "Unable to request shell on allocated pty\n"); } libssh2_channel_write(channel, cmd, strlen(cmd)); libssh2_channel_send_eof(channel); char buffer[BUF_SIZE]; memset(buffer, 0, BUF_SIZE); rc = libssh2_channel_read(channel, buffer, BUF_SIZE); if (rc > 0) { m_execResultStr.append(buffer); } m_channelExitCode = 127; while ((rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN) waitsocket(); if (rc == 0) { m_channelExitCode = libssh2_channel_get_exit_status(channel); } skip_shell: if (channel) { libssh2_channel_free(channel); channel = NULL; } return rc; }
void cql_ccm_bridge_t::start_ssh_connection(const cql_ccm_bridge_configuration_t& settings) { _ssh_internals->_session = libssh2_session_init(); if (!_ssh_internals->_session) throw cql_ccm_bridge_exception_t("cannot create ssh session"); try { if (libssh2_session_handshake(_ssh_internals->_session, _socket)) throw cql_ccm_bridge_exception_t("ssh session handshake failed"); // get authentication modes supported by server char* auth_methods = libssh2_userauth_list(_ssh_internals->_session, settings.ssh_username().c_str(), settings.ssh_username().size()); int auth_result; if (!settings.ssh_public_key_file().empty() && !settings.ssh_private_key_file().empty()) { auth_result = libssh2_userauth_publickey_fromfile(_ssh_internals->_session, settings.ssh_username().c_str(), settings.ssh_public_key_file().c_str(), settings.ssh_private_key_file().c_str(), ""); } else { if (strstr(auth_methods, "password") == NULL) throw cql_ccm_bridge_exception_t("server doesn't support authentication by password"); // try to login using username and password auth_result = libssh2_userauth_password(_ssh_internals->_session, settings.ssh_username().c_str(), settings.ssh_password().c_str()); } if (auth_result != 0) throw cql_ccm_bridge_exception_t("invalid password or user"); if (!(_ssh_internals->_channel = libssh2_channel_open_session(_ssh_internals->_session))) throw cql_ccm_bridge_exception_t("cannot open ssh session"); try { if (libssh2_channel_request_pty(_ssh_internals->_channel, "vanilla")) throw cql_ccm_bridge_exception_t("pty requests failed"); if (libssh2_channel_shell(_ssh_internals->_channel)) throw cql_ccm_bridge_exception_t("cannot open shell"); //TODO: Copy SSL files to remote connection for CCM to enable SSL with Cassandra instances (or use keytool to simply generate the files remotely) } catch (cql_ccm_bridge_exception_t&) { // calls channel_close libssh2_channel_free(_ssh_internals->_channel); } } catch (cql_ccm_bridge_exception_t&) { close_ssh_session(); throw; } }
int main(int argc, char *argv[]) { unsigned long hostaddr; int rc, sock, i, auth_pw = 0; struct sockaddr_in sin; const char *fingerprint; char *userauthlist; LIBSSH2_SESSION *session; LIBSSH2_CHANNEL *channel; #ifdef WIN32 WSADATA wsadata; int err; err = WSAStartup(MAKEWORD(2,0), &wsadata); if (err != 0) { fprintf(stderr, "WSAStartup failed with error: %d\n", err); return 1; } #endif if (argc > 1) { hostaddr = inet_addr(argv[1]); } else { hostaddr = htonl(0x7F000001); } if(argc > 2) { username = argv[2]; } if(argc > 3) { password = argv[3]; } rc = libssh2_init (0); if (rc != 0) { fprintf (stderr, "libssh2 initialization failed (%d)\n", rc); return 1; } /* Ultra basic "connect to port 22 on localhost". Your code is * responsible for creating the socket establishing the connection */ sock = socket(AF_INET, SOCK_STREAM, 0); sin.sin_family = AF_INET; sin.sin_port = htons(22); sin.sin_addr.s_addr = hostaddr; if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { fprintf(stderr, "failed to connect!\n"); return -1; } /* Create a session instance and start it up. This will trade welcome * banners, exchange keys, and setup crypto, compression, and MAC layers */ session = libssh2_session_init(); if (libssh2_session_handshake(session, sock)) { fprintf(stderr, "Failure establishing SSH session\n"); return -1; } /* At this point we havn't 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") != NULL) { auth_pw |= 1; } if (strstr(userauthlist, "keyboard-interactive") != NULL) { auth_pw |= 2; } if (strstr(userauthlist, "publickey") != NULL) { auth_pw |= 4; } /* if we got an 4. argument we set this option if supported */ if(argc > 4) { if ((auth_pw & 1) && !strcasecmp(argv[4], "-p")) { auth_pw = 1; } if ((auth_pw & 2) && !strcasecmp(argv[4], "-i")) { auth_pw = 2; } if ((auth_pw & 4) && !strcasecmp(argv[4], "-k")) { auth_pw = 4; } } if (auth_pw & 1) { /* We could authenticate via password */ if (libssh2_userauth_password(session, username, password)) { fprintf(stderr, "\tAuthentication by password failed!\n"); goto shutdown; } else { fprintf(stderr, "\tAuthentication by password succeeded.\n"); } } else if (auth_pw & 2) { /* Or via keyboard-interactive */ if (libssh2_userauth_keyboard_interactive(session, username, &kbd_callback) ) { fprintf(stderr, "\tAuthentication by keyboard-interactive failed!\n"); goto shutdown; } else { fprintf(stderr, "\tAuthentication by keyboard-interactive succeeded.\n"); } } else if (auth_pw & 4) { /* Or by public key */ if (libssh2_userauth_publickey_fromfile(session, username, keyfile1, keyfile2, password)) { fprintf(stderr, "\tAuthentication by public key failed!\n"); goto shutdown; } else { fprintf(stderr, "\tAuthentication by public key succeeded.\n"); } } else { fprintf(stderr, "No supported authentication methods found!\n"); goto shutdown; } /* Request a shell */ if (!(channel = libssh2_channel_open_session(session))) { fprintf(stderr, "Unable to open a session\n"); goto shutdown; } /* Some environment variables may be set, * It's up to the server which ones it'll allow though */ libssh2_channel_setenv(channel, "FOO", "bar"); /* Request a terminal with 'vanilla' terminal emulation * See /etc/termcap for more options */ if (libssh2_channel_request_pty(channel, "vanilla")) { fprintf(stderr, "Failed requesting pty\n"); goto skip_shell; } /* Open a SHELL on that pty */ if (libssh2_channel_shell(channel)) { fprintf(stderr, "Unable to request shell on allocated pty\n"); goto shutdown; } /* At this point the shell can be interacted with using * libssh2_channel_read() * libssh2_channel_read_stderr() * libssh2_channel_write() * libssh2_channel_write_stderr() * * Blocking mode may be (en|dis)abled with: libssh2_channel_set_blocking() * If the server send EOF, libssh2_channel_eof() will return non-0 * To send EOF to the server use: libssh2_channel_send_eof() * A channel can be closed with: libssh2_channel_close() * A channel can be freed with: libssh2_channel_free() */ skip_shell: if (channel) { libssh2_channel_free(channel); channel = NULL; } /* Other channel types are supported via: * libssh2_scp_send() * libssh2_scp_recv() * libssh2_channel_direct_tcpip() */ shutdown: libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing"); libssh2_session_free(session); #ifdef WIN32 closesocket(sock); #else close(sock); #endif fprintf(stderr, "all done!\n"); libssh2_exit(); return 0; }
int ssh_shell_channel_open(void* ssh_session) { SSH_SESSION* p_session; LIBSSH2_CHANNEL* channel; int ec; p_session = (SSH_SESSION*)ssh_session; if(!(login_check(p_session))) { debug_log(SSH_TERMINAL_NO_SESSION_ERROR, "ssh_shell_channel_open : no session."); return SSH_TERMINAL_NO_SESSION_ERROR; } if(p_session->session_param->channel != NULL) { debug_log(SSH_TERMINAL_ALREADY_CHANNEL_OPEN, "ssh_shell_channel_open : already channel open."); return SSH_TERMINAL_ALREADY_CHANNEL_OPEN; } while((channel = libssh2_channel_open_session(p_session->session_param->session)) == NULL && libssh2_session_last_error(p_session->session_param->session, NULL, NULL, 0) == LIBSSH2_ERROR_EAGAIN) { waitsocket(p_session->session_param->sock, p_session->session_param->session, TIMEOUT_SEC); } if(channel == NULL) { debug_log(SSH_TERMINAL_CHANNEL_OPEN_ERROR, "ssh_shell_channel_open : channel open failed."); return SSH_TERMINAL_CHANNEL_OPEN_ERROR; } while((ec = libssh2_channel_request_pty(channel, "vt100")) == LIBSSH2_ERROR_EAGAIN) { waitsocket(p_session->session_param->sock, p_session->session_param->session, TIMEOUT_SEC);; } if(ec < 0){ debug_log(SSH_TERMINAL_REQUEST_PTY_ERROR, "ssh_shell_channel_open : request pty failed."); while(libssh2_channel_close(channel) == LIBSSH2_ERROR_EAGAIN) { waitsocket(p_session->session_param->sock, p_session->session_param->session, TIMEOUT_SEC); } libssh2_channel_free(channel); return SSH_TERMINAL_REQUEST_PTY_ERROR; } while((ec = libssh2_channel_request_pty_size(channel, DEFAULT_PTY_SIZE_WIDTH, DEFAULT_PTY_SIZE_HEIGHT)) == LIBSSH2_ERROR_EAGAIN) { waitsocket(p_session->session_param->sock, p_session->session_param->session, TIMEOUT_SEC); } if(ec < 0){ debug_log(SSH_TERMINAL_REQUEST_PTY_ERROR, "ssh_shell_channel_open : request pty failed."); while(libssh2_channel_close(channel) == LIBSSH2_ERROR_EAGAIN) { waitsocket(p_session->session_param->sock, p_session->session_param->session, TIMEOUT_SEC); } libssh2_channel_free(channel); return SSH_TERMINAL_REQUEST_PTY_ERROR; } while((ec = libssh2_channel_shell(channel)) == LIBSSH2_ERROR_EAGAIN) { waitsocket(p_session->session_param->sock, p_session->session_param->session, TIMEOUT_SEC); } if(ec < 0) { debug_log(SSH_TERMINAL_SHELL_ERROR, "ssh_shell_channel_open : channel shell failed."); while(libssh2_channel_close(channel) == LIBSSH2_ERROR_EAGAIN) { waitsocket(p_session->session_param->sock, p_session->session_param->session, TIMEOUT_SEC); } libssh2_channel_free(channel); return SSH_TERMINAL_SHELL_ERROR; } p_session->session_param->channel = channel; p_session->session_param->channel_type = CHANNEL_TYPE_SHELL; return 0; }
bool QxtSshChannelPrivate::activate(){ //session if(d_state==1){ d_channel=libssh2_channel_open_session(d_session); if(d_channel==NULL){ if(libssh2_session_last_error(d_session,NULL,NULL,0)==LIBSSH2_ERROR_EAGAIN) { return true; }else{ return false; } } #ifdef QXT_DEBUG_SSH qDebug("session opened"); #endif d_state=2; return activate(); //transition to allow early cmd }else if (d_state==2){ if(!d_next_actions.isEmpty()){ d_state=d_next_actions.takeFirst(); return activate(); }else{ return true; } //request pty }else if (d_state==5){ int r=libssh2_channel_request_pty(d_channel,d_pty.data()); if(r){ if(r==LIBSSH2_ERROR_EAGAIN){ return true; }else{ qWarning("QxtSshChannel: pty allocation failed"); return false; } } #ifdef QXT_DEBUG_SSH qDebug("pty opened"); #endif d_state=2; return activate(); //start }else if (d_state==3){ int r=libssh2_channel_exec(d_channel,qPrintable(d_cmd)); if(r){ if(r==LIBSSH2_ERROR_EAGAIN){ return true; }else{ #ifdef QXT_DEBUG_SSH qDebug("exec failed"); #endif return false; } } #ifdef QXT_DEBUG_SSH qDebug("exec opened"); #endif p->setOpenMode(QIODevice::ReadWrite); d_state=66; emit p->connected(); return true; //start shell }else if (d_state==4){ int r=libssh2_channel_shell(d_channel); if(r){ if(r==LIBSSH2_ERROR_EAGAIN){ return true; }else{ #ifdef QXT_DEBUG_SSH qDebug("exec failed"); #endif return false; } } #ifdef QXT_DEBUG_SSH qDebug("shell opened"); #endif p->setOpenMode(QIODevice::ReadWrite); d_state=9999; emit p->connected(); return true; // tcp channel }else if (d_state==10){ d_channel=libssh2_channel_direct_tcpip(d_session, qPrintable(d_host),d_port); if(d_channel==NULL){ if(libssh2_session_last_error(d_session,NULL,NULL,0)==LIBSSH2_ERROR_EAGAIN) { return true; }else{ return false; } } #ifdef QXT_DEBUG_SSH qDebug("tcp channel opened"); #endif p->setOpenMode(QIODevice::ReadWrite); d_state=9999; return activate(); //read channel }else if (d_state==9999){ emit p->readyRead(); } return true; }
int main(int argc, char *argv[]) { unsigned long hostaddr; int sock, i, auth_pw = 0; struct sockaddr_in sin; const char *fingerprint; char *userauthlist; LIBSSH2_SESSION *session; LIBSSH2_CHANNEL *channel; #ifdef WIN32 WSADATA wsadata; WSAStartup(MAKEWORD(2,0), &wsadata); #endif const char *pubkeyfile="etc/user.pub"; const char *privkeyfile="etc/user"; const char *username="******"; const char *password="******"; int ec = 1; (void)argc; (void)argv; if (getenv ("USER")) username = getenv ("USER"); if (getenv ("PRIVKEY")) privkeyfile = getenv ("PRIVKEY"); if (getenv ("PRIVKEY")) pubkeyfile = getenv ("PUBKEY"); hostaddr = htonl(0x7F000001); sock = socket(AF_INET, SOCK_STREAM, 0); #ifndef WIN32 fcntl(sock, F_SETFL, 0); #endif sin.sin_family = AF_INET; sin.sin_port = htons(4711); sin.sin_addr.s_addr = hostaddr; if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { fprintf(stderr, "failed to connect!\n"); return -1; } /* Create a session instance and start it up * This will trade welcome banners, exchange keys, and setup crypto, compression, and MAC layers */ session = libssh2_session_init(); if (libssh2_session_startup(session, sock)) { fprintf(stderr, "Failure establishing SSH session\n"); return -1; } /* At this point we havn't 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_MD5); printf("Fingerprint: "); for(i = 0; i < 16; i++) { printf("%02X ", (unsigned char)fingerprint[i]); } printf("\n"); /* check what authentication methods are available */ userauthlist = libssh2_userauth_list(session, username, strlen(username)); printf("Authentication methods: %s\n", userauthlist); if (strstr(userauthlist, "password") != NULL) { auth_pw |= 1; } if (strstr(userauthlist, "keyboard-interactive") != NULL) { auth_pw |= 2; } if (strstr(userauthlist, "publickey") != NULL) { auth_pw |= 4; } if (auth_pw & 4) { /* Authenticate by public key */ if (libssh2_userauth_publickey_fromfile(session, username, pubkeyfile, privkeyfile, password)) { printf("\tAuthentication by public key failed!\n"); goto shutdown; } else { printf("\tAuthentication by public key succeeded.\n"); } } else { printf("No supported authentication methods found!\n"); goto shutdown; } /* Request a shell */ if (!(channel = libssh2_channel_open_session(session))) { fprintf(stderr, "Unable to open a session\n"); goto shutdown; } /* Some environment variables may be set, * It's up to the server which ones it'll allow though */ libssh2_channel_setenv(channel, "FOO", "bar"); /* Request a terminal with 'vanilla' terminal emulation * See /etc/termcap for more options */ if (libssh2_channel_request_pty(channel, "vanilla")) { fprintf(stderr, "Failed requesting pty\n"); goto skip_shell; } /* Open a SHELL on that pty */ if (libssh2_channel_shell(channel)) { fprintf(stderr, "Unable to request shell on allocated pty\n"); goto shutdown; } ec = 0; skip_shell: if (channel) { libssh2_channel_free(channel); channel = NULL; } shutdown: libssh2_session_disconnect(session, "Normal Shutdown"); libssh2_session_free(session); #ifdef WIN32 Sleep(1000); closesocket(sock); #else sleep(1); close(sock); #endif return ec; }
int main(int argc, char *argv[]) { unsigned long hostaddr; int sock = -1, i, rc; struct sockaddr_in sin; const char *fingerprint; char *userauthlist; LIBSSH2_SESSION *session = NULL; LIBSSH2_CHANNEL *channel; LIBSSH2_AGENT *agent = NULL; struct libssh2_agent_publickey *identity, *prev_identity = NULL; #ifdef WIN32 WSADATA wsadata; WSAStartup(MAKEWORD(2,0), &wsadata); #endif if (argc > 1) { hostaddr = inet_addr(argv[1]); } else { hostaddr = htonl(0x7F000001); } if(argc > 2) { username = argv[2]; } rc = libssh2_init (0); if (rc != 0) { fprintf (stderr, "libssh2 initialization failed (%d)\n", rc); return 1; } /* Ultra basic "connect to port 22 on localhost". Your code is * responsible for creating the socket establishing the connection */ sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { fprintf(stderr, "failed to create socket!\n"); rc = 1; goto shutdown; } sin.sin_family = AF_INET; sin.sin_port = htons(22); sin.sin_addr.s_addr = hostaddr; if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { fprintf(stderr, "failed to connect!\n"); goto shutdown; } /* Create a session instance and start it up. This will trade welcome * banners, exchange keys, and setup crypto, compression, and MAC layers */ session = libssh2_session_init(); if (libssh2_session_handshake(session, sock)) { fprintf(stderr, "Failure establishing SSH session\n"); return 1; } /* At this point we havn't 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, "publickey") == NULL) { fprintf(stderr, "\"publickey\" authentication is not supported\n"); goto shutdown; } /* Connect to the ssh-agent */ agent = libssh2_agent_init(session); if (!agent) { fprintf(stderr, "Failure initializing ssh-agent support\n"); rc = 1; goto shutdown; } if (libssh2_agent_connect(agent)) { fprintf(stderr, "Failure connecting to ssh-agent\n"); rc = 1; goto shutdown; } if (libssh2_agent_list_identities(agent)) { fprintf(stderr, "Failure requesting identities to ssh-agent\n"); rc = 1; goto shutdown; } while (1) { rc = libssh2_agent_get_identity(agent, &identity, prev_identity); if (rc == 1) break; if (rc < 0) { fprintf(stderr, "Failure obtaining identity from ssh-agent support\n"); rc = 1; goto shutdown; } if (libssh2_agent_userauth(agent, username, identity)) { fprintf(stderr, "\tAuthentication with username %s and " "public key %s failed!\n", username, identity->comment); } else { fprintf(stderr, "\tAuthentication with username %s and " "public key %s succeeded!\n", username, identity->comment); break; } prev_identity = identity; } if (rc) { fprintf(stderr, "Couldn't continue authentication\n"); goto shutdown; } /* We're authenticated now. */ /* Request a shell */ if (!(channel = libssh2_channel_open_session(session))) { fprintf(stderr, "Unable to open a session\n"); goto shutdown; } /* Some environment variables may be set, * It's up to the server which ones it'll allow though */ libssh2_channel_setenv(channel, "FOO", "bar"); /* Request a terminal with 'vanilla' terminal emulation * See /etc/termcap for more options */ if (libssh2_channel_request_pty(channel, "vanilla")) { fprintf(stderr, "Failed requesting pty\n"); goto skip_shell; } /* Open a SHELL on that pty */ if (libssh2_channel_shell(channel)) { fprintf(stderr, "Unable to request shell on allocated pty\n"); goto shutdown; } /* At this point the shell can be interacted with using * libssh2_channel_read() * libssh2_channel_read_stderr() * libssh2_channel_write() * libssh2_channel_write_stderr() * * Blocking mode may be (en|dis)abled with: libssh2_channel_set_blocking() * If the server send EOF, libssh2_channel_eof() will return non-0 * To send EOF to the server use: libssh2_channel_send_eof() * A channel can be closed with: libssh2_channel_close() * A channel can be freed with: libssh2_channel_free() */ skip_shell: if (channel) { libssh2_channel_free(channel); channel = NULL; } /* Other channel types are supported via: * libssh2_scp_send() * libssh2_scp_recv() * libssh2_channel_direct_tcpip() */ shutdown: libssh2_agent_disconnect(agent); libssh2_agent_free(agent); if(session) { libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing"); libssh2_session_free(session); } if (sock != -1) { #ifdef WIN32 closesocket(sock); #else close(sock); #endif } fprintf(stderr, "all done!\n"); libssh2_exit(); return rc; }
bool ShellChannel::handleOpening() { int rc; if (mInternalStatus == _OpenSession) { mHandle = libssh2_channel_open_session(mSession->sessionHandle()); if (mHandle == NULL) { int rc = libssh2_session_last_errno(mSession->sessionHandle()); if (rc == LIBSSH2_ERROR_EAGAIN) return true; else { if (rc == LIBSSH2_ERROR_CHANNEL_FAILURE) // This channel needs to be given away; this connection can't handle it. // TODO: Detect if this channel request has been handed off too often and kill it if so. setSession(NULL); else criticalError(tr("Failed to open a channel %1: %2").arg((unsigned long)mHandle, 0, 16).arg(rc)); return false; } } setInternalStatus(_RequestPty); } if (mInternalStatus == _RequestPty) { // Due to a bug in OpenSSH (popular server-side implementation of SSH), we must simulate blocking for PTY request. while ((rc = libssh2_channel_request_pty(mHandle, mPtyType)) == LIBSSH2_ERROR_EAGAIN) {}; if (rc < 0) { criticalError(tr("Failed to request an appropriate pty %1: %2").arg((unsigned long)mHandle, 0, 16).arg(rc)); return false; } setInternalStatus(_StartShell); } if (mInternalStatus == _StartShell) { if (mMachineReadable) rc = libssh2_channel_exec(mHandle, "sh"); else rc = libssh2_channel_shell(mHandle); if (rc < 0) { if (rc == -1) rc = libssh2_session_last_errno(mSession->sessionHandle()); if (rc == LIBSSH2_ERROR_EAGAIN) return true; criticalError(tr("Failed to open a shell %1: %2").arg((unsigned long)mHandle, 0, 16).arg(rc)); return false; } if (mMachineReadable) setInternalStatus(_SendInit); else shellReady(); } if (mInternalStatus == _SendInit) { SendResponse r = sendData(MACHINE_READABLE_INIT); if (r == SendAgain) return true; if (r != SendSucceed) criticalError("Failed to send shell initializer"); setInternalStatus(_WaitForInitReply); } if (mInternalStatus == _WaitForInitReply) { ReadReply reply = readUntilPrompt(); if (reply.readAgain) return true; if (reply.data.isNull()) return false; shellReady(); } return true; }