desarrollosconsejeria/siaticControl/3.3-13/SIATICControl/qsshsocket.cpp @ 29401061
29401061 | Elisa | #include "qsshsocket.h"
|
|
#include <QFileInfo>
|
|||
QSshSocket::QSshSocket(QObject * parent )
|
|||
:QThread(parent)
|
|||
{
|
|||
m_host = "";
|
|||
m_user = "";
|
|||
m_password = "";
|
|||
m_port = -1;
|
|||
m_loggedIn = false;
|
|||
m_session = NULL;
|
|||
m_clone = NULL;
|
|||
m_workingDirectory = ".";
|
|||
qRegisterMetaType<QSshSocket::SshError>("QSshSocket::SshError");
|
|||
m_currentOperation.executed = true;
|
|||
m_run = true;
|
|||
start();
|
|||
}
|
|||
QSshSocket::~QSshSocket()
|
|||
{
|
|||
if (m_session != NULL)
|
|||
ssh_free(m_session);
|
|||
m_run = false;
|
|||
this->wait();
|
|||
}
|
|||
void QSshSocket::run()
|
|||
{
|
|||
while(m_run)
|
|||
{
|
|||
if (m_session == NULL)
|
|||
{
|
|||
if (m_host != "")
|
|||
m_attemptConnect();
|
|||
}
|
|||
// if we have a vaild ssh connection, authenticate connection with credentials
|
|||
else if (!m_loggedIn)
|
|||
{
|
|||
// check to see if a username and a password have been given
|
|||
if (m_user != "" && m_password !="")
|
|||
m_attemptLogin();
|
|||
}
|
|||
// if all ssh setup has been completed, check to see if we have any commands to execute
|
|||
else if (!m_currentOperation.executed)
|
|||
{
|
|||
if (m_currentOperation.type == Command || m_currentOperation.type == WorkingDirectoryTest)
|
|||
m_attemptCommand();
|
|||
// if all ssh setup has been completed, check to see if we have any file transfers to execute
|
|||
else if (m_currentOperation.type == Pull)
|
|||
m_attemptPull();
|
|||
else if (m_currentOperation.type == Push)
|
|||
m_attemptPush();
|
|||
m_currentOperation.executed = true;
|
|||
}
|
|||
else
|
|||
{
|
|||
msleep(100);
|
|||
}
|
|||
}
|
|||
}
|
|||
void QSshSocket::clone()
|
|||
{
|
|||
m_clone = new QSshSocket(this->parent());
|
|||
connect(m_clone,SIGNAL(connected()),this,SLOT(m_onCloneConnect()));
|
|||
connect(m_clone,SIGNAL(loginSuccessful()),this,SLOT(m_onCloneLoggedIn()));
|
|||
connect(m_clone,SIGNAL(workingDirectorySet(QString)),this,SLOT(m_onCloneCWDSet(QString)));
|
|||
connect(m_clone,SIGNAL(error(QSshSocket::SshError)),this,SLOT(m_onCloneError(QSshSocket::SshError)));
|
|||
if (m_connected)
|
|||
m_clone->connectToHost(m_host,m_port,m_loggingProtocol);
|
|||
else
|
|||
{
|
|||
m_releaseClone();
|
|||
cloned(m_clone);
|
|||
m_clone = NULL;
|
|||
}
|
|||
}
|
|||
void QSshSocket::m_releaseClone()
|
|||
{
|
|||
disconnect(m_clone,SIGNAL(connected()),this,SLOT(m_onCloneConnect()));
|
|||
disconnect(m_clone,SIGNAL(loginSuccessful()),this,SLOT(m_onCloneLoggedIn()));
|
|||
disconnect(m_clone,SIGNAL(workingDirectorySet(QString)),this,SLOT(m_onCloneCWDSet(QString)));
|
|||
disconnect(m_clone,SIGNAL(error(QSshSocket::SshError)),this,SLOT(m_onCloneError(QSshSocket::SshError)));
|
|||
}
|
|||
void QSshSocket::m_onCloneConnect()
|
|||
{
|
|||
if (m_loggedIn)
|
|||
m_clone->login(m_user,m_password);
|
|||
else
|
|||
{
|
|||
m_releaseClone();
|
|||
cloned(m_clone);
|
|||
m_clone = NULL;
|
|||
}
|
|||
}
|
|||
void QSshSocket::m_onCloneLoggedIn()
|
|||
{
|
|||
if (m_workingDirectory != ".")
|
|||
m_clone->setWorkingDirectory(m_workingDirectory);
|
|||
else
|
|||
{
|
|||
m_releaseClone();
|
|||
cloned(m_clone);
|
|||
m_clone = NULL;
|
|||
}
|
|||
}
|
|||
void QSshSocket::m_onCloneCWDSet(QString cwd)
|
|||
{
|
|||
Q_UNUSED(cwd);
|
|||
m_releaseClone();
|
|||
cloned(m_clone);
|
|||
m_clone = NULL;
|
|||
}
|
|||
void QSshSocket::m_onCloneError(QSshSocket::SshError)
|
|||
{
|
|||
m_releaseClone();
|
|||
error(QSshSocket::CloneError);
|
|||
m_clone = NULL;
|
|||
}
|
|||
void QSshSocket::disconnectFromHost()
|
|||
{
|
|||
m_host = "";
|
|||
m_user = "";
|
|||
m_password = "";
|
|||
m_port = -1;
|
|||
m_loggedIn = false;
|
|||
m_clone = NULL;
|
|||
if (m_session != NULL)
|
|||
{
|
|||
ssh_disconnect(m_session);
|
|||
//ssh_free(m_session);
|
|||
}
|
|||
m_session = NULL;
|
|||
}
|
|||
void QSshSocket::connectToHost(QString host, int port,LoggingProtocol logging)
|
|||
{
|
|||
m_host = host;
|
|||
m_port = port;
|
|||
m_loggingProtocol = logging;
|
|||
}
|
|||
void QSshSocket::login(QString user, QString password)
|
|||
{
|
|||
m_user = user;
|
|||
m_password = password;
|
|||
}
|
|||
void QSshSocket::executeCommand(QString command)
|
|||
{
|
|||
m_currentOperation.type = Command;
|
|||
if (m_workingDirectory != ".")
|
|||
m_currentOperation.adminCommand = "cd " + m_workingDirectory + "; " + command;
|
|||
else
|
|||
m_currentOperation.adminCommand = command ;
|
|||
m_currentOperation.command =command;
|
|||
m_currentOperation.executed = false;
|
|||
}
|
|||
void QSshSocket::executeCommandResponse(QString command , QString response){
|
|||
m_currentOperation.type = Command;
|
|||
if (m_workingDirectory != ".")
|
|||
m_currentOperation.adminCommand = "cd " + m_workingDirectory + "; " + command;
|
|||
else
|
|||
m_currentOperation.adminCommand = command ;
|
|||
m_currentOperation.command =command;
|
|||
m_currentOperation.executed = false;
|
|||
}
|
|||
void QSshSocket::pullFile(QString localPath, QString remotePath)
|
|||
{
|
|||
m_currentOperation.localPath = localPath;
|
|||
if (QFileInfo(remotePath).isAbsolute())
|
|||
m_currentOperation.remotePath = remotePath;
|
|||
else
|
|||
m_currentOperation.remotePath = m_workingDirectory + "/" + remotePath;
|
|||
m_currentOperation.type = Pull;
|
|||
m_currentOperation.executed = false;
|
|||
}
|
|||
void QSshSocket::pushFile(QString localPath, QString remotePath)
|
|||
{
|
|||
m_currentOperation.localPath = localPath;
|
|||
if (QFileInfo(remotePath).isAbsolute())
|
|||
m_currentOperation.remotePath = remotePath;
|
|||
else
|
|||
m_currentOperation.remotePath = m_workingDirectory + "/" + remotePath;
|
|||
m_currentOperation.type = Push;
|
|||
m_currentOperation.executed = false;
|
|||
}
|
|||
void QSshSocket::setWorkingDirectory(QString path)
|
|||
{
|
|||
m_nextWorkingDir = path;
|
|||
m_currentOperation.type = WorkingDirectoryTest;
|
|||
m_currentOperation.adminCommand = "[ -d " + m_nextWorkingDir +" ] && echo 'exists'";
|
|||
m_currentOperation.executed = false;
|
|||
}
|
|||
bool QSshSocket::isConnected()
|
|||
{
|
|||
return m_session != NULL;
|
|||
}
|
|||
bool QSshSocket::isLoggedIn()
|
|||
{
|
|||
return m_loggedIn;
|
|||
}
|
|||
QString QSshSocket::user(){return m_user;}
|
|||
QString QSshSocket::password(){return m_password;}
|
|||
QString QSshSocket::host(){return m_host;}
|
|||
int QSshSocket::port(){return m_port;}
|
|||
void QSshSocket::m_attemptConnect()
|
|||
{
|
|||
m_session = ssh_new();
|
|||
// set the pertinant ssh session options
|
|||
ssh_options_set(m_session, SSH_OPTIONS_HOST, m_host.toLatin1().data());
|
|||
ssh_options_set(m_session, SSH_OPTIONS_LOG_VERBOSITY, &m_loggingProtocol);
|
|||
ssh_options_set(m_session, SSH_OPTIONS_PORT, &m_port);
|
|||
// try to connect given host, user, port
|
|||
int connectionResponse = ssh_connect(m_session);
|
|||
// if connection is Successful keep track of connection info.
|
|||
if (connectionResponse == SSH_OK)
|
|||
{
|
|||
m_connected = true;
|
|||
connected();
|
|||
}
|
|||
else
|
|||
error(SessionCreationError);
|
|||
}
|
|||
void QSshSocket::m_attemptLogin()
|
|||
{
|
|||
// try authenticating current user at remote host
|
|||
int worked = ssh_userauth_password(m_session, m_user.toLatin1().data(), m_password.toLatin1().data());
|
|||
// if successful, store user password.
|
|||
if (worked == SSH_OK)
|
|||
{
|
|||
loginSuccessful();
|
|||
m_loggedIn = true;
|
|||
}
|
|||
else
|
|||
{
|
|||
m_user = "";
|
|||
m_password = "";
|
|||
error(PasswordAuthenticationFailedError);
|
|||
}
|
|||
}
|
|||
void QSshSocket::m_attemptCommand()
|
|||
{
|
|||
//if (m_loggingProtocol == LogAll || m_loggingProtocol == LogOperations)
|
|||
//qDebug() << "!!! Command '" << m_currentOperation.command << "'' executing on "<< m_user << "@" << m_host <<" at working directory " << m_workingDirectory << " ... RESPONSE: "<< SSH_AGAIN;
|
|||
// attempt to open ssh shell channel
|
|||
ssh_channel channel = ssh_channel_new(m_session);
|
|||
// if attempt fails,return
|
|||
if (ssh_channel_open_session(channel) != SSH_OK)
|
|||
{
|
|||
error(ChannelCreationError);
|
|||
return;
|
|||
}
|
|||
int requestResponse = SSH_AGAIN;
|
|||
// attempt to execute shell command
|
|||
while (requestResponse == SSH_AGAIN)
|
|||
requestResponse = ssh_channel_request_exec(channel, m_currentOperation.adminCommand.toLatin1().data());
|
|||
// if attempt not executed, close connection then return
|
|||
if (requestResponse != SSH_OK)
|
|||
{
|
|||
error(ChannelCreationError);
|
|||
return;
|
|||
}
|
|||
QByteArray buffer;
|
|||
buffer.resize(1000);
|
|||
// read in std out
|
|||
int totalBytes = 0, newBytes = 0;
|
|||
do
|
|||
{
|
|||
newBytes = ssh_channel_read(channel, &(buffer.data()[totalBytes]), buffer.size() - totalBytes, 0);
|
|||
if (newBytes > 0)
|
|||
totalBytes += newBytes;
|
|||
}while ( newBytes > 0);
|
|||
QString stdOut = QString(buffer).mid(0,totalBytes);
|
|||
// read in std err
|
|||
totalBytes = 0, newBytes = 0;
|
|||
do
|
|||
{
|
|||
newBytes = ssh_channel_read(channel, &(buffer.data()[totalBytes]), buffer.size() - totalBytes, 1);
|
|||
if (newBytes > 0)
|
|||
totalBytes += newBytes;
|
|||
}while ( newBytes > 0);
|
|||
QString stdErr = QString(buffer).mid(0,totalBytes);
|
|||
if (totalBytes >0)
|
|||
{
|
|||
//qDebug() << ssh_get_error(m_session);
|
|||
}
|
|||
// close channel
|
|||
ssh_channel_send_eof(channel);
|
|||
ssh_channel_close(channel);
|
|||
ssh_channel_free(channel);
|
|||
if (m_currentOperation.type == WorkingDirectoryTest)
|
|||
{
|
|||
if (stdOut.contains("exists"))
|
|||
m_workingDirectory = m_nextWorkingDir;
|
|||
m_nextWorkingDir = ".";
|
|||
workingDirectorySet(m_workingDirectory);
|
|||
}
|
|||
else{
|
|||
commandExecuted( m_currentOperation.command, stdOut,stdErr) ;
|
|||
emit onCommandReceived(stdOut);
|
|||
//qDebug() << " A RESPONDER: "<< stdOut;
|
|||
}
|
|||
}
|
|||
void QSshSocket::m_attemptPull()
|
|||
{
|
|||
//if (m_loggingProtocol == LogAll || m_loggingProtocol == LogOperations)
|
|||
//qDebug() << "!!! Remote file '"<< m_currentOperation.remotePath << "'' being pulled to local file '"<< m_currentOperation.localPath <<"'' ..." ;
|
|||
ssh_scp scpSession = ssh_scp_new(m_session,SSH_SCP_READ, m_currentOperation.remotePath.toLatin1().data());
|
|||
if (scpSession == NULL)
|
|||
error(ScpChannelCreationError);
|
|||
// attempt to initialize new scp session.
|
|||
int scpInitialized = ssh_scp_init(scpSession);
|
|||
if(scpInitialized != SSH_OK)
|
|||
{
|
|||
ssh_scp_close(scpSession);
|
|||
ssh_scp_free(scpSession);
|
|||
error(ScpChannelCreationError);
|
|||
return;
|
|||
}
|
|||
// attempt to authorize new scp pull
|
|||
if (ssh_scp_pull_request(scpSession) != SSH_SCP_REQUEST_NEWFILE)
|
|||
{
|
|||
ssh_scp_close(scpSession);
|
|||
ssh_scp_free(scpSession);
|
|||
error(ScpPullRequestError);
|
|||
return;
|
|||
}
|
|||
// accept authorization
|
|||
ssh_scp_accept_request(scpSession);
|
|||
// get remote file size
|
|||
int size = ssh_scp_request_get_size(scpSession);
|
|||
// resize buffer, read remote file into buffer
|
|||
QByteArray buffer;
|
|||
buffer.resize(size);
|
|||
// if an error happens while reading, close the scp session and return
|
|||
if (ssh_scp_read(scpSession, buffer.data() , size) == SSH_ERROR)
|
|||
{
|
|||
ssh_scp_close(scpSession);
|
|||
ssh_scp_free(scpSession);
|
|||
error(ScpReadError);
|
|||
return;
|
|||
}
|
|||
// loop until eof flag
|
|||
if (ssh_scp_pull_request(scpSession) != SSH_SCP_REQUEST_EOF)
|
|||
{
|
|||
ssh_scp_close(scpSession);
|
|||
ssh_scp_free(scpSession);
|
|||
error(ScpReadError);
|
|||
return;
|
|||
}
|
|||
//close scp session
|
|||
ssh_scp_close(scpSession);
|
|||
ssh_scp_free(scpSession);
|
|||
// open up local file and write contents of buffer to it.
|
|||
QFile file(m_currentOperation.localPath);
|
|||
file.open(QIODevice::WriteOnly);
|
|||
file.write(buffer);
|
|||
file.close();
|
|||
pullSuccessful(m_currentOperation.localPath,m_currentOperation.remotePath);
|
|||
}
|
|||
void QSshSocket::m_attemptPush()
|
|||
{
|
|||
//if (m_loggingProtocol == LogAll || m_loggingProtocol == LogOperations)
|
|||
//qDebug() << "!!! Local file '" << m_currentOperation.localPath <<"'' being pushed to remote file '"<< m_currentOperation.remotePath << "'' ..." ;
|
|||
// attempt to create new scp from ssh session.
|
|||
ssh_scp scpSession = ssh_scp_new(m_session,SSH_SCP_WRITE, m_currentOperation.remotePath.toLatin1().data());
|
|||
// if creation failed, return
|
|||
if (scpSession == NULL)
|
|||
error(SocketError);
|
|||
// attempt to initialize new scp session.
|
|||
int scpInitialized = ssh_scp_init(scpSession);
|
|||
// if failed, close scp session and return.
|
|||
if(scpInitialized != SSH_OK)
|
|||
{
|
|||
ssh_scp_close(scpSession);
|
|||
ssh_scp_free(scpSession);
|
|||
error(ScpChannelCreationError);
|
|||
return;
|
|||
}
|
|||
// open the local file and check to make sure it exists
|
|||
// if not, close scp session and return.
|
|||
QFile file(m_currentOperation.localPath);
|
|||
if (!file.exists())
|
|||
{
|
|||
ssh_scp_close(scpSession);
|
|||
ssh_scp_free(scpSession);
|
|||
error(ScpFileNotCreatedError);
|
|||
return;
|
|||
}
|
|||
// if the file does exist, read all contents as bytes
|
|||
file.open(QIODevice::ReadOnly);
|
|||
QByteArray buffer =file.readAll();
|
|||
file.close();
|
|||
// attempt to authorize pushing bytes over scp socket
|
|||
// if this fails, close scp session and return.
|
|||
if (ssh_scp_push_file(scpSession, m_currentOperation.remotePath.toLatin1().data(), buffer.size(), 0000400 | 0000200 ) != SSH_OK)
|
|||
{
|
|||
ssh_scp_close(scpSession);
|
|||
ssh_scp_free(scpSession);
|
|||
error(ScpPushRequestError);
|
|||
return;
|
|||
}
|
|||
// once authorized to push bytes over scp socket, start writing
|
|||
// if an error is returned, close scp session and return.
|
|||
if ( ssh_scp_write(scpSession,buffer.data(), buffer.size()) != SSH_OK)
|
|||
{
|
|||
ssh_scp_close(scpSession);
|
|||
ssh_scp_free(scpSession);
|
|||
error(ScpWriteError);
|
|||
return;
|
|||
}
|
|||
// close scp session and return.
|
|||
ssh_scp_close(scpSession);
|
|||
ssh_scp_free(scpSession);
|
|||
pushSuccessful(m_currentOperation.localPath,m_currentOperation.remotePath);
|
|||
}
|