Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 34 additions & 18 deletions src/auth/Pam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <filesystem>
#include <unistd.h>
#include <pwd.h>
#include <security/pam_appl.h>
#if __has_include(<security/pam_misc.h>)
#include <security/pam_misc.h>
#endif
Expand Down Expand Up @@ -106,34 +105,27 @@ void CPam::init() {
}

bool CPam::auth() {
const pam_conv localConv = {.conv = conv, .appdata_ptr = (void*)&m_sConversationState};
pam_handle_t* handle = nullptr;
auto uidPassword = getpwuid(getuid());
RASSERT(uidPassword && uidPassword->pw_name, "Failed to get username (getpwuid)");

int ret = pam_start(m_sPamModule.c_str(), uidPassword->pw_name, &localConv, &handle);
m_iRet = pam_authenticate(m_pHandle, 0);

if (ret != PAM_SUCCESS) {
m_sConversationState.failText = "pam_start failed";
Debug::log(ERR, "auth: pam_start failed for {}", m_sPamModule);
if (m_iRet != PAM_SUCCESS) {
if (!m_sConversationState.failTextFromPam)
m_sConversationState.failText = "Authentication failed";
Debug::log(ERR, "auth: {} for {}", m_sConversationState.failText, m_sPamModule);
return false;
}

ret = pam_authenticate(handle, 0);
pam_end(handle, ret);
handle = nullptr;
m_iRet = pam_setcred(m_pHandle, PAM_REFRESH_CRED);

m_sConversationState.waitingForPamAuth = false;

if (ret != PAM_SUCCESS) {
if (m_iRet != PAM_SUCCESS) {
if (!m_sConversationState.failTextFromPam)
m_sConversationState.failText = ret == PAM_AUTH_ERR ? "Authentication failed" : "pam_authenticate failed";
m_sConversationState.failText = "Setting credentials failed";
Debug::log(ERR, "auth: {} for {}", m_sConversationState.failText, m_sPamModule);
return false;
}

m_sConversationState.waitingForPamAuth = false;
m_sConversationState.failText = "Successfully authenticated";
Debug::log(LOG, "auth: authenticated for {}", m_sPamModule);
Debug::log(LOG, "auth: {} for {}", m_sConversationState.failText, m_sPamModule);

return true;
}
Expand Down Expand Up @@ -171,15 +163,39 @@ bool CPam::checkWaiting() {
return m_bBlockInput || m_sConversationState.waitingForPamAuth;
}

void CPam::clearHandle() {
if (m_pHandle != nullptr) {
pam_end(m_pHandle, m_iRet);
}

m_iRet = -1;
m_pHandle = nullptr;
}

void CPam::terminate() {
clearHandle();

m_sConversationState.inputSubmittedCondition.notify_all();
if (m_thread.joinable())
m_thread.join();
}

void CPam::resetConversation() {
clearHandle();

m_sConversationState.input = "";
m_sConversationState.waitingForPamAuth = false;
m_sConversationState.inputRequested = false;
m_sConversationState.failTextFromPam = false;

auto uidPassword = getpwuid(getuid());
RASSERT(uidPassword && uidPassword->pw_name, "Failed to get username (getpwuid)");
const pam_conv localConv = {.conv = conv, .appdata_ptr = (void*)&m_sConversationState};

m_iRet = pam_start(m_sPamModule.c_str(), uidPassword->pw_name, &localConv, &m_pHandle);

if (m_iRet != PAM_SUCCESS) {
m_sConversationState.failText = "pam_start failed";
Debug::log(ERR, "auth: {} for {}", m_sConversationState.failText, m_sPamModule);
}
}
4 changes: 4 additions & 0 deletions src/auth/Pam.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <condition_variable>
#include <functional>
#include <thread>
#include <security/pam_appl.h>

class CPam : public IAuthImplementation {
public:
Expand Down Expand Up @@ -38,6 +39,7 @@ class CPam : public IAuthImplementation {
virtual bool checkWaiting();
virtual std::optional<std::string> getLastFailText();
virtual std::optional<std::string> getLastPrompt();
virtual void clearHandle();
virtual void terminate();

private:
Expand All @@ -47,6 +49,8 @@ class CPam : public IAuthImplementation {
bool m_bBlockInput = true;

std::string m_sPamModule;
int m_iRet = -1;
pam_handle_t* m_pHandle = nullptr;

bool auth();
void resetConversation();
Expand Down