Skip to content

Commit

Permalink
Server|libshell|Shell: Password challenge when connecting
Browse files Browse the repository at this point in the history
The password set with "server-password" is now required when opening
a shell connection. The password is sent hashed (with SHA-1) over the
network.
  • Loading branch information
skyjake committed Feb 11, 2013
1 parent 56b1483 commit a90cebe
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 5 deletions.
27 changes: 25 additions & 2 deletions doomsday/client/src/network/sys_network.cpp
Expand Up @@ -55,6 +55,7 @@
#include <de/Socket>
#include <de/LegacyCore>
#include <de/LegacyNetwork>
#include <QCryptographicHash>

#define MAX_NODES 32

Expand Down Expand Up @@ -538,11 +539,33 @@ static boolean serverHandleNodeRequest(nodeid_t node, const char *command, int l

DEBUG_VERBOSE_Message(("serverHandleNodeRequest: Sending: %s\n", Str_Text(&msg)));

LegacyNetwork_Send(sock, Str_Text(&msg), (int) Str_Length(&msg));
LegacyNetwork_Send(sock, Str_Text(&msg), Str_Length(&msg));
Str_Free(&msg);
}
else if(length == 5 && !strncmp(command, "Shell", 5))
else if(length >= 5 && !strncmp(command, "Shell", 5))
{
if(length == 5)
{
if(strlen(netPassword) > 0)
{
// Need to ask for a password, too.
LegacyNetwork_Send(sock, "Password?", 9);
return true;
}
}
else if(length > 5)
{
// A password was included.
QByteArray supplied(command + 5, length - 5);
QByteArray pwd(netPassword, strlen(netPassword));
if(supplied != QCryptographicHash::hash(pwd, QCryptographicHash::Sha1))
{
// Wrong!
N_TerminateNode(node);
return false;
}
}

// This node will switch to shell mode: ownership of the socket is
// passed to a ShellUser.
switchNodeToShellMode(node);
Expand Down
11 changes: 11 additions & 0 deletions doomsday/libshell/include/de/shell/protocol.h
Expand Up @@ -29,6 +29,16 @@
namespace de {
namespace shell {

/**
* Password challenge.
*/
class LIBSHELL_PUBLIC ChallengePacket : public Packet
{
public:
ChallengePacket();
static Packet *fromBlock(Block const &block);
};

/**
* Packet with one or more log entries.
*/
Expand Down Expand Up @@ -131,6 +141,7 @@ class LIBSHELL_PUBLIC Protocol : public de::Protocol
enum PacketType
{
Unknown,
PasswordChallenge,
Command, ///< Console command (only to server).
LogEntries, ///< Log entries.
ConsoleLexicon, ///< Known words for command line completion.
Expand Down
23 changes: 23 additions & 0 deletions doomsday/libshell/src/protocol.cpp
Expand Up @@ -31,6 +31,22 @@ static String const PT_COMMAND = "shell.command";
static String const PT_LEXICON = "shell.lexicon";
static String const PT_GAME_STATE = "shell.game.state";

// ChallengePacket -----------------------------------------------------------

static char const *CHALLENGE_PACKET_TYPE = "Psw?";

ChallengePacket::ChallengePacket() : Packet(CHALLENGE_PACKET_TYPE)
{}

Packet *ChallengePacket::fromBlock(Block const &block)
{
if(block == "Password?")
{
return new ChallengePacket;
}
return 0;
}

// LogEntryPacket ------------------------------------------------------------

static char const *LOG_ENTRY_PACKET_TYPE = "LgEn";
Expand Down Expand Up @@ -173,12 +189,19 @@ Packet *MapOutlinePacket::fromBlock(Block const &block)

Protocol::Protocol()
{
define(ChallengePacket::fromBlock);
define(LogEntryPacket::fromBlock);
define(MapOutlinePacket::fromBlock);
}

Protocol::PacketType Protocol::recognize(Packet const *packet)
{
if(packet->type() == CHALLENGE_PACKET_TYPE)
{
DENG2_ASSERT(dynamic_cast<ChallengePacket const *>(packet) != 0);
return PasswordChallenge;
}

if(packet->type() == LOG_ENTRY_PACKET_TYPE)
{
DENG2_ASSERT(dynamic_cast<LogEntryPacket const *>(packet) != 0);
Expand Down
2 changes: 1 addition & 1 deletion doomsday/tools/shell/shell-gui/src/guishellapp.cpp
Expand Up @@ -80,7 +80,7 @@ GuiShellApp::GuiShellApp(int &argc, char **argv)

QMenu *svMenu = d->menuBar->addMenu(tr("Local Server"));
svMenu->addAction(tr("Start..."), this, SLOT(startLocalServer()),
QKeySequence(tr("Ctrl+N", "Local Server|Start")));
QKeySequence(tr("Ctrl+N", "Local Server|Start")));
d->stopAction = svMenu->addAction(tr("Stop"), this, SLOT(stopServer()));
svMenu->addSeparator();
svMenu->addMenu(d->localMenu);
Expand Down
32 changes: 32 additions & 0 deletions doomsday/tools/shell/shell-gui/src/linkwindow.cpp
Expand Up @@ -27,6 +27,7 @@
#include <de/shell/Link>
#include <QToolBar>
#include <QMenuBar>
#include <QInputDialog>
#include <QTimer>
#include <QCloseEvent>
#include <QMessageBox>
Expand All @@ -35,6 +36,7 @@
#include <QStackedWidget>
#include <QStatusBar>
#include <QLabel>
#include <QCryptographicHash>

using namespace de;
using namespace de::shell;
Expand Down Expand Up @@ -357,10 +359,16 @@ void LinkWindow::handleIncomingPackets()
QScopedPointer<Packet> packet(d->link->nextPacket());
if(packet.isNull()) break;

//qDebug() << "Packet:" << packet->type();

// Process packet contents.
shell::Protocol &protocol = d->link->protocol();
switch(protocol.recognize(packet.data()))
{
case shell::Protocol::PasswordChallenge:
askForPassword();
break;

case shell::Protocol::LogEntries: {
// Add the entries into the local log buffer.
LogEntryPacket *pkt = static_cast<LogEntryPacket *>(packet.data());
Expand Down Expand Up @@ -440,3 +448,27 @@ void LinkWindow::disconnected()

emit linkClosed(this);
}

void LinkWindow::askForPassword()
{
QInputDialog dlg(this);
dlg.setWindowModality(Qt::WindowModal);
dlg.setInputMode(QInputDialog::TextInput);
dlg.setTextEchoMode(QLineEdit::Password);
dlg.setLabelText(tr("Server password:"));

if(dlg.exec() == QDialog::Accepted)
{
if(d->link)
{
Block response;
response.append("Shell");
response += QCryptographicHash::hash(dlg.textValue().toUtf8(),
QCryptographicHash::Sha1);
*d->link << response;
}
return;
}

QTimer::singleShot(1, this, SLOT(closeConnection()));
}
1 change: 1 addition & 0 deletions doomsday/tools/shell/shell-gui/src/linkwindow.h
Expand Up @@ -56,6 +56,7 @@ protected slots:
void addressResolved();
void connected();
void disconnected();
void askForPassword();

private:
struct Instance;
Expand Down
2 changes: 0 additions & 2 deletions doomsday/tools/shell/shell-gui/src/statuswidget.cpp
Expand Up @@ -104,8 +104,6 @@ void StatusWidget::setMapOutline(shell::MapOutlinePacket const &outline)

d->mapBounds = d->mapBounds.united(QRect(b, QSize(1, 1)));
}

qDebug() << d->mapBounds;
}

void StatusWidget::paintEvent(QPaintEvent *)
Expand Down

0 comments on commit a90cebe

Please sign in to comment.