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@collabora.com> Tested-by: Andras Timar <andras.timar@collabora.com>private/kendy/monitoring-rebased
parent
30b44bf373
commit
a2e25cc7d3
|
@ -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
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Source: loolwsd
|
||||
Section: web
|
||||
Priority: optional
|
||||
Maintainer: Tor Lillqvist <tml@collabora.com>
|
||||
Maintainer: Andras Timar <andras.timar@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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue