Add ip subnet whitelist for bypassing webui auth

This commit is contained in:
Thomas Piccirello
2017-09-27 13:55:20 -04:00
parent 04cec39277
commit 95bf63330e
15 changed files with 504 additions and 20 deletions

View File

@@ -43,6 +43,7 @@
#include "base/logger.h"
#include "base/preferences.h"
#include "base/utils/fs.h"
#include "base/utils/net.h"
#include "base/utils/random.h"
#include "base/utils/string.h"
#include "websessiondata.h"
@@ -319,10 +320,13 @@ void AbstractWebApplication::increaseFailedAttempts()
bool AbstractWebApplication::isAuthNeeded()
{
return (env_.clientAddress != QHostAddress::LocalHost
&& env_.clientAddress != QHostAddress::LocalHostIPv6
&& env_.clientAddress != QHostAddress("::ffff:127.0.0.1"))
|| Preferences::instance()->isWebUiLocalAuthEnabled();
qDebug("Checking auth rules against client address %s", qPrintable(env().clientAddress.toString()));
const Preferences *pref = Preferences::instance();
if (!pref->isWebUiLocalAuthEnabled() && Utils::Net::isLoopbackAddress(env().clientAddress))
return false;
if (pref->isWebUiAuthSubnetWhitelistEnabled() && Utils::Net::isIPInRange(env().clientAddress, pref->getWebUiAuthSubnetWhitelist()))
return false;
return true;
}
void AbstractWebApplication::printFile(const QString& path)

View File

@@ -37,6 +37,7 @@
#endif
#include <QStringList>
#include <QTranslator>
#include <QRegularExpression>
#include "base/bittorrent/session.h"
#include "base/net/portforwarder.h"
@@ -44,6 +45,7 @@
#include "base/preferences.h"
#include "base/scanfoldersmodel.h"
#include "base/utils/fs.h"
#include "base/utils/net.h"
#include "jsonutils.h"
prefjson::prefjson()
@@ -173,6 +175,11 @@ QByteArray prefjson::getPreferences()
data["web_ui_username"] = pref->getWebUiUsername();
data["web_ui_password"] = pref->getWebUiPassword();
data["bypass_local_auth"] = !pref->isWebUiLocalAuthEnabled();
data["bypass_auth_subnet_whitelist_enabled"] = pref->isWebUiAuthSubnetWhitelistEnabled();
QStringList authSubnetWhitelistStringList;
for (const Utils::Net::Subnet &subnet : pref->getWebUiAuthSubnetWhitelist())
authSubnetWhitelistStringList << Utils::Net::subnetToString(subnet);
data["bypass_auth_subnet_whitelist"] = authSubnetWhitelistStringList.join("\n");
// Update my dynamic domain name
data["dyndns_enabled"] = pref->isDynDNSEnabled();
data["dyndns_service"] = pref->getDynDNSService();
@@ -427,6 +434,20 @@ void prefjson::setPreferences(const QString& json)
pref->setWebUiPassword(m["web_ui_password"].toString());
if (m.contains("bypass_local_auth"))
pref->setWebUiLocalAuthEnabled(!m["bypass_local_auth"].toBool());
if (m.contains("bypass_auth_subnet_whitelist_enabled"))
pref->setWebUiAuthSubnetWhitelistEnabled(m["bypass_auth_subnet_whitelist_enabled"].toBool());
if (m.contains("bypass_auth_subnet_whitelist")) {
QList<Utils::Net::Subnet> subnets;
// recognize new line and comma as delimiters
foreach (QString subnetString, m["bypass_auth_subnet_whitelist"].toString().split(QRegularExpression("\n|,"), QString::SkipEmptyParts)) {
bool ok = false;
const Utils::Net::Subnet subnet = Utils::Net::parseSubnet(subnetString.trimmed(), &ok);
if (ok)
subnets.append(subnet);
}
pref->setWebUiAuthSubnetWhitelist(subnets);
}
// Update my dynamic domain name
if (m.contains("dyndns_enabled"))
pref->setDynDNSEnabled(m["dyndns_enabled"].toBool());

View File

@@ -438,9 +438,17 @@
<div class="formRow">
<label for="webui_password_text" class="leftLabelSmall">QBT_TR(Password:)QBT_TR[CONTEXT=OptionsDialog]</label><input type="password" id="webui_password_text" />
</div>
<input type="checkbox" id="bypass_local_auth_checkbox" />
<label for="bypass_local_auth_checkbox">QBT_TR(Bypass authentication for localhost)QBT_TR[CONTEXT=OptionsDialog]</label>
<div class="formRow">
<input type="checkbox" id="bypass_local_auth_checkbox" />
<label for="bypass_local_auth_checkbox">QBT_TR(Bypass authentication for clients on localhost)QBT_TR[CONTEXT=OptionsDialog]</label>
</div>
<div class="formRow">
<input type="checkbox" id="bypass_auth_subnet_whitelist_checkbox" onclick="updateBypasssAuthSettings();" />
<label for="bypass_auth_subnet_whitelist_checkbox">QBT_TR(Bypass authentication for clients in these IP subnets (CIDR notation))QBT_TR[CONTEXT=OptionsDialog]</label>
</div>
<div class="formRow" style="padding-left: 30px; padding-top: 5px;">
<textarea id="bypass_auth_subnet_whitelist_textarea" rows="5" cols="48" placeholder="Example: 172.17.32.0/24, fdff:ffff:c8::/40"></textarea>
</div>
</fieldset>
<fieldset class="settings">
@@ -781,6 +789,13 @@ updateHttpsSettings = function() {
}
}
updateBypasssAuthSettings = function() {
if ($('bypass_auth_subnet_whitelist_checkbox').getProperty('checked'))
$('bypass_auth_subnet_whitelist_textarea').setProperty('disabled', false);
else
$('bypass_auth_subnet_whitelist_textarea').setProperty('disabled', true);
};
updateDynDnsSettings = function() {
if($('use_dyndns_checkbox').getProperty('checked')) {
$('dyndns_select').setProperty('disabled', false);
@@ -1059,6 +1074,9 @@ loadPreferences = function() {
$('webui_username_text').setProperty('value', pref.web_ui_username);
$('webui_password_text').setProperty('value', pref.web_ui_password);
$('bypass_local_auth_checkbox').setProperty('checked', pref.bypass_local_auth);
$('bypass_auth_subnet_whitelist_checkbox').setProperty('checked', pref.bypass_auth_subnet_whitelist_enabled);
$('bypass_auth_subnet_whitelist_textarea').setProperty('value', pref.bypass_auth_subnet_whitelist);
updateBypasssAuthSettings();
// Update my dynamic domain name
$('use_dyndns_checkbox').setProperty('checked', pref.dyndns_enabled);
@@ -1343,6 +1361,8 @@ applyPreferences = function() {
settings.set('web_ui_username', web_ui_username);
settings.set('web_ui_password', web_ui_password);
settings.set('bypass_local_auth', $('bypass_local_auth_checkbox').getProperty('checked'));
settings.set('bypass_auth_subnet_whitelist_enabled', $('bypass_auth_subnet_whitelist_checkbox').getProperty('checked'));
settings.set('bypass_auth_subnet_whitelist', $('bypass_auth_subnet_whitelist_textarea').getProperty('value'));
// Update my dynamic domain name
settings.set('dyndns_enabled', $('use_dyndns_checkbox').getProperty('checked'));