diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d8608e7..79cf2293 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,6 +153,7 @@ find_package(Qt5Concurrent 5.2 REQUIRED) find_package(Qt5Widgets 5.2 REQUIRED) find_package(Qt5Test 5.2 REQUIRED) find_package(Qt5LinguistTools 5.2 REQUIRED) +find_package(Qt5Network 5.2 REQUIRED) set(CMAKE_AUTOMOC ON) # Debian sets the the build type to None for package builds. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2ef1d77d..c7d8cbf3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -174,7 +174,7 @@ qt5_wrap_ui(keepassx_SOURCES ${keepassx_FORMS}) add_library(keepassx_core STATIC ${keepassx_SOURCES}) set_target_properties(keepassx_core PROPERTIES COMPILE_DEFINITIONS KEEPASSX_BUILDING_CORE) -target_link_libraries(keepassx_core Qt5::Core Qt5::Concurrent Qt5::Widgets) +target_link_libraries(keepassx_core Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network) add_executable(${PROGNAME} WIN32 MACOSX_BUNDLE ${keepassx_SOURCES_MAINEXE}) target_link_libraries(${PROGNAME} @@ -183,6 +183,7 @@ target_link_libraries(${PROGNAME} Qt5::Core Qt5::Concurrent Qt5::Widgets + Qt5::Network ${GCRYPT_LIBRARIES} ${ZLIB_LIBRARIES}) diff --git a/src/http/HttpSettings.cpp b/src/http/HttpSettings.cpp index f9cf6c59..dd0dd00f 100644 --- a/src/http/HttpSettings.cpp +++ b/src/http/HttpSettings.cpp @@ -126,6 +126,18 @@ 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; diff --git a/src/http/HttpSettings.h b/src/http/HttpSettings.h index bea5648c..c1987f7e 100644 --- a/src/http/HttpSettings.h +++ b/src/http/HttpSettings.h @@ -42,6 +42,8 @@ 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); diff --git a/src/http/OptionDialog.cpp b/src/http/OptionDialog.cpp index 357a3cd7..4d9d1f6c 100644 --- a/src/http/OptionDialog.cpp +++ b/src/http/OptionDialog.cpp @@ -41,6 +41,7 @@ void OptionDialog::loadSettings() ui->sortByUsername->setChecked(true); else ui->sortByTitle->setChecked(true); + ui->httpHost->setText(settings.httpHost()); ui->httpPort->setText(QString::number(settings.httpPort())); /* @@ -68,6 +69,7 @@ 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()); /* diff --git a/src/http/OptionDialog.ui b/src/http/OptionDialog.ui index c925d7ad..a230f2ad 100644 --- a/src/http/OptionDialog.ui +++ b/src/http/OptionDialog.ui @@ -28,7 +28,7 @@ This is required for accessing keypass database from ChromeIPass or PassIfoxQTabWidget::Rounded - 2 + 0 @@ -200,6 +200,30 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< + + + + + + + 0 + 0 + + + + HTTP Host: + + + + + + + Default host: localhost + + + + + diff --git a/src/http/Protocol.cpp b/src/http/Protocol.cpp index 4650937e..40a1445c 100644 --- a/src/http/Protocol.cpp +++ b/src/http/Protocol.cpp @@ -27,7 +27,7 @@ static const char * const STR_SET_LOGIN = "set-login"; static const char * const STR_ASSOCIATE = "associate"; static const char * const STR_TEST_ASSOCIATE = "test-associate"; static const char * const STR_GENERATE_PASSWORD = "generate-password"; -static const char * const STR_VERSION = "1.8.4.1"; // TODO: not true, need to incorporate change of listener host +static const char * const STR_VERSION = "1.8.4.1"; }/*namespace KeepassHttpProtocol*/ diff --git a/src/http/Server.cpp b/src/http/Server.cpp index 2056464a..e54a9995 100644 --- a/src/http/Server.cpp +++ b/src/http/Server.cpp @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include using namespace KeepassHttpProtocol; @@ -324,11 +327,49 @@ void Server::start(void) int port = HttpSettings::httpPort(); - 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); + struct sockaddr_in as; + struct sockaddr_in *ss = &as; + bool nohost = true; + + QHostInfo info = QHostInfo::fromName(HttpSettings::httpHost()); + if (!info.addresses().isEmpty()) { + QHostAddress address = info.addresses().first(); + + if (address.protocol() == QAbstractSocket::IPv4Protocol) { + struct sockaddr_in* addr = ss; + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->sin_family = AF_INET; + addr->sin_port = htons(HttpSettings::httpPort()); + addr->sin_addr.s_addr = htonl(address.toIPv4Address()); + nohost = false; +#ifdef MHD_USE_IPv6 + } else { + struct sockaddr_in6* addr = (sockaddr_in6*)ss; + memset(addr, 0, sizeof(struct sockaddr_in6)); + addr->sin6_family = AF_INET6; + addr->sin6_port = htons(HttpSettings::httpPort()); + memcpy(&addr->sin6_addr, address.toIPv6Address().c, 16); + nohost = false; +#endif + } + + 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_SOCK_ADDR, + ss, + MHD_OPTION_END); + } + + if (nohost) { + 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); + } + m_started = true; }