Skip to content

Commit

Permalink
SASL: add webadmin interface (closes #910)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpnurmi committed Apr 4, 2015
1 parent ce156b5 commit 72223fe
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 10 deletions.
64 changes: 64 additions & 0 deletions modules/data/sasl/tmpl/index.tmpl
@@ -0,0 +1,64 @@
<? INC Header.tmpl ?>

<form action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>" method="post">
<? INC _csrf_check.tmpl ?>
<div class="section">
<h3>SASL</h3>
<div class="sectionbg">
<div class="sectionbody">
<div class="subsection">
<div class="inputlabel">Username:</div>
<input type="text" name="username" value="<? VAR Username ?>" class="half" maxlength="128"
title="Please enter a username." />
</div>
<div class="subsection">
<div class="inputlabel">Password:</div>
<input type="password" name="password" class="half"
title="Please enter a password." autocomplete="off" />
</div>
</div>
</div>
<h3>Options</h3>
<div class="sectionbg">
<div class="sectionbody lotsofcheckboxes">
<span class="checkboxandlabel" title="Connect only if SASL authentication succeeds.">
<input type="checkbox" name="require_auth" id="opt_require_auth" value="1"<? IF RequireAuth ?> checked="checked"<? ENDIF ?> />
<label for="opt_require_auth">Require authentication</label>
</span>
<div style="clear:both;"></div>
</div>
</div>
</div>

<div class="section">
<h3>Mechanisms</h3>
<div class="sectionbg">
<table class="data">
<thead>
<tr>
<td>Name</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<? LOOP MechanismLoop SORTASC=Name ?>
<tr class="<? IF __EVEN__ ?>evenrow<? ELSE ?>oddrow<? ENDIF ?>">
<td>
<input type="checkbox" name="<? VAR Name ?>" id="opt_<? VAR Name ?>" value="1"<? IF Checked ?> checked="checked"<? ENDIF ?> />
<label for="opt_<? VAR Name ?>"><? VAR Name ?></label>
</td>
<td><? VAR Description ?></td>
</tr>
<? ENDLOOP ?>
</tbody>
</table>
</div>
</div>

<div class="submitline">
<input type="hidden" name="submitted" value="1" />
<input type="submit" value="Save" />
</div>
</form>

<? INC Footer.tmpl ?>
65 changes: 55 additions & 10 deletions modules/sasl.cpp
Expand Up @@ -16,15 +16,15 @@

#include <znc/IRCNetwork.h>
#include <znc/IRCSock.h>
#include <algorithm>

static const struct {
const char *szName;
const char *szDescription;
const bool bDefault;
} SupportedMechanisms[] = {
{ "EXTERNAL", "TLS certificate, for use with the *cert module", false },
{ "PLAIN", "Plain text negotiation, this should work always if the network supports SASL", true },
{ nullptr, nullptr, false }
{ "PLAIN", "Plain text negotiation, this should work always if the network supports SASL", true }
};

#define NV_REQUIRE_AUTH "require_auth"
Expand Down Expand Up @@ -86,10 +86,10 @@ class CSASLMod : public CModule {
Mechanisms.AddColumn("Mechanism");
Mechanisms.AddColumn("Description");

for (size_t i = 0; SupportedMechanisms[i].szName != nullptr; i++) {
for (const auto& it : SupportedMechanisms) {
Mechanisms.AddRow();
Mechanisms.SetCell("Mechanism", SupportedMechanisms[i].szName);
Mechanisms.SetCell("Description", SupportedMechanisms[i].szDescription);
Mechanisms.SetCell("Mechanism", it.szName);
Mechanisms.SetCell("Description", it.szDescription);
}

PutModule("The following mechanisms are available:");
Expand Down Expand Up @@ -137,8 +137,8 @@ class CSASLMod : public CModule {
}

bool SupportsMechanism(const CString& sMechanism) const {
for (size_t i = 0; SupportedMechanisms[i].szName != nullptr; i++) {
if (sMechanism.Equals(SupportedMechanisms[i].szName)) {
for (const auto& it : SupportedMechanisms) {
if (sMechanism.Equals(it.szName)) {
return true;
}
}
Expand All @@ -150,13 +150,13 @@ class CSASLMod : public CModule {
if (GetNV(NV_MECHANISMS).empty()) {
CString sDefaults = "";

for (size_t i = 0; SupportedMechanisms[i].szName != nullptr; i++) {
if (SupportedMechanisms[i].bDefault) {
for (const auto& it : SupportedMechanisms) {
if (it.bDefault) {
if (!sDefaults.empty()) {
sDefaults += " ";
}

sDefaults += SupportedMechanisms[i].szName;
sDefaults += it.szName;
}
}

Expand Down Expand Up @@ -256,6 +256,51 @@ class CSASLMod : public CModule {
void OnIRCDisconnected() override {
m_bAuthenticated = false;
}

CString GetWebMenuTitle() override { return "SASL"; }

bool OnWebRequest(CWebSock& WebSock, const CString& sPageName, CTemplate& Tmpl) override {
if (sPageName != "index") {
// only accept requests to index
return false;
}

if (WebSock.IsPost()) {
SetNV("username", WebSock.GetRawParam("username"));
CString sPassword = WebSock.GetRawParam("password");
if (!sPassword.empty()) {
SetNV("password", sPassword);
}
SetNV(NV_REQUIRE_AUTH, WebSock.GetRawParam(NV_REQUIRE_AUTH));

VCString vsMechanisms;
for (const auto& it : SupportedMechanisms) {
bool bChecked = WebSock.GetRawParam(it.szName).ToBool();
if (bChecked) {
vsMechanisms.push_back(it.szName);
}
}
SetNV(NV_MECHANISMS, CString(" ").Join(vsMechanisms.begin(), vsMechanisms.end()));
}

Tmpl["Username"] = GetNV("username");
Tmpl["Password"] = GetNV("password");
Tmpl["RequireAuth"] = GetNV(NV_REQUIRE_AUTH);

VCString vsMechanisms;
GetMechanismsString().Split(" ", vsMechanisms);

for (const auto& it : SupportedMechanisms) {
CTemplate& Row = Tmpl.AddRow("MechanismLoop");
CString sName(it.szName);
Row["Name"] = sName;
Row["Description"] = CString(it.szDescription);
Row["Checked"] = CString(std::find(vsMechanisms.begin(), vsMechanisms.end(), sName) != vsMechanisms.end());
}

return true;
}

private:
Mechanisms m_Mechanisms;
bool m_bAuthenticated;
Expand Down

0 comments on commit 72223fe

Please sign in to comment.