Commit 7edeedfc authored by Lefebvre, Jordan's avatar Lefebvre, Jordan
Browse files

Working authentication and command submission. Started on interactive authentication.

parent 2d792e1e
......@@ -51,6 +51,11 @@ SessionController::SessionController(QObject* parent)
&SessionController::connectionFailed);
QObject::connect(p->worker, &SessionWorker::connectionSuccessful, this,
&SessionController::connectionSuccessful);
QObject::connect(p->worker, &SessionWorker::disconnectSuccessful, this,
&SessionController::disconnectSuccessful);
QObject::connect(p->worker,
&SessionWorker::interactiveAuthenticationRequested, this,
&SessionController::interactiveAuthenticationRequested);
QObject::connect(p->worker, &SessionWorker::verifyKnownHostSuccessful, this,
&SessionController::verifyKnownHostSuccessful);
QObject::connect(p->worker, &SessionWorker::getServerPublicKeyFailed, this,
......
......@@ -88,7 +88,11 @@ class RSM_PUBLIC SessionController : public QObject
void connectionFailed(QString message);
void connectionSuccessful();
void disconnectSuccessful();
void verifyKnownHostSuccessful();
void interactiveAuthenticationRequested(QString instruction, QString name,
QStringList prompts);
/**
* @brief getServerPublicKeyFailed
* Signal is emitted when the remote host does not have or provide a public
......
......@@ -86,6 +86,9 @@ void SessionWorker::connect()
{
assert_ssh_session(p->session, "connect() -- Session is not allocated.");
if (ssh_is_connected(p->session) == 0)
{
ssh_disconnect(p->session);
}
{
// attempt a connection
int rc = ssh_connect(p->session);
......@@ -111,10 +114,12 @@ void SessionWorker::connect()
void SessionWorker::disconnect()
{
assert_ssh_session(p->session, "disconnect() -- Session is not allocated.");
radix_tagged_line("disconnect()");
if (ssh_is_connected(p->session) != 0)
{
radix_tagged_line("Disconnecting session.");
ssh_disconnect(p->session);
emit disconnectSuccessful();
}
}
......@@ -129,6 +134,7 @@ void SessionWorker::verifyKnownHost()
size_t hlen;
QString qhexa;
radix_tagged_line("verifyKnownHost()");
int rc = ssh_get_server_publickey(p->session, &server_public_key);
if (rc < 0)
{
......@@ -191,6 +197,7 @@ void SessionWorker::acceptHostPublicKeyUpdate()
{
assert_ssh_session(
p->session, "acceptHostPublicKeyUpdate() -- Session is not allocated.");
radix_tagged_line("authenticateHostPublicKeyUpdate()");
int rc = ssh_session_update_known_hosts(p->session);
if (rc != SSH_OK)
{
......@@ -202,6 +209,7 @@ void SessionWorker::authenticate()
{
assert_ssh_session(p->session, "authenticate() -- Session is not allocated.");
radix_tagged_line("Authenticate.");
// Try authenticating with no credentials - rarely works
int rc = ssh_userauth_none(p->session, nullptr);
if (rc == SSH_AUTH_ERROR)
......@@ -232,6 +240,34 @@ void SessionWorker::authenticate()
}
radix_tagged_line("SSH_AUTH_METHOD_PUBLICKEY didn't work.");
} // public key authentication
// Try to authenticate with keyboard interactive";
if (method & SSH_AUTH_METHOD_INTERACTIVE)
{
int err;
err = ssh_userauth_kbdint(p->session, nullptr, nullptr);
while (err == SSH_AUTH_INFO)
{
QString instruction = ssh_userauth_kbdint_getname(p->session);
QString name = ssh_userauth_kbdint_getinstruction(p->session);
int num_prompts = ssh_userauth_kbdint_getnprompts(p->session);
// build list of prompts
QStringList prompts;
char echo;
for (int i = 0; i < num_prompts; ++i)
{
QString prompt = ssh_userauth_kbdint_getprompt(
p->session, static_cast<unsigned int>(i), &echo);
radix_tagged_line(i << ". " << prompt.toStdString());
if (prompt.isEmpty()) break;
prompts << prompt;
}
emit interactiveAuthenticationRequested(instruction, name, prompts);
return;
}
}
// Try to authenticate with password
if (method & SSH_AUTH_METHOD_PASSWORD)
{
......@@ -245,6 +281,7 @@ void SessionWorker::authenticateWithPassword(QString pswd)
{
assert_ssh_session(p->session,
"authenticateWithPassword() -- Session is not allocated.");
radix_tagged_line("Authenticate with password.");
int rc =
ssh_userauth_password(p->session, nullptr, pswd.toStdString().c_str());
if (rc == SSH_AUTH_ERROR)
......@@ -266,6 +303,36 @@ void SessionWorker::authenticateWithPassword(QString pswd)
}
}
void SessionWorker::authenticatePrompts(QStringList responses)
{
int err;
for (int i = 0; i < responses.size(); ++i)
{
const char* answer = responses.at(i).toStdString().c_str();
err = ssh_userauth_kbdint_setanswer(p->session,
static_cast<unsigned int>(i), answer);
if (err < 0)
{
emit authenticationError("Failed to authenticate prompts.");
ssh_disconnect(p->session);
return;
}
}
// check status
err = ssh_userauth_kbdint(p->session, nullptr, nullptr);
if (err == SSH_AUTH_DENIED)
{
emit authenticationError("Authentication denied.");
ssh_disconnect(p->session);
return;
}
else if (err == SSH_AUTH_SUCCESS)
{
emit authenticationSucceeded();
return;
}
}
void SessionWorker::requestExec(QString command)
{
assert_ssh_session(p->session, "request_exec() -- Session is not allocated.");
......@@ -303,9 +370,9 @@ void SessionWorker::requestExec(QString command)
while (nbytes > 0)
{
p->output_buffer.append(buffer, nbytes);
emit execOutputReady();
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
emit execOutputReady();
radix_tagged_line("nbytes=" << nbytes);
radix_tagged_line("Finished reading response\n" << p->output_buffer.data());
......
......@@ -85,6 +85,8 @@ class RSM_PUBLIC SessionWorker : public QObject
*/
void authenticateWithPassword(QString pswd);
void authenticatePrompts(QStringList responses);
/**
* Requests remote execution of command
* @param command - QString command to execute
......@@ -94,7 +96,11 @@ class RSM_PUBLIC SessionWorker : public QObject
signals:
void connectionFailed(QString message);
void connectionSuccessful();
void disconnectSuccessful();
void verifyKnownHostSuccessful();
void interactiveAuthenticationRequested(QString instruction, QString name,
QStringList prompts);
/**
* @brief getServerPublicKeyFailed
* Signal is emitted when the remote host does not have or provide a public
......
......@@ -9,7 +9,9 @@
#include <QApplication>
#include <QGridLayout>
#include <QHeaderView>
#include <QInputDialog>
#include <QLabel>
#include <QMessageBox>
#include "radixbug/bug.hh"
using namespace rsm;
......@@ -45,18 +47,26 @@ ExamplePortalWidget::ExamplePortalWidget(QWidget *parent)
connect(mConnectButton, &QPushButton::pressed, this,
&ExamplePortalWidget::connectToHost);
connect(mCommandSubmitButton, &QPushButton::pressed, this,
&ExamplePortalWidget::submitCommandToHost);
mSession = new SessionController();
connect(mSession, &SessionController::connectionFailed, this,
&ExamplePortalWidget::connectionFailed);
connect(mSession, &SessionController::connectionSuccessful, this,
&ExamplePortalWidget::connectionSuccessful);
connect(mSession, &SessionController::disconnectSuccessful, this,
&ExamplePortalWidget::disconnectSuccessful);
connect(mSession, &SessionController::interactiveAuthenticationRequested,
this, &ExamplePortalWidget::interactiveAuthenticationRequested);
connect(mSession, &SessionController::getServerPublicKeyFailed, this,
&ExamplePortalWidget::getServerPublicKeyFailed);
connect(mSession, &SessionController::hostUnknown, this,
&ExamplePortalWidget::hostUnknown);
connect(mSession, &SessionController::hostPublicKeyChanged, this,
&ExamplePortalWidget::hostPublicKeyChanged);
connect(mSession, &SessionController::verifyKnownHostSuccessful, this,
&ExamplePortalWidget::verifyKnownHostSuccessful);
connect(mSession, &SessionController::knownHostError, this,
&ExamplePortalWidget::knownHostError);
connect(mSession, &SessionController::authenticationError, this,
......@@ -79,13 +89,26 @@ void ExamplePortalWidget::connectToHost()
{
radix_tagged_line("Host:" << mHostEdit->text().toStdString());
mSession->setHost(mHostEdit->text());
mSession->setPort(mPortEdit->text().toInt());
mSession->setUser(mUserNameEdit->text());
mSession->connect();
if (mConnectButton->text().compare("Disconnect") == 0)
{
mSession->disconnect();
mConnectButton->setText("Connect");
}
else
{
mSession->setHost(mHostEdit->text());
mSession->setPort(mPortEdit->text().toInt());
mSession->setUser(mUserNameEdit->text());
mSession->connect();
}
}
void ExamplePortalWidget::disconnectFromHost() { mSession->disconnect(); }
void ExamplePortalWidget::submitCommandToHost()
{
radix_tagged_line("submitCommandToHost()");
QString command = mCommandEdit->text();
mSession->requestExec(command);
}
void ExamplePortalWidget::slotExecOutputReady()
{
......@@ -105,12 +128,31 @@ void ExamplePortalWidget::connectionSuccessful()
mSession->verifyKnownHost();
}
void ExamplePortalWidget::verifyKnownHostSuccesful()
void ExamplePortalWidget::disconnectSuccessful()
{
mTextEdit->append("Disconnected.\n");
}
void ExamplePortalWidget::verifyKnownHostSuccessful()
{
mTextEdit->append("Verification successful.\Authenticating...\n");
mTextEdit->append("Verification successful.\nAuthenticating...\n");
mSession->authenticate();
}
void ExamplePortalWidget::interactiveAuthenticationRequested(
QString instruction, QString name, QStringList prompts)
{
mTextEdit->append("Interactive authentication requested.");
mTextEdit->append("Instruction: ");
mTextEdit->append(instruction);
mTextEdit->append("Name:");
mTextEdit->append(name);
for (int i = 0; i < prompts.size(); ++i)
{
mTextEdit->append(prompts.at(i));
}
}
void ExamplePortalWidget::getServerPublicKeyFailed()
{
mTextEdit->append("Retrieval of host's public key failed.\n");
......@@ -119,9 +161,21 @@ void ExamplePortalWidget::getServerPublicKeyFailed()
void ExamplePortalWidget::hostUnknown(QString host_hash)
{
mTextEdit->append("Host key unknown.\nDo you accept:");
mTextEdit->append(host_hash);
mTextEdit->append("\n");
int ret = QMessageBox::warning(
this, tr("Host Unknown"),
QString("The remote host is unknown.\n")
.append("Are you sure you want to continue connecting?\n")
.append("Remote host key:")
.append(host_hash),
QMessageBox::Yes | QMessageBox::Cancel);
if (ret == QMessageBox::Yes)
{
mSession->acceptHostPublicKeyUpdate();
}
else
{
mSession->disconnect();
}
}
void ExamplePortalWidget::hostPublicKeyChanged(QString host_hash)
......@@ -159,17 +213,33 @@ void ExamplePortalWidget::authenticationSucceeded()
{
mTextEdit->append("Authentication succeeded.");
mTextEdit->append("\n");
mConnectButton->setText("Disconnect");
}
void ExamplePortalWidget::passwordRequested()
{
mTextEdit->append("Password requested.");
mTextEdit->append("\n");
// TODO: Prompt password dialog
QString text = QInputDialog::getText(this, "Authentication",
"Password:", QLineEdit::Password);
if (text.isEmpty())
{
mSession->disconnect();
}
else
{
mSession->authenticateWithPassword(text);
}
}
void ExamplePortalWidget::loginBannerIssued(QString message)
{
int ret = QMessageBox::warning(this, tr("Host Login Banner"), message,
QMessageBox::Ok | QMessageBox::Cancel);
if (ret != QMessageBox::Ok)
{
mSession->disconnect();
}
mTextEdit->append(message);
mTextEdit->append("\n");
}
......
......@@ -33,12 +33,16 @@ class ExamplePortalWidget : public QWidget
public slots:
void connectToHost();
void disconnectFromHost();
void submitCommandToHost();
void slotExecOutputReady();
void connectionFailed(QString message);
void connectionSuccessful();
void verifyKnownHostSuccesful();
void disconnectSuccessful();
void verifyKnownHostSuccessful();
void interactiveAuthenticationRequested(QString instruction, QString name,
QStringList prompts);
void getServerPublicKeyFailed();
void hostUnknown(QString host_hash);
void hostPublicKeyChanged(QString host_hash);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment