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); 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() int HttpSettings::httpPort()
{ {
static const int PORT = 19455; static const int PORT = 19455;

View File

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

View File

@ -15,6 +15,8 @@
#include "ui_OptionDialog.h" #include "ui_OptionDialog.h"
#include "HttpSettings.h" #include "HttpSettings.h"
#include <QMessageBox>
OptionDialog::OptionDialog(QWidget *parent) : OptionDialog::OptionDialog(QWidget *parent) :
QWidget(parent), QWidget(parent),
ui(new Ui::OptionDialog()) ui(new Ui::OptionDialog())
@ -41,7 +43,6 @@ void OptionDialog::loadSettings()
ui->sortByUsername->setChecked(true); ui->sortByUsername->setChecked(true);
else else
ui->sortByTitle->setChecked(true); ui->sortByTitle->setChecked(true);
ui->httpHost->setText(settings.httpHost());
ui->httpPort->setText(QString::number(settings.httpPort())); ui->httpPort->setText(QString::number(settings.httpPort()));
/* /*
@ -70,8 +71,14 @@ void OptionDialog::saveSettings()
settings.setUnlockDatabase(ui->unlockDatabase->isChecked()); settings.setUnlockDatabase(ui->unlockDatabase->isChecked());
settings.setMatchUrlScheme(ui->matchUrlScheme->isChecked()); settings.setMatchUrlScheme(ui->matchUrlScheme->isChecked());
settings.setSortByUsername(ui->sortByUsername->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()); settings.setPasswordUseLowercase(ui->checkBoxLower->isChecked());

View File

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

View File

@ -331,35 +331,20 @@ void Server::start(void)
if (m_started) if (m_started)
return; 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(); int port = HttpSettings::httpPort();
QHostInfo info = QHostInfo::fromName(HttpSettings::httpHost());
if (!info.addresses().isEmpty()) {
void* addrx = NULL; void* addrx = NULL;
unsigned int flags = MHD_USE_SELECT_INTERNALLY; unsigned int flags = MHD_USE_SELECT_INTERNALLY;
QHostAddress address = info.addresses().first();
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
struct sockaddr_in *addr = static_cast<struct sockaddr_in*>(calloc(1, sizeof(struct sockaddr_in))); struct sockaddr_in *addr = static_cast<struct sockaddr_in*>(calloc(1, sizeof(struct sockaddr_in)));
addrx = static_cast<void*>(addr); addrx = static_cast<void*>(addr);
addr->sin_family = AF_INET; addr->sin_family = AF_INET;
addr->sin_port = htons(HttpSettings::httpPort()); addr->sin_port = htons(port);
addr->sin_addr.s_addr = htonl(address.toIPv4Address()); 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, if (NULL == (daemon = MHD_start_daemon(flags, port, NULL, NULL,
&this->request_handler_wrapper, this, &this->request_handler_wrapper, this,
MHD_OPTION_NOTIFY_COMPLETED, MHD_OPTION_NOTIFY_COMPLETED,
@ -367,34 +352,15 @@ void Server::start(void)
MHD_OPTION_SOCK_ADDR, MHD_OPTION_SOCK_ADDR,
addrx, addrx,
MHD_OPTION_END))) { MHD_OPTION_END))) {
nohost = true; qWarning("HTTPPlugin: Failed to bind to localhost!");
qWarning("HTTPPlugin: Failed to bind to configured host!");
} else { } else {
nohost = false; m_started = true;
//qWarning("HTTPPlugin: Binded to configured host.");
}
} }
if (addrx != NULL) if (addrx != NULL)
free(addrx); free(addrx);
} }
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;
}
void Server::stop(void) void Server::stop(void)
{ {