[Libreoffice-commits] online.git: debian/control loolwsd.spec.in loolwsd.xml.in Makefile.am wsd/FileServer.cpp wsd/LOOLWSD.cpp
Andras Timar
andras.timar at collabora.com
Tue Jan 23 10:04:03 UTC 2018
Makefile.am | 2 -
debian/control | 2 -
loolwsd.spec.in | 4 ++
loolwsd.xml.in | 5 +-
wsd/FileServer.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++++------
wsd/LOOLWSD.cpp | 3 +
6 files changed, 90 insertions(+), 15 deletions(-)
New commits:
commit a2e25cc7d31f3daa011df7f7b4e40fc540d91d2a
Author: Andras Timar <andras.timar at collabora.com>
Date: Mon Jan 22 11:57:39 2018 +0100
Add PAM support
Possibilities are endless. With a simple /etc/pam.d/loolwsd config below,
the user which runs loolwsd ('lool' in production environment) can login
to admin console with normal linux password.
auth required pam_unix.so
account required pam_unix.so
Change-Id: I354a7e9b4705e8fe346d17d6b6041d1406198b37
Reviewed-on: https://gerrit.libreoffice.org/48307
Reviewed-by: Andras Timar <andras.timar at collabora.com>
Tested-by: Andras Timar <andras.timar at collabora.com>
diff --git a/Makefile.am b/Makefile.am
index 3d751207..d0e2ae2d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -36,7 +36,7 @@ if !ENABLE_DEBUG
AM_CPPFLAGS += -DNDEBUG
endif
-AM_LDFLAGS = -pthread -Wl,-E,-rpath,/snap/loolwsd/current/usr/lib $(ZLIB_LIBS)
+AM_LDFLAGS = -pthread -Wl,-E,-rpath,/snap/loolwsd/current/usr/lib -lpam $(ZLIB_LIBS)
if ENABLE_SSL
AM_LDFLAGS += -lssl -lcrypto
diff --git a/debian/control b/debian/control
index b89cb7ca..30bdfe04 100644
--- a/debian/control
+++ b/debian/control
@@ -1,7 +1,7 @@
Source: loolwsd
Section: web
Priority: optional
-Maintainer: Tor Lillqvist <tml at collabora.com>
+Maintainer: Andras Timar <andras.timar at collabora.com>
Build-Depends: debhelper (>= 9), dh-systemd (>= 1.3), libcap-dev, libcap2-bin, libpcre3-dev, libpng-dev, libpoco-dev (>= 1.7.5), linux-libc-dev
Standards-Version: 3.9.7
diff --git a/loolwsd.spec.in b/loolwsd.spec.in
index f7355b17..0933b1a3 100644
--- a/loolwsd.spec.in
+++ b/loolwsd.spec.in
@@ -88,6 +88,9 @@ install -D -m 644 sysconfig.loolwsd %{buildroot}/var/adm/fillup-templates
mkdir -p %{buildroot}/etc/cron.d
echo "#Remove old tiles once every 10 days at midnight" > %{buildroot}/etc/cron.d/loolwsd.cron
echo "0 0 */1 * * root find /var/cache/loolwsd -name \"*.png\" -a -atime +10 -exec rm {} \;" >> %{buildroot}/etc/cron.d/loolwsd.cron
+mkdir -p %{buildroot}/etc/pam.d
+echo "auth required pam_unix.so" > %{buildroot}/etc/pam.d/loolwsd
+echo "account required pam_unix.so" >> %{buildroot}/etc/pam.d/loolwsd
%files
/usr/bin/loolwsd
@@ -116,6 +119,7 @@ echo "0 0 */1 * * root find /var/cache/loolwsd -name \"*.png\" -a -atime +10 -ex
%endif
%config(noreplace) /etc/cron.d/loolwsd.cron
+%config(noreplace) /etc/pam.d/loolwsd
%config(noreplace) %attr(640, lool, root) /etc/loolwsd/loolwsd.xml
%config /etc/loolwsd/loolkitconfig.xcu
diff --git a/loolwsd.xml.in b/loolwsd.xml.in
index 1609c7bc..31ab1a07 100644
--- a/loolwsd.xml.in
+++ b/loolwsd.xml.in
@@ -100,8 +100,9 @@
<tile_cache_persistent desc="Should the tiles persist between two editing sessions of the given document?" type="bool" default="true">true</tile_cache_persistent>
<admin_console desc="Web admin console settings.">
- <username desc="The username of the admin console. Must be set."></username>
- <password desc="The password of the admin console. Must be set."></password>
+ <enable_pam desc="Enable admin user authentication with PAM" type="bool" default="true">true</enable_pam>
+ <username desc="The username of the admin console. Must be set, if PAM is not enabled, otherwise it's optional."></username>
+ <password desc="The password of the admin console. Deprecated on most platforms. Instead, use loolconfig to set up a secure password."></password>
</admin_console>
</config>
diff --git a/wsd/FileServer.cpp b/wsd/FileServer.cpp
index 9f788818..ad4b890d 100644
--- a/wsd/FileServer.cpp
+++ b/wsd/FileServer.cpp
@@ -17,6 +17,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <zlib.h>
+#include <security/pam_appl.h>
#include <openssl/evp.h>
@@ -53,6 +54,62 @@ using Poco::Util::Application;
std::map<std::string, std::pair<std::string, std::string>> FileServerRequestHandler::FileHash;
+namespace {
+
+int functionConversation(int /*num_msg*/, const struct pam_message** /*msg*/,
+ struct pam_response **reply, void *appdata_ptr)
+{
+ *reply = (struct pam_response *)malloc(sizeof(struct pam_response));
+ (*reply)[0].resp = strdup(static_cast<char *>(appdata_ptr));
+ (*reply)[0].resp_retcode = 0;
+
+ return PAM_SUCCESS;
+}
+
+bool isPamAuthOk(const std::string user, const std::string pass)
+{
+ struct pam_conv localConversation { functionConversation, nullptr };
+ pam_handle_t *localAuthHandle = NULL;
+ int retval;
+
+ localConversation.appdata_ptr = const_cast<char *>(pass.c_str());
+
+ retval = pam_start("loolwsd", user.c_str(), &localConversation, &localAuthHandle);
+
+ if (retval != PAM_SUCCESS)
+ {
+ LOG_ERR("pam_start returned " << retval);
+ return false;
+ }
+
+ retval = pam_authenticate(localAuthHandle, 0);
+
+ if (retval != PAM_SUCCESS)
+ {
+ if (retval == PAM_AUTH_ERR)
+ {
+ LOG_ERR("PAM authentication failure for user \"" << user << "\".");
+ }
+ else
+ {
+ LOG_ERR("pam_authenticate returned " << retval);
+ }
+ return false;
+ }
+
+ LOG_INF("PAM authentication success for user \"" << user << "\".");
+
+ retval = pam_end(localAuthHandle, retval);
+
+ if (retval != PAM_SUCCESS)
+ {
+ LOG_WRN("pam_end returned " << retval);
+ }
+
+ return true;
+}
+}
+
bool FileServerRequestHandler::isAdminLoggedIn(const HTTPRequest& request,
HTTPResponse &response)
{
@@ -81,10 +138,12 @@ bool FileServerRequestHandler::isAdminLoggedIn(const HTTPRequest& request,
HTTPBasicCredentials credentials(request);
std::string userProvidedPwd = credentials.getPassword();
+ std::string userProvidedUsr = credentials.getUsername();
// If no cookie found, or is invalid, let admin re-login
const std::string user = config.getString("admin_console.username", "");
std::string pass = config.getString("admin_console.password", "");
+ const bool pam = config.getBool("admin_console.enable_pam", "true");
if (config.has("admin_console.secure_password"))
{
@@ -99,9 +158,7 @@ bool FileServerRequestHandler::isAdminLoggedIn(const HTTPRequest& request,
!Util::dataFromHexString(tokens[3], saltData))
{
LOG_ERR("Incorrect format detected for secure_password in config file."
- << "Denying access until correctly set."
<< "Use loolconfig to configure admin password.");
- return false;
}
unsigned char userProvidedPwdHash[tokens[4].size() / 2];
@@ -120,18 +177,29 @@ bool FileServerRequestHandler::isAdminLoggedIn(const HTTPRequest& request,
#else
LOG_ERR("The config file has admin_console.secure_password setting, "
<< "but this application was compiled with old OpenSSL version, "
- << "and this setting cannot be used. Falling back to plain text password, if it is set.");
+ << "and this setting cannot be used. Falling back to plain text password or to PAM, if it is set.");
#endif
}
- if (user.empty() || pass.empty())
+ if (!pam && (user.empty() || pass.empty()))
{
LOG_ERR("Admin Console credentials missing. Denying access until set.");
return false;
}
- if (credentials.getUsername() == user &&
- userProvidedPwd == pass)
+ bool authenticated = false;
+
+ if (userProvidedUsr == user && userProvidedPwd == pass)
+ {
+ authenticated = true;
+ }
+
+ if (!authenticated && pam)
+ {
+ authenticated = isPamAuthOk(userProvidedUsr, userProvidedPwd);
+ }
+
+ if (authenticated)
{
// generate and set the cookie
JWTAuth authAgent(sslKeyPath, "admin", "admin", "admin");
@@ -143,12 +211,13 @@ bool FileServerRequestHandler::isAdminLoggedIn(const HTTPRequest& request,
cookie.setSecure(LOOLWSD::isSSLEnabled() ||
LOOLWSD::isSSLTermination());
response.addCookie(cookie);
-
- return true;
+ }
+ else
+ {
+ LOG_INF("Wrong admin credentials.");
}
- LOG_INF("Wrong admin credentials.");
- return false;
+ return authenticated;
}
void FileServerRequestHandler::handleRequest(const HTTPRequest& request, Poco::MemoryInputStream& message,
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 94b4c0d3..88b6f805 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -687,7 +687,8 @@ void LOOLWSD::initialize(Application& self)
{ "logging.file.property[3]", "false" },
{ "trace[@enable]", "false" },
{ "trace.path[@compress]", "true" },
- { "trace.path[@snapshot]", "false" } };
+ { "trace.path[@snapshot]", "false" },
+ { "admin_console.enable_pam", "true"} };
// Set default values, in case they are missing from the config file.
AutoPtr<AppConfigMap> defConfig(new AppConfigMap(DefAppConfig));
More information about the Libreoffice-commits
mailing list