|
|
|
@@ -17,8 +17,6 @@
|
|
|
|
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* This file contains some classes in order to get info from file using the libavconv */
|
|
|
|
|
|
|
|
|
|
#include "PasswordService.hpp"
|
|
|
|
|
|
|
|
|
|
#include <Wt/Auth/HashFunction.h>
|
|
|
|
@@ -29,6 +27,8 @@
|
|
|
|
|
#include "utils/Exception.hpp"
|
|
|
|
|
#include "utils/Logger.hpp"
|
|
|
|
|
|
|
|
|
|
#include <security/pam_appl.h>
|
|
|
|
|
|
|
|
|
|
namespace Auth {
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<IPasswordService> createPasswordService(std::size_t maxThrottlerEntries)
|
|
|
|
@@ -41,10 +41,101 @@ PasswordService::PasswordService(std::size_t maxThrottlerEntries)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef USEPAM
|
|
|
|
|
static void
|
|
|
|
|
delete_resp(int num_msg, pam_response *response)
|
|
|
|
|
{
|
|
|
|
|
if (response == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
for (int i = 0; i < num_msg; i++) {
|
|
|
|
|
if (response[i].resp) {
|
|
|
|
|
/* clear before freeing -- might be a password */
|
|
|
|
|
bzero(response[i].resp, strlen(response[i].resp));
|
|
|
|
|
free(response[i].resp);
|
|
|
|
|
response[i].resp = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct pam_conv_data
|
|
|
|
|
{
|
|
|
|
|
const char *username;
|
|
|
|
|
const char *password;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
int lms_conv(int num_msg, const pam_message** msgs, pam_response** resps, void* appdata_ptr)
|
|
|
|
|
{
|
|
|
|
|
if(num_msg < 1)
|
|
|
|
|
return PAM_CONV_ERR;
|
|
|
|
|
if (!resps || !msgs || !appdata_ptr)
|
|
|
|
|
return PAM_CONV_ERR;
|
|
|
|
|
|
|
|
|
|
pam_conv_data *data = static_cast<pam_conv_data*>( appdata_ptr );
|
|
|
|
|
pam_response *response = new (std::nothrow) pam_response[num_msg];
|
|
|
|
|
if(!response)
|
|
|
|
|
return PAM_CONV_ERR;
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < num_msg; ++i)
|
|
|
|
|
{
|
|
|
|
|
response[i].resp_retcode = 0;
|
|
|
|
|
response[i].resp = 0;
|
|
|
|
|
switch (msgs[i]->msg_style) {
|
|
|
|
|
case PAM_PROMPT_ECHO_ON:
|
|
|
|
|
/* on memory allocation failure, auth fails */
|
|
|
|
|
response[i].resp = strdup(data->username);
|
|
|
|
|
break;
|
|
|
|
|
case PAM_PROMPT_ECHO_OFF:
|
|
|
|
|
response[i].resp = strdup(data->password);
|
|
|
|
|
break;
|
|
|
|
|
case PAM_ERROR_MSG:
|
|
|
|
|
case PAM_TEXT_INFO:
|
|
|
|
|
default:
|
|
|
|
|
delete_resp(i, response);
|
|
|
|
|
return PAM_CONV_ERR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*resps = response;
|
|
|
|
|
return PAM_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
pamCheckUserPassword(const std::string& loginName, const std::string& password)
|
|
|
|
|
{
|
|
|
|
|
#ifdef USEPAM
|
|
|
|
|
pam_conv_data authdata{loginName.c_str(), password.c_str()};
|
|
|
|
|
pam_conv conv = { lms_conv, &authdata };
|
|
|
|
|
pam_handle_t *pamh;
|
|
|
|
|
bool authenticated{false};
|
|
|
|
|
|
|
|
|
|
/* Initialize PAM framework */
|
|
|
|
|
int err = pam_start("lms", loginName.c_str(), &conv, &pamh);
|
|
|
|
|
if (err != PAM_SUCCESS) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = pam_authenticate(pamh, 0);
|
|
|
|
|
if(err == PAM_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
/* Make sure account and password are still valid */
|
|
|
|
|
err = pam_acct_mgmt(pamh, PAM_SILENT);
|
|
|
|
|
authenticated = err == PAM_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(void) pam_end(pamh, 0);
|
|
|
|
|
return authenticated;
|
|
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
bool
|
|
|
|
|
checkUserPassword(Database::Session& session, const std::string& loginName, const std::string& password)
|
|
|
|
|
{
|
|
|
|
|
bool hasExternalAuth;
|
|
|
|
|
Database::User::PasswordHash passwordHash;
|
|
|
|
|
{
|
|
|
|
|
auto transaction {session.createSharedTransaction()};
|
|
|
|
@@ -53,11 +144,19 @@ checkUserPassword(Database::Session& session, const std::string& loginName, cons
|
|
|
|
|
if (!user)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
hasExternalAuth = user->hasExternalAuth();
|
|
|
|
|
passwordHash = user->getPasswordHash();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Wt::Auth::BCryptHashFunction hashFunc {6};
|
|
|
|
|
return hashFunc.verify(password, passwordHash.salt, passwordHash.hash);
|
|
|
|
|
if (hasExternalAuth)
|
|
|
|
|
{
|
|
|
|
|
return pamCheckUserPassword(loginName, password);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
const Wt::Auth::BCryptHashFunction hashFunc {6};
|
|
|
|
|
return hashFunc.verify(password, passwordHash.salt, passwordHash.hash);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|