Commit 7edeedfc authored by LEFEBVREJP email's avatar LEFEBVREJP email
Browse files

Working authentication and command submission. Started on interactive authentication.

parent 2d792e1e
...@@ -51,6 +51,11 @@ SessionController::SessionController(QObject* parent) ...@@ -51,6 +51,11 @@ SessionController::SessionController(QObject* parent)
&SessionController::connectionFailed); &SessionController::connectionFailed);
QObject::connect(p->worker, &SessionWorker::connectionSuccessful, this, QObject::connect(p->worker, &SessionWorker::connectionSuccessful, this,
&SessionController::connectionSuccessful); &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, QObject::connect(p->worker, &SessionWorker::verifyKnownHostSuccessful, this,
&SessionController::verifyKnownHostSuccessful); &SessionController::verifyKnownHostSuccessful);
QObject::connect(p->worker, &SessionWorker::getServerPublicKeyFailed, this, QObject::connect(p->worker, &SessionWorker::getServerPublicKeyFailed, this,
......
...@@ -88,7 +88,11 @@ class RSM_PUBLIC SessionController : public QObject ...@@ -88,7 +88,11 @@ class RSM_PUBLIC SessionController : public QObject
void connectionFailed(QString message); void connectionFailed(QString message);
void connectionSuccessful(); void connectionSuccessful();
void disconnectSuccessful();
void verifyKnownHostSuccessful(); void verifyKnownHostSuccessful();
void interactiveAuthenticationRequested(QString instruction, QString name,
QStringList prompts);
/** /**
* @brief getServerPublicKeyFailed * @brief getServerPublicKeyFailed
* Signal is emitted when the remote host does not have or provide a public * Signal is emitted when the remote host does not have or provide a public
......
...@@ -86,6 +86,9 @@ void SessionWorker::connect() ...@@ -86,6 +86,9 @@ void SessionWorker::connect()
{ {
assert_ssh_session(p->session, "connect() -- Session is not allocated."); assert_ssh_session(p->session, "connect() -- Session is not allocated.");
if (ssh_is_connected(p->session) == 0) if (ssh_is_connected(p->session) == 0)
{
ssh_disconnect(p->session);
}
{ {
// attempt a connection // attempt a connection
int rc = ssh_connect(p->session); int rc = ssh_connect(p->session);
...@@ -111,10 +114,12 @@ void SessionWorker::connect() ...@@ -111,10 +114,12 @@ void SessionWorker::connect()
void SessionWorker::disconnect() void SessionWorker::disconnect()
{ {
assert_ssh_session(p->session, "disconnect() -- Session is not allocated."); assert_ssh_session(p->session, "disconnect() -- Session is not allocated.");
radix_tagged_line("disconnect()");
if (ssh_is_connected(p->session) != 0) if (ssh_is_connected(p->session) != 0)
{ {
radix_tagged_line("Disconnecting session."); radix_tagged_line("Disconnecting session.");
ssh_disconnect(p->session); ssh_disconnect(p->session);
emit disconnectSuccessful();
} }
} }
...@@ -129,6 +134,7 @@ void SessionWorker::verifyKnownHost() ...@@ -129,6 +134,7 @@ void SessionWorker::verifyKnownHost()
size_t hlen; size_t hlen;
QString qhexa; QString qhexa;
radix_tagged_line("verifyKnownHost()");
int rc = ssh_get_server_publickey(p->session, &server_public_key); int rc = ssh_get_server_publickey(p->session, &server_public_key);
if (rc < 0) if (rc < 0)
{ {
...@@ -191,6 +197,7 @@ void SessionWorker::acceptHostPublicKeyUpdate() ...@@ -191,6 +197,7 @@ void SessionWorker::acceptHostPublicKeyUpdate()
{ {
assert_ssh_session( assert_ssh_session(
p->session, "acceptHostPublicKeyUpdate() -- Session is not allocated."); p->session, "acceptHostPublicKeyUpdate() -- Session is not allocated.");
radix_tagged_line("authenticateHostPublicKeyUpdate()");
int rc = ssh_session_update_known_hosts(p->session); int rc = ssh_session_update_known_hosts(p->session);
if (rc != SSH_OK) if (rc != SSH_OK)
{ {
...@@ -202,6 +209,7 @@ void SessionWorker::authenticate() ...@@ -202,6 +209,7 @@ void SessionWorker::authenticate()
{ {
assert_ssh_session(p->session, "authenticate() -- Session is not allocated."); assert_ssh_session(p->session, "authenticate() -- Session is not allocated.");
radix_tagged_line("Authenticate.");
// Try authenticating with no credentials - rarely works // Try authenticating with no credentials - rarely works
int rc = ssh_userauth_none(p->session, nullptr); int rc = ssh_userauth_none(p->session, nullptr);
if (rc == SSH_AUTH_ERROR) if (rc == SSH_AUTH_ERROR)
...@@ -232,6 +240,34 @@ void SessionWorker::authenticate() ...@@ -232,6 +240,34 @@ void SessionWorker::authenticate()
} }
radix_tagged_line("SSH_AUTH_METHOD_PUBLICKEY didn't work."); radix_tagged_line("SSH_AUTH_METHOD_PUBLICKEY didn't work.");
} // public key authentication } // 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 // Try to authenticate with password
if (method & SSH_AUTH_METHOD_PASSWORD) if (method & SSH_AUTH_METHOD_PASSWORD)
{ {
...@@ -245,6 +281,7 @@ void SessionWorker::authenticateWithPassword(QString pswd) ...@@ -245,6 +281,7 @@ void SessionWorker::authenticateWithPassword(QString pswd)
{ {
assert_ssh_session(p->session, assert_ssh_session(p->session,
"authenticateWithPassword() -- Session is not allocated."); "authenticateWithPassword() -- Session is not allocated.");
radix_tagged_line("Authenticate with password.");
int rc = int rc =
ssh_userauth_password(p->session, nullptr, pswd.toStdString().c_str()); ssh_userauth_password(p->session, nullptr, pswd.toStdString().c_str());
if (rc == SSH_AUTH_ERROR) if (rc == SSH_AUTH_ERROR)
...@@ -266,6 +303,36 @@ void SessionWorker::authenticateWithPassword(QString pswd) ...@@ -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) void SessionWorker::requestExec(QString command)
{ {
assert_ssh_session(p->session, "request_exec() -- Session is not allocated."); assert_ssh_session(p->session, "request_exec() -- Session is not allocated.");
...@@ -303,9 +370,9 @@ void SessionWorker::requestExec(QString command) ...@@ -303,9 +370,9 @@ void SessionWorker::requestExec(QString command)
while (nbytes > 0) while (nbytes > 0)
{ {
p->output_buffer.append(buffer, nbytes); p->output_buffer.append(buffer, nbytes);
emit execOutputReady();
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
} }
emit execOutputReady();
radix_tagged_line("nbytes=" << nbytes); radix_tagged_line("nbytes=" << nbytes);
radix_tagged_line("Finished reading response\n" << p->output_buffer.data()); radix_tagged_line("Finished reading response\n" << p->output_buffer.data());
......
...@@ -85,6 +85,8 @@ class RSM_PUBLIC SessionWorker : public QObject ...@@ -85,6 +85,8 @@ class RSM_PUBLIC SessionWorker : public QObject
*/ */
void authenticateWithPassword(QString pswd); void authenticateWithPassword(QString pswd);
void authenticatePrompts(QStringList responses);
/** /**
* Requests remote execution of command * Requests remote execution of command
* @param command - QString command to execute * @param command - QString command to execute
...@@ -94,7 +96,11 @@ class RSM_PUBLIC SessionWorker : public QObject ...@@ -94,7 +96,11 @@ class RSM_PUBLIC SessionWorker : public QObject
signals: signals:
void connectionFailed(QString message); void connectionFailed(QString message);
void connectionSuccessful(); void connectionSuccessful();
void disconnectSuccessful();
void verifyKnownHostSuccessful(); void verifyKnownHostSuccessful();
void interactiveAuthenticationRequested(QString instruction, QString name,
QStringList prompts);
/** /**
* @brief getServerPublicKeyFailed * @brief getServerPublicKeyFailed
* Signal is emitted when the remote host does not have or provide a public * Signal is emitted when the remote host does not have or provide a public
......
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
#include <QApplication> #include <QApplication>
#include <QGridLayout> #include <QGridLayout>
#include <QHeaderView> #include <QHeaderView>
#include <QInputDialog>
#include <QLabel> #include <QLabel>
#include <QMessageBox>
#include "radixbug/bug.hh" #include "radixbug/bug.hh"
using namespace rsm; using namespace rsm;
...@@ -45,18 +47,26 @@ ExamplePortalWidget::ExamplePortalWidget(QWidget *parent) ...@@ -45,18 +47,26 @@ ExamplePortalWidget::ExamplePortalWidget(QWidget *parent)
connect(mConnectButton, &QPushButton::pressed, this, connect(mConnectButton, &QPushButton::pressed, this,
&ExamplePortalWidget::connectToHost); &ExamplePortalWidget::connectToHost);
connect(mCommandSubmitButton, &QPushButton::pressed, this,
&ExamplePortalWidget::submitCommandToHost);
mSession = new SessionController(); mSession = new SessionController();
connect(mSession, &SessionController::connectionFailed, this, connect(mSession, &SessionController::connectionFailed, this,
&ExamplePortalWidget::connectionFailed); &ExamplePortalWidget::connectionFailed);
connect(mSession, &SessionController::connectionSuccessful, this, connect(mSession, &SessionController::connectionSuccessful, this,
&ExamplePortalWidget::connectionSuccessful); &ExamplePortalWidget::connectionSuccessful);
connect(mSession, &SessionController::disconnectSuccessful, this,
&ExamplePortalWidget::disconnectSuccessful);
connect(mSession, &SessionController::interactiveAuthenticationRequested,
this, &ExamplePortalWidget::interactiveAuthenticationRequested);
connect(mSession, &SessionController::getServerPublicKeyFailed, this, connect(mSession, &SessionController::getServerPublicKeyFailed, this,
&ExamplePortalWidget::getServerPublicKeyFailed); &ExamplePortalWidget::getServerPublicKeyFailed);
connect(mSession, &SessionController::hostUnknown, this, connect(mSession, &SessionController::hostUnknown, this,
&ExamplePortalWidget::hostUnknown); &ExamplePortalWidget::hostUnknown);
connect(mSession, &SessionController::hostPublicKeyChanged, this, connect(mSession, &SessionController::hostPublicKeyChanged, this,
&ExamplePortalWidget::hostPublicKeyChanged); &ExamplePortalWidget::hostPublicKeyChanged);
connect(mSession, &SessionController::verifyKnownHostSuccessful, this,
&ExamplePortalWidget::verifyKnownHostSuccessful);
connect(mSession, &SessionController::knownHostError, this, connect(mSession, &SessionController::knownHostError, this,
&ExamplePortalWidget::knownHostError); &ExamplePortalWidget::knownHostError);
connect(mSession, &SessionController::authenticationError, this, connect(mSession, &SessionController::authenticationError, this,
...@@ -79,13 +89,26 @@ void ExamplePortalWidget::connectToHost() ...@@ -79,13 +89,26 @@ void ExamplePortalWidget::connectToHost()
{ {
radix_tagged_line("Host:" << mHostEdit->text().toStdString()); radix_tagged_line("Host:" << mHostEdit->text().toStdString());
mSession->setHost(mHostEdit->text()); if (mConnectButton->text().compare("Disconnect") == 0)
mSession->setPort(mPortEdit->text().toInt()); {
mSession->setUser(mUserNameEdit->text()); mSession->disconnect();
mSession->connect(); 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() void ExamplePortalWidget::slotExecOutputReady()
{ {
...@@ -105,12 +128,31 @@ void ExamplePortalWidget::connectionSuccessful() ...@@ -105,12 +128,31 @@ void ExamplePortalWidget::connectionSuccessful()
mSession->verifyKnownHost(); 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(); 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() void ExamplePortalWidget::getServerPublicKeyFailed()
{ {
mTextEdit->append("Retrieval of host's public key failed.\n"); mTextEdit->append("Retrieval of host's public key failed.\n");
...@@ -119,9 +161,21 @@ void ExamplePortalWidget::getServerPublicKeyFailed() ...@@ -119,9 +161,21 @@ void ExamplePortalWidget::getServerPublicKeyFailed()
void ExamplePortalWidget::hostUnknown(QString host_hash) void ExamplePortalWidget::hostUnknown(QString host_hash)
{ {
mTextEdit->append("Host key unknown.\nDo you accept:"); int ret = QMessageBox::warning(
mTextEdit->append(host_hash); this, tr("Host Unknown"),
mTextEdit->append("\n"); 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) void ExamplePortalWidget::hostPublicKeyChanged(QString host_hash)
...@@ -159,17 +213,33 @@ void ExamplePortalWidget::authenticationSucceeded() ...@@ -159,17 +213,33 @@ void ExamplePortalWidget::authenticationSucceeded()
{ {
mTextEdit->append("Authentication succeeded."); mTextEdit->append("Authentication succeeded.");
mTextEdit->append("\n"); mTextEdit->append("\n");
mConnectButton->setText("Disconnect");
} }
void ExamplePortalWidget::passwordRequested() void ExamplePortalWidget::passwordRequested()
{ {
mTextEdit->append("Password requested."); mTextEdit->append("Password requested.");
mTextEdit->append("\n"); 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) 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(message);
mTextEdit->append("\n"); mTextEdit->append("\n");
} }
......
...@@ -33,12 +33,16 @@ class ExamplePortalWidget : public QWidget ...@@ -33,12 +33,16 @@ class ExamplePortalWidget : public QWidget
public slots: public slots:
void connectToHost(); void connectToHost();
void disconnectFromHost(); void submitCommandToHost();
void slotExecOutputReady(); void slotExecOutputReady();
void connectionFailed(QString message); void connectionFailed(QString message);
void connectionSuccessful(); void connectionSuccessful();
void verifyKnownHostSuccesful(); void disconnectSuccessful();
void verifyKnownHostSuccessful();
void interactiveAuthenticationRequested(QString instruction, QString name,
QStringList prompts);
void getServerPublicKeyFailed(); void getServerPublicKeyFailed();
void hostUnknown(QString host_hash); void hostUnknown(QString host_hash);
void hostPublicKeyChanged(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