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.ti...@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.ti...@collabora.com> Tested-by: Andras Timar <andras.ti...@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 <t...@collabora.com> +Maintainer: Andras Timar <andras.ti...@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)); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits