Drop WebUI default credentials

PR #19777.
This commit is contained in:
Vladimir Golovnev
2023-11-10 07:18:42 +03:00
committed by Vladimir Golovnev (Glassez)
parent 2c2252d7d9
commit 786c09e981
21 changed files with 378 additions and 254 deletions

View File

@@ -50,7 +50,7 @@ IPSubnetWhitelistOptionsDialog::IPSubnetWhitelistOptionsDialog(QWidget *parent)
connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
QStringList authSubnetWhitelistStringList;
for (const Utils::Net::Subnet &subnet : asConst(Preferences::instance()->getWebUiAuthSubnetWhitelist()))
for (const Utils::Net::Subnet &subnet : asConst(Preferences::instance()->getWebUIAuthSubnetWhitelist()))
authSubnetWhitelistStringList << Utils::Net::subnetToString(subnet);
m_model = new QStringListModel(authSubnetWhitelistStringList, this);
@@ -81,7 +81,7 @@ void IPSubnetWhitelistOptionsDialog::on_buttonBox_accepted()
// Operate on the m_sortFilter to grab the strings in sorted order
for (int i = 0; i < m_sortFilter->rowCount(); ++i)
subnets.append(m_sortFilter->index(i, 0).data().toString());
Preferences::instance()->setWebUiAuthSubnetWhitelist(subnets);
Preferences::instance()->setWebUIAuthSubnetWhitelist(subnets);
QDialog::accept();
}
else

View File

@@ -1182,7 +1182,7 @@ void MainWindow::closeEvent(QCloseEvent *e)
if (!isVisible())
show();
QMessageBox confirmBox(QMessageBox::Question, tr("Exiting qBittorrent"),
// Split it because the last sentence is used in the Web UI
// Split it because the last sentence is used in the WebUI
tr("Some files are currently transferring.") + u'\n' + tr("Are you sure you want to quit qBittorrent?"),
QMessageBox::NoButton, this);
QPushButton *noBtn = confirmBox.addButton(tr("&No"), QMessageBox::NoRole);

View File

@@ -69,6 +69,7 @@
#include "utils.h"
#include "watchedfolderoptionsdialog.h"
#include "watchedfoldersmodel.h"
#include "webui/webui.h"
#ifndef DISABLE_WEBUI
#include "base/net/dnsupdater.h"
@@ -80,6 +81,9 @@
#define SETTINGS_KEY(name) u"OptionsDialog/" name
const int WEBUI_MIN_USERNAME_LENGTH = 3;
const int WEBUI_MIN_PASSWORD_LENGTH = 6;
namespace
{
QStringList translatedWeekdayNames()
@@ -106,6 +110,16 @@ namespace
}
};
bool isValidWebUIUsername(const QString &username)
{
return (username.length() >= WEBUI_MIN_USERNAME_LENGTH);
}
bool isValidWebUIPassword(const QString &password)
{
return (password.length() >= WEBUI_MIN_PASSWORD_LENGTH);
}
// Shortcuts for frequently used signals that have more than one overload. They would require
// type casts and that is why we declare required member pointer here instead.
void (QComboBox::*qComboBoxCurrentIndexChanged)(int) = &QComboBox::currentIndexChanged;
@@ -175,7 +189,11 @@ OptionsDialog::OptionsDialog(IGUIApplication *app, QWidget *parent)
// setup apply button
m_applyButton->setEnabled(false);
connect(m_applyButton, &QPushButton::clicked, this, &OptionsDialog::applySettings);
connect(m_applyButton, &QPushButton::clicked, this, [this]
{
if (applySettings())
m_applyButton->setEnabled(false);
});
// disable mouse wheel event on widgets to avoid misselection
auto *wheelEventEater = new WheelEventEater(this);
@@ -1211,28 +1229,33 @@ void OptionsDialog::loadWebUITabOptions()
m_ui->textWebUIRootFolder->setMode(FileSystemPathEdit::Mode::DirectoryOpen);
m_ui->textWebUIRootFolder->setDialogCaption(tr("Choose Alternative UI files location"));
m_ui->checkWebUi->setChecked(pref->isWebUiEnabled());
m_ui->textWebUiAddress->setText(pref->getWebUiAddress());
m_ui->spinWebUiPort->setValue(pref->getWebUiPort());
if (app()->webUI()->isErrored())
m_ui->labelWebUIError->setText(tr("WebUI configuration failed. Reason: %1").arg(app()->webUI()->errorMessage()));
else
m_ui->labelWebUIError->hide();
m_ui->checkWebUI->setChecked(pref->isWebUIEnabled());
m_ui->textWebUIAddress->setText(pref->getWebUIAddress());
m_ui->spinWebUIPort->setValue(pref->getWebUIPort());
m_ui->checkWebUIUPnP->setChecked(pref->useUPnPForWebUIPort());
m_ui->checkWebUiHttps->setChecked(pref->isWebUiHttpsEnabled());
m_ui->checkWebUIHttps->setChecked(pref->isWebUIHttpsEnabled());
webUIHttpsCertChanged(pref->getWebUIHttpsCertificatePath());
webUIHttpsKeyChanged(pref->getWebUIHttpsKeyPath());
m_ui->textWebUiUsername->setText(pref->getWebUiUsername());
m_ui->checkBypassLocalAuth->setChecked(!pref->isWebUiLocalAuthEnabled());
m_ui->checkBypassAuthSubnetWhitelist->setChecked(pref->isWebUiAuthSubnetWhitelistEnabled());
m_ui->textWebUIUsername->setText(pref->getWebUIUsername());
m_ui->checkBypassLocalAuth->setChecked(!pref->isWebUILocalAuthEnabled());
m_ui->checkBypassAuthSubnetWhitelist->setChecked(pref->isWebUIAuthSubnetWhitelistEnabled());
m_ui->IPSubnetWhitelistButton->setEnabled(m_ui->checkBypassAuthSubnetWhitelist->isChecked());
m_ui->spinBanCounter->setValue(pref->getWebUIMaxAuthFailCount());
m_ui->spinBanDuration->setValue(pref->getWebUIBanDuration().count());
m_ui->spinSessionTimeout->setValue(pref->getWebUISessionTimeout());
// Alternative UI
m_ui->groupAltWebUI->setChecked(pref->isAltWebUiEnabled());
m_ui->textWebUIRootFolder->setSelectedPath(pref->getWebUiRootFolder());
m_ui->groupAltWebUI->setChecked(pref->isAltWebUIEnabled());
m_ui->textWebUIRootFolder->setSelectedPath(pref->getWebUIRootFolder());
// Security
m_ui->checkClickjacking->setChecked(pref->isWebUiClickjackingProtectionEnabled());
m_ui->checkCSRFProtection->setChecked(pref->isWebUiCSRFProtectionEnabled());
m_ui->checkSecureCookie->setEnabled(pref->isWebUiHttpsEnabled());
m_ui->checkSecureCookie->setChecked(pref->isWebUiSecureCookieEnabled());
m_ui->checkClickjacking->setChecked(pref->isWebUIClickjackingProtectionEnabled());
m_ui->checkCSRFProtection->setChecked(pref->isWebUICSRFProtectionEnabled());
m_ui->checkSecureCookie->setEnabled(pref->isWebUIHttpsEnabled());
m_ui->checkSecureCookie->setChecked(pref->isWebUISecureCookieEnabled());
m_ui->groupHostHeaderValidation->setChecked(pref->isWebUIHostHeaderValidationEnabled());
m_ui->textServerDomains->setText(pref->getServerDomains());
// Custom HTTP headers
@@ -1248,18 +1271,18 @@ void OptionsDialog::loadWebUITabOptions()
m_ui->DNSUsernameTxt->setText(pref->getDynDNSUsername());
m_ui->DNSPasswordTxt->setText(pref->getDynDNSPassword());
connect(m_ui->checkWebUi, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->textWebUiAddress, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
connect(m_ui->spinWebUiPort, qSpinBoxValueChanged, this, &ThisType::enableApplyButton);
connect(m_ui->checkWebUI, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->textWebUIAddress, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
connect(m_ui->spinWebUIPort, qSpinBoxValueChanged, this, &ThisType::enableApplyButton);
connect(m_ui->checkWebUIUPnP, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->checkWebUiHttps, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->checkWebUIHttps, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->textWebUIHttpsCert, &FileSystemPathLineEdit::selectedPathChanged, this, &ThisType::enableApplyButton);
connect(m_ui->textWebUIHttpsCert, &FileSystemPathLineEdit::selectedPathChanged, this, &OptionsDialog::webUIHttpsCertChanged);
connect(m_ui->textWebUIHttpsKey, &FileSystemPathLineEdit::selectedPathChanged, this, &ThisType::enableApplyButton);
connect(m_ui->textWebUIHttpsKey, &FileSystemPathLineEdit::selectedPathChanged, this, &OptionsDialog::webUIHttpsKeyChanged);
connect(m_ui->textWebUiUsername, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
connect(m_ui->textWebUiPassword, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
connect(m_ui->textWebUIUsername, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
connect(m_ui->textWebUIPassword, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
connect(m_ui->checkBypassLocalAuth, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->checkBypassAuthSubnetWhitelist, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
@@ -1273,7 +1296,7 @@ void OptionsDialog::loadWebUITabOptions()
connect(m_ui->checkClickjacking, &QCheckBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->checkCSRFProtection, &QCheckBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->checkWebUiHttps, &QGroupBox::toggled, m_ui->checkSecureCookie, &QWidget::setEnabled);
connect(m_ui->checkWebUIHttps, &QGroupBox::toggled, m_ui->checkSecureCookie, &QWidget::setEnabled);
connect(m_ui->checkSecureCookie, &QCheckBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->groupHostHeaderValidation, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->textServerDomains, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
@@ -1295,29 +1318,32 @@ void OptionsDialog::saveWebUITabOptions() const
{
auto *pref = Preferences::instance();
pref->setWebUiEnabled(isWebUiEnabled());
pref->setWebUiAddress(m_ui->textWebUiAddress->text());
pref->setWebUiPort(m_ui->spinWebUiPort->value());
const bool webUIEnabled = isWebUIEnabled();
pref->setWebUIEnabled(webUIEnabled);
pref->setWebUIAddress(m_ui->textWebUIAddress->text());
pref->setWebUIPort(m_ui->spinWebUIPort->value());
pref->setUPnPForWebUIPort(m_ui->checkWebUIUPnP->isChecked());
pref->setWebUiHttpsEnabled(m_ui->checkWebUiHttps->isChecked());
pref->setWebUIHttpsEnabled(m_ui->checkWebUIHttps->isChecked());
pref->setWebUIHttpsCertificatePath(m_ui->textWebUIHttpsCert->selectedPath());
pref->setWebUIHttpsKeyPath(m_ui->textWebUIHttpsKey->selectedPath());
pref->setWebUIMaxAuthFailCount(m_ui->spinBanCounter->value());
pref->setWebUIBanDuration(std::chrono::seconds {m_ui->spinBanDuration->value()});
pref->setWebUISessionTimeout(m_ui->spinSessionTimeout->value());
// Authentication
pref->setWebUiUsername(webUiUsername());
if (!webUiPassword().isEmpty())
pref->setWebUIPassword(Utils::Password::PBKDF2::generate(webUiPassword()));
pref->setWebUiLocalAuthEnabled(!m_ui->checkBypassLocalAuth->isChecked());
pref->setWebUiAuthSubnetWhitelistEnabled(m_ui->checkBypassAuthSubnetWhitelist->isChecked());
if (const QString username = webUIUsername(); isValidWebUIUsername(username))
pref->setWebUIUsername(username);
if (const QString password = webUIPassword(); isValidWebUIPassword(password))
pref->setWebUIPassword(Utils::Password::PBKDF2::generate(password));
pref->setWebUILocalAuthEnabled(!m_ui->checkBypassLocalAuth->isChecked());
pref->setWebUIAuthSubnetWhitelistEnabled(m_ui->checkBypassAuthSubnetWhitelist->isChecked());
// Alternative UI
pref->setAltWebUiEnabled(m_ui->groupAltWebUI->isChecked());
pref->setWebUiRootFolder(m_ui->textWebUIRootFolder->selectedPath());
pref->setAltWebUIEnabled(m_ui->groupAltWebUI->isChecked());
pref->setWebUIRootFolder(m_ui->textWebUIRootFolder->selectedPath());
// Security
pref->setWebUiClickjackingProtectionEnabled(m_ui->checkClickjacking->isChecked());
pref->setWebUiCSRFProtectionEnabled(m_ui->checkCSRFProtection->isChecked());
pref->setWebUiSecureCookieEnabled(m_ui->checkSecureCookie->isChecked());
pref->setWebUIClickjackingProtectionEnabled(m_ui->checkClickjacking->isChecked());
pref->setWebUICSRFProtectionEnabled(m_ui->checkCSRFProtection->isChecked());
pref->setWebUISecureCookieEnabled(m_ui->checkSecureCookie->isChecked());
pref->setWebUIHostHeaderValidationEnabled(m_ui->groupHostHeaderValidation->isChecked());
pref->setServerDomains(m_ui->textServerDomains->text());
// Custom HTTP headers
@@ -1517,53 +1543,37 @@ void OptionsDialog::on_buttonBox_accepted()
{
if (m_applyButton->isEnabled())
{
if (!schedTimesOk())
{
m_ui->tabSelection->setCurrentRow(TAB_SPEED);
if (!applySettings())
return;
}
#ifndef DISABLE_WEBUI
if (!webUIAuthenticationOk())
{
m_ui->tabSelection->setCurrentRow(TAB_WEBUI);
return;
}
if (!isAlternativeWebUIPathValid())
{
m_ui->tabSelection->setCurrentRow(TAB_WEBUI);
return;
}
#endif
m_applyButton->setEnabled(false);
saveOptions();
}
accept();
}
void OptionsDialog::applySettings()
bool OptionsDialog::applySettings()
{
if (!schedTimesOk())
{
m_ui->tabSelection->setCurrentRow(TAB_SPEED);
return;
return false;
}
#ifndef DISABLE_WEBUI
if (!webUIAuthenticationOk())
if (isWebUIEnabled() && !webUIAuthenticationOk())
{
m_ui->tabSelection->setCurrentRow(TAB_WEBUI);
return;
return false;
}
if (!isAlternativeWebUIPathValid())
{
m_ui->tabSelection->setCurrentRow(TAB_WEBUI);
return;
return false;
}
#endif
m_applyButton->setEnabled(false);
saveOptions();
return true;
}
void OptionsDialog::on_buttonBox_rejected()
@@ -1859,31 +1869,33 @@ void OptionsDialog::webUIHttpsKeyChanged(const Path &path)
(isKeyValid ? u"security-high"_s : u"security-low"_s), 24));
}
bool OptionsDialog::isWebUiEnabled() const
bool OptionsDialog::isWebUIEnabled() const
{
return m_ui->checkWebUi->isChecked();
return m_ui->checkWebUI->isChecked();
}
QString OptionsDialog::webUiUsername() const
QString OptionsDialog::webUIUsername() const
{
return m_ui->textWebUiUsername->text();
return m_ui->textWebUIUsername->text();
}
QString OptionsDialog::webUiPassword() const
QString OptionsDialog::webUIPassword() const
{
return m_ui->textWebUiPassword->text();
return m_ui->textWebUIPassword->text();
}
bool OptionsDialog::webUIAuthenticationOk()
{
if (webUiUsername().length() < 3)
if (!isValidWebUIUsername(webUIUsername()))
{
QMessageBox::warning(this, tr("Length Error"), tr("The Web UI username must be at least 3 characters long."));
QMessageBox::warning(this, tr("Length Error"), tr("The WebUI username must be at least 3 characters long."));
return false;
}
if (!webUiPassword().isEmpty() && (webUiPassword().length() < 6))
const bool dontChangePassword = webUIPassword().isEmpty() && !Preferences::instance()->getWebUIPassword().isEmpty();
if (!isValidWebUIPassword(webUIPassword()) && !dontChangePassword)
{
QMessageBox::warning(this, tr("Length Error"), tr("The Web UI password must be at least 6 characters long."));
QMessageBox::warning(this, tr("Length Error"), tr("The WebUI password must be at least 6 characters long."));
return false;
}
return true;
@@ -1893,7 +1905,7 @@ bool OptionsDialog::isAlternativeWebUIPathValid()
{
if (m_ui->groupAltWebUI->isChecked() && m_ui->textWebUIRootFolder->selectedPath().isEmpty())
{
QMessageBox::warning(this, tr("Location Error"), tr("The alternative Web UI files location cannot be blank."));
QMessageBox::warning(this, tr("Location Error"), tr("The alternative WebUI files location cannot be blank."));
return false;
}
return true;

View File

@@ -88,7 +88,6 @@ private slots:
void adjustProxyOptions();
void on_buttonBox_accepted();
void on_buttonBox_rejected();
void applySettings();
void enableApplyButton();
void toggleComboRatioLimitAct();
void changePage(QListWidgetItem *, QListWidgetItem *);
@@ -115,6 +114,7 @@ private:
void showEvent(QShowEvent *e) override;
// Methods
bool applySettings();
void saveOptions() const;
void loadBehaviorTabOptions();
@@ -184,9 +184,9 @@ private:
int getMaxActiveTorrents() const;
// WebUI
#ifndef DISABLE_WEBUI
bool isWebUiEnabled() const;
QString webUiUsername() const;
QString webUiPassword() const;
bool isWebUIEnabled() const;
QString webUIUsername() const;
QString webUIPassword() const;
bool webUIAuthenticationOk();
bool isAlternativeWebUIPathValid();
#endif

View File

@@ -3223,8 +3223,8 @@ Disable encryption: Only connect to peers without protocol encryption</string>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabWebuiPage">
<layout class="QVBoxLayout" name="tabWebuiPageLayout">
<widget class="QWidget" name="tabWebUIPage">
<layout class="QVBoxLayout" name="tabWebUIPageLayout">
<property name="leftMargin">
<number>0</number>
</property>
@@ -3253,7 +3253,7 @@ Disable encryption: Only connect to peers without protocol encryption</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_23">
<item>
<widget class="QGroupBox" name="checkWebUi">
<widget class="QGroupBox" name="checkWebUI">
<property name="title">
<string>Web User Interface (Remote control)</string>
</property>
@@ -3264,17 +3264,29 @@ Disable encryption: Only connect to peers without protocol encryption</string>
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="labelWebUIError">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="lblWebUiAddress">
<widget class="QLabel" name="lblWebUIAddress">
<property name="text">
<string>IP address:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="textWebUiAddress">
<widget class="QLineEdit" name="textWebUIAddress">
<property name="toolTip">
<string>IP address that the Web UI will bind to.
Specify an IPv4 or IPv6 address. You can specify &quot;0.0.0.0&quot; for any IPv4 address,
@@ -3283,14 +3295,14 @@ Specify an IPv4 or IPv6 address. You can specify &quot;0.0.0.0&quot; for any IPv
</widget>
</item>
<item>
<widget class="QLabel" name="lblWebUiPort">
<widget class="QLabel" name="lblWebUIPort">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinWebUiPort">
<widget class="QSpinBox" name="spinWebUIPort">
<property name="minimum">
<number>1</number>
</property>
@@ -3315,7 +3327,7 @@ Specify an IPv4 or IPv6 address. You can specify &quot;0.0.0.0&quot; for any IPv
</widget>
</item>
<item>
<widget class="QGroupBox" name="checkWebUiHttps">
<widget class="QGroupBox" name="checkWebUIHttps">
<property name="title">
<string>&amp;Use HTTPS instead of HTTP</string>
</property>
@@ -3327,14 +3339,14 @@ Specify an IPv4 or IPv6 address. You can specify &quot;0.0.0.0&quot; for any IPv
</property>
<layout class="QGridLayout" name="gridLayout_11">
<item row="1" column="1">
<widget class="QLabel" name="lblWebUiKey">
<widget class="QLabel" name="lblWebUIKey">
<property name="text">
<string>Key:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblWebUiCrt">
<widget class="QLabel" name="lblWebUICrt">
<property name="text">
<string>Certificate:</string>
</property>
@@ -3366,7 +3378,7 @@ Specify an IPv4 or IPv6 address. You can specify &quot;0.0.0.0&quot; for any IPv
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupWebUiAuth">
<widget class="QGroupBox" name="groupWebUIAuth">
<property name="title">
<string>Authentication</string>
</property>
@@ -3374,24 +3386,24 @@ Specify an IPv4 or IPv6 address. You can specify &quot;0.0.0.0&quot; for any IPv
<item>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="0">
<widget class="QLabel" name="lblWebUiUsername">
<widget class="QLabel" name="lblWebUIUsername">
<property name="text">
<string>Username:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="textWebUiUsername"/>
<widget class="QLineEdit" name="textWebUIUsername"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblWebUiPassword">
<widget class="QLabel" name="lblWebUIPassword">
<property name="text">
<string>Password:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="textWebUiPassword">
<widget class="QLineEdit" name="textWebUIPassword">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
@@ -3819,13 +3831,13 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
<tabstop>stopConditionComboBox</tabstop>
<tabstop>spinPort</tabstop>
<tabstop>checkUPnP</tabstop>
<tabstop>textWebUiUsername</tabstop>
<tabstop>checkWebUi</tabstop>
<tabstop>textWebUIUsername</tabstop>
<tabstop>checkWebUI</tabstop>
<tabstop>textSavePath</tabstop>
<tabstop>scrollArea_7</tabstop>
<tabstop>scrollArea_2</tabstop>
<tabstop>spinWebUiPort</tabstop>
<tabstop>textWebUiPassword</tabstop>
<tabstop>spinWebUIPort</tabstop>
<tabstop>textWebUIPassword</tabstop>
<tabstop>buttonBox</tabstop>
<tabstop>tabSelection</tabstop>
<tabstop>scrollArea</tabstop>
@@ -3915,7 +3927,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
<tabstop>spinMaxActiveUploads</tabstop>
<tabstop>spinMaxActiveTorrents</tabstop>
<tabstop>checkWebUIUPnP</tabstop>
<tabstop>checkWebUiHttps</tabstop>
<tabstop>checkWebUIHttps</tabstop>
<tabstop>checkBypassLocalAuth</tabstop>
<tabstop>checkBypassAuthSubnetWhitelist</tabstop>
<tabstop>IPSubnetWhitelistButton</tabstop>