Only listen to local loopback instead of user-configured host as discussed in issue #147

Also issue warning when trying to bind to a port below 1024 and use default port in that case
This commit is contained in:
Janek Bevendorff 2017-01-24 00:08:48 +01:00
parent 8a3ac7a26e
commit 40aa92c5f7
No known key found for this signature in database
GPG Key ID: CFEC2F6850BFFA53
5 changed files with 71 additions and 110 deletions

View File

@ -126,18 +126,6 @@ void HttpSettings::setSupportKphFields(bool supportKphFields)
config()->set("Http/SupportKphFields", supportKphFields);
}
QString HttpSettings::httpHost()
{
static const QString host = "localhost";
return config()->get("Http/Host", host).toString().toUtf8();
}
void HttpSettings::setHttpHost(QString host)
{
config()->set("Http/Host", host);
}
int HttpSettings::httpPort()
{
static const int PORT = 19455;

View File

@ -42,8 +42,6 @@ public:
static void setSearchInAllDatabases(bool searchInAllDatabases);
static bool supportKphFields();
static void setSupportKphFields(bool supportKphFields);
static QString httpHost();
static void setHttpHost(QString host);
static int httpPort();
static void setHttpPort(int port);

View File

@ -15,6 +15,8 @@
#include "ui_OptionDialog.h"
#include "HttpSettings.h"
#include <QMessageBox>
OptionDialog::OptionDialog(QWidget *parent) :
QWidget(parent),
ui(new Ui::OptionDialog())
@ -41,7 +43,6 @@ void OptionDialog::loadSettings()
ui->sortByUsername->setChecked(true);
else
ui->sortByTitle->setChecked(true);
ui->httpHost->setText(settings.httpHost());
ui->httpPort->setText(QString::number(settings.httpPort()));
/*
@ -70,8 +71,14 @@ void OptionDialog::saveSettings()
settings.setUnlockDatabase(ui->unlockDatabase->isChecked());
settings.setMatchUrlScheme(ui->matchUrlScheme->isChecked());
settings.setSortByUsername(ui->sortByUsername->isChecked());
settings.setHttpHost(ui->httpHost->text());
settings.setHttpPort(ui->httpPort->text().toInt());
int port = ui->httpPort->text().toInt();
if (port < 1024) {
QMessageBox::warning(this, tr("Cannot bind to privileged ports"),
tr("Cannot bind to privileged ports below 1024!\nUsing default port 19455."));
port = 19455;
}
settings.setHttpPort(port);
/*
settings.setPasswordUseLowercase(ui->checkBoxLower->isChecked());

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>605</width>
<height>389</height>
<height>429</height>
</rect>
</property>
<property name="windowTitle">
@ -17,7 +17,7 @@
<item>
<widget class="QCheckBox" name="enableHttpServer">
<property name="text">
<string>Enable KeepassXC Http protocol
<string>Enable KeepassXC HTTP protocol
This is required for accessing your databases from ChromeIPass or PassIFox</string>
</property>
</widget>
@ -28,7 +28,7 @@ This is required for accessing your databases from ChromeIPass or PassIFox</stri
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
@ -201,32 +201,41 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned<
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_1">
<item>
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>HTTP Host:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="httpHost">
<property name="placeholderText">
<string>Default host: localhost</string>
</property>
</widget>
</item>
</layout>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QLineEdit" name="httpPort">
<property name="inputMask">
<string notr="true">d0000</string>
</property>
<property name="placeholderText">
<string>Default port: 19455</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_5">
<property name="text">
<string>KeePassXC will listen to this port on localhost</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -237,15 +246,8 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned<
<property name="text">
<string>HTTP Port:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="httpPort">
<property name="inputMask">
<string notr="true">d0000</string>
</property>
<property name="placeholderText">
<string>Default port: 19455</string>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>

View File

@ -331,68 +331,34 @@ void Server::start(void)
if (m_started)
return;
bool nohost = true;
// local loopback hardcoded, since KeePassHTTP handshake
// is not safe against interception
QHostAddress address("127.0.0.1");
int port = HttpSettings::httpPort();
void* addrx = NULL;
unsigned int flags = MHD_USE_SELECT_INTERNALLY;
QHostInfo info = QHostInfo::fromName(HttpSettings::httpHost());
if (!info.addresses().isEmpty()) {
void* addrx = NULL;
unsigned int flags = MHD_USE_SELECT_INTERNALLY;
QHostAddress address = info.addresses().first();
struct sockaddr_in *addr = static_cast<struct sockaddr_in*>(calloc(1, sizeof(struct sockaddr_in)));
addrx = static_cast<void*>(addr);
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
addr->sin_addr.s_addr = htonl(address.toIPv4Address());
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
struct sockaddr_in *addr = static_cast<struct sockaddr_in*>(calloc(1, sizeof(struct sockaddr_in)));
addrx = static_cast<void*>(addr);
addr->sin_family = AF_INET;
addr->sin_port = htons(HttpSettings::httpPort());
addr->sin_addr.s_addr = htonl(address.toIPv4Address());
nohost = false;
} else {
struct sockaddr_in6 *addr = static_cast<struct sockaddr_in6*>(calloc(1, sizeof(struct sockaddr_in6)));
addrx = static_cast<void*>(addr);
addr->sin6_family = AF_INET6;
addr->sin6_port = htons(HttpSettings::httpPort());
memcpy(&addr->sin6_addr, address.toIPv6Address().c, 16);
nohost = false;
flags |= MHD_USE_IPv6;
}
if (nohost) {
qWarning("HTTPPlugin: Faled to get configured host!");
} else {
if (NULL == (daemon = MHD_start_daemon(flags, port, NULL, NULL,
&this->request_handler_wrapper, this,
MHD_OPTION_NOTIFY_COMPLETED,
this->request_completed, NULL,
MHD_OPTION_SOCK_ADDR,
addrx,
MHD_OPTION_END))) {
nohost = true;
qWarning("HTTPPlugin: Failed to bind to configured host!");
} else {
nohost = false;
//qWarning("HTTPPlugin: Binded to configured host.");
}
}
if (addrx != NULL)
free(addrx);
if (NULL == (daemon = MHD_start_daemon(flags, port, NULL, NULL,
&this->request_handler_wrapper, this,
MHD_OPTION_NOTIFY_COMPLETED,
this->request_completed, NULL,
MHD_OPTION_SOCK_ADDR,
addrx,
MHD_OPTION_END))) {
qWarning("HTTPPlugin: Failed to bind to localhost!");
} else {
m_started = true;
}
if (nohost) {
if (NULL == (daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, port, NULL, NULL,
&this->request_handler_wrapper, this,
MHD_OPTION_NOTIFY_COMPLETED,
this->request_completed, NULL,
MHD_OPTION_END))) {
qWarning("HTTPPlugin: Fatal! Failed to bind to both configured and default hosts!");
} else {
qWarning("HTTPPlugin: Bound to fallback address 0.0.0.0/:::!");
}
}
m_started = true;
if (addrx != NULL)
free(addrx);
}