Commit 00a43489 authored by Lefebvre, Jordan's avatar Lefebvre, Jordan
Browse files

Implementing interactive keyboard authentication with multiple prompts.

parent 7edeedfc
......@@ -107,6 +107,8 @@ SessionController::SessionController(QObject* parent)
&SessionWorker::authenticate);
QObject::connect(this, &SessionController::authenticateWithPasswordRequested,
p->worker, &SessionWorker::authenticateWithPassword);
QObject::connect(this, &SessionController::authenticatePromptsRequested,
p->worker, &SessionWorker::authenticatePrompts);
QObject::connect(this, &SessionController::requestExecRequested, p->worker,
&SessionWorker::requestExec);
}
......@@ -153,6 +155,11 @@ void SessionController::authenticateWithPassword(QString pswd)
emit authenticateWithPasswordRequested(pswd);
}
void SessionController::authenticatePrompts(QStringList responses)
{
emit authenticatePromptsRequested(responses);
}
void SessionController::requestExec(QString command)
{
emit requestExecRequested(command);
......
......@@ -78,6 +78,8 @@ class RSM_PUBLIC SessionController : public QObject
*/
void authenticateWithPassword(QString pswd);
void authenticatePrompts(QStringList responses);
/**
* Requests remote execution of command
* @param command - QString command to execute
......@@ -229,6 +231,8 @@ class RSM_PUBLIC SessionController : public QObject
*/
void authenticateWithPasswordRequested(QString pswd);
void authenticatePromptsRequested(QStringList responses);
/**
* Requests remote execution of command
* @param command - QString command to execute
......
......@@ -40,6 +40,25 @@ class SessionWorkerImpl
}
};
void SessionWorker::processPrompts()
{
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);
}
SessionWorker::SessionWorker(QObject* parent)
: QObject(parent)
{
......@@ -85,11 +104,14 @@ void SessionWorker::setUser(QString name)
void SessionWorker::connect()
{
assert_ssh_session(p->session, "connect() -- Session is not allocated.");
if (ssh_is_connected(p->session) == 0)
radix_tagged_line("connect()");
if (ssh_is_connected(p->session) == 1)
{
radix_tagged_line("session already connected. disconnectinng.");
ssh_disconnect(p->session);
}
{
radix_tagged_line("Attempting connection.");
// attempt a connection
int rc = ssh_connect(p->session);
if (rc != SSH_OK)
......@@ -98,7 +120,7 @@ void SessionWorker::connect()
int rv = ssh_options_get(p->session, SSH_OPTIONS_HOST, &message);
std::ostringstream os;
if (rv == SSH_OK)
if (rv == SSH_OK) // if the error message retrieval was good
{
os << "Error connecting to " << message << ":";
delete message;
......@@ -249,21 +271,7 @@ void SessionWorker::authenticate()
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);
processPrompts();
return;
}
}
......@@ -306,8 +314,10 @@ void SessionWorker::authenticateWithPassword(QString pswd)
void SessionWorker::authenticatePrompts(QStringList responses)
{
int err;
radix_tagged_line("authenticatePrompts()");
for (int i = 0; i < responses.size(); ++i)
{
radix_tagged_line("Setting response " << i);
const char* answer = responses.at(i).toStdString().c_str();
err = ssh_userauth_kbdint_setanswer(p->session,
static_cast<unsigned int>(i), answer);
......@@ -326,7 +336,12 @@ void SessionWorker::authenticatePrompts(QStringList responses)
ssh_disconnect(p->session);
return;
}
else if (err == SSH_AUTH_SUCCESS)
if (err == SSH_AUTH_INFO)
{
processPrompts();
return;
}
if (err == SSH_AUTH_SUCCESS)
{
emit authenticationSucceeded();
return;
......
......@@ -17,6 +17,8 @@ class RSM_PUBLIC SessionWorker : public QObject
// Private implementation
SessionWorkerImpl* p;
void processPrompts();
public:
/**
* Basic Constructor
......
......@@ -151,6 +151,28 @@ void ExamplePortalWidget::interactiveAuthenticationRequested(
{
mTextEdit->append(prompts.at(i));
}
if (!prompts.isEmpty())
{
QString text = QInputDialog::getText(this, "Authentication", prompts.at(0),
QLineEdit::Password);
if (text.isEmpty())
{
mSession->disconnect();
}
else
{
QStringList responses;
responses << text;
mSession->authenticatePrompts(responses);
}
}
else
{
radix_tagged_line("Reponsing with empty handshake.");
QStringList empty;
mSession->authenticatePrompts(empty);
}
}
void ExamplePortalWidget::getServerPublicKeyFailed()
......
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