Skip to content

Commit

Permalink
auth: fixup prompt and fail substitution
Browse files Browse the repository at this point in the history
BREAKING:
- Removed $PROMPT variable. Either use $PAMPROMPT or $FPRINTPROMPT.
- Removed $FPRINTMESSAGE. Use $FPRINTPROMPT instead. There is also
  $FPRINTFAIL.
  • Loading branch information
PaideiaDilemma committed Jan 7, 2025
1 parent de844d3 commit dccf1f7
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 118 deletions.
37 changes: 14 additions & 23 deletions src/auth/Auth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,8 @@ bool CAuth::checkWaiting() {
return false;
}

std::string CAuth::getInlineFeedback() {
std::optional<std::string> firstFeedback = std::nullopt;
for (const auto& i : m_vImpls) {
const auto FEEDBACK = (m_bDisplayFailText) ? i->getLastFailText() : i->getLastPrompt();
if (!FEEDBACK.has_value())
continue;

if (!firstFeedback.has_value())
firstFeedback = FEEDBACK;

if (i->getImplType() == m_eLastActiveImpl)
return FEEDBACK.value();
}

return firstFeedback.value_or("Ups, no authentication feedack");
const std::string& CAuth::getCurrentFailText() {
return m_sCurrentFail.failText;
}

std::optional<std::string> CAuth::getFailText(eAuthImplementations implType) {
Expand All @@ -73,6 +60,10 @@ std::optional<std::string> CAuth::getPrompt(eAuthImplementations implType) {
return std::nullopt;
}

size_t CAuth::getFailedAttempts() {
return m_sCurrentFail.failedAttempts;
}

std::shared_ptr<IAuthImplementation> CAuth::getImpl(eAuthImplementations implType) {
for (const auto& i : m_vImpls) {
if (i->getImplType() == implType)
Expand All @@ -89,11 +80,10 @@ void CAuth::terminate() {
}

static void passwordFailCallback(std::shared_ptr<CTimer> self, void* data) {
g_pAuth->m_bDisplayFailText = true;

g_pHyprlock->clearPasswordBuffer();
g_pAuth->m_iFailedAttempts++;
Debug::log(LOG, "Failed attempts: {}", g_pAuth->m_iFailedAttempts);

g_pAuth->m_bDisplayFailText = true;
g_pHyprlock->enqueueForceUpdateTimers();

g_pHyprlock->renderAllOutputs();
Expand All @@ -103,14 +93,15 @@ static void passwordUnlockCallback(std::shared_ptr<CTimer> self, void* data) {
g_pHyprlock->unlock();
}

void CAuth::enqueueFail() {
void CAuth::enqueueFail(const std::string& failText, eAuthImplementations implType) {
m_sCurrentFail.failText = failText;
m_sCurrentFail.failedAttempts++;

Debug::log(LOG, "Failed attempts: {}", m_sCurrentFail.failedAttempts);

g_pHyprlock->addTimer(std::chrono::milliseconds(0), passwordFailCallback, nullptr);
}

void CAuth::enqueueUnlock() {
g_pHyprlock->addTimer(std::chrono::milliseconds(0), passwordUnlockCallback, nullptr);
}

void CAuth::postActivity(eAuthImplementations implType) {
m_eLastActiveImpl = implType;
}
29 changes: 15 additions & 14 deletions src/auth/Auth.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,35 @@ class CAuth {
public:
CAuth();

void start();
void start();

void submitInput(const std::string& input);
bool checkWaiting();
void submitInput(const std::string& input);
bool checkWaiting();

// Used by the PasswordInput field. We are constraint to a single line for the authentication feedback there.
// Based on m_bDisplayFailText, this will return either the fail text or the prompt.
// Based on m_eLastActiveImpl, it will select the implementation.
std::string getInlineFeedback();
const std::string& getCurrentFailText();

std::optional<std::string> getFailText(eAuthImplementations implType);
std::optional<std::string> getPrompt(eAuthImplementations implType);
size_t getFailedAttempts();

std::shared_ptr<IAuthImplementation> getImpl(eAuthImplementations implType);

void terminate();

// Should only be set via the main thread
bool m_bDisplayFailText = false;
size_t m_iFailedAttempts = 0;
void enqueueUnlock();
void enqueueFail(const std::string& failText, eAuthImplementations implType);

void enqueueUnlock();
void enqueueFail();
void postActivity(eAuthImplementations implType);
// Should only be set via the main thread
bool m_bDisplayFailText = false;

private:
struct {
std::string failText = "";
eAuthImplementations failSource = AUTH_IMPL_PAM;
size_t failedAttempts = 0;
} m_sCurrentFail;

std::vector<std::shared_ptr<IAuthImplementation>> m_vImpls;
std::optional<eAuthImplementations> m_eLastActiveImpl = std::nullopt;
};

inline std::unique_ptr<CAuth> g_pAuth;
57 changes: 19 additions & 38 deletions src/auth/Fingerprint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,7 @@ bool CFingerprint::createDeviceProxy() {
bool isPresent = presentVariant.get<bool>();
if (!isPresent)
return;
m_sPrompt = m_sFingerprintPresent;
m_sFailureReason = "";
m_sPrompt = m_sFingerprintPresent;
g_pHyprlock->enqueueForceUpdateTimers();
} catch (std::out_of_range& e) {}
});
Expand All @@ -153,7 +152,6 @@ bool CFingerprint::createDeviceProxy() {
}

void CFingerprint::handleVerifyStatus(const std::string& result, bool done) {
g_pAuth->postActivity(AUTH_IMPL_FINGERPRINT);
Debug::log(LOG, "fprint: handling status {}", result);
auto matchResult = s_mapStringToTestType[result];
bool authenticated = false;
Expand All @@ -165,60 +163,47 @@ void CFingerprint::handleVerifyStatus(const std::string& result, bool done) {
case MATCH_NO_MATCH:
stopVerify();
if (m_sDBUSState.retries >= 3) {
m_sPrompt = "";
m_sFailureReason = "Fingerprint auth disabled (too many failed attempts)";
} else {
done = false;
done = false;
static const auto RETRYDELAY = **(Hyprlang::INT* const*)(g_pConfigManager->getValuePtr("auth:fingerprint:retry_delay"));
g_pHyprlock->addTimer(
std::chrono::milliseconds(RETRYDELAY),
[](std::shared_ptr<CTimer> self, void* data) {
((CFingerprint*)data)->startVerify(true);
},
this);
g_pHyprlock->addTimer(std::chrono::milliseconds(RETRYDELAY), [](std::shared_ptr<CTimer> self, void* data) { ((CFingerprint*)data)->startVerify(true); }, this);
m_sFailureReason = "Fingerprint did not match";
}
break;
case MATCH_UNKNOWN_ERROR:
stopVerify();
m_sPrompt = "";
m_sFailureReason = "Fingerprint auth disabled (unknown error)";
break;
case MATCH_MATCHED:
stopVerify();
m_sPrompt = "";
m_sFailureReason = "";
authenticated = true;
authenticated = true;
g_pAuth->enqueueUnlock();
break;
case MATCH_RETRY:
retry = true;
m_sPrompt = "Please retry fingerprint scan";
m_sFailureReason = "";
retry = true;
m_sPrompt = "Please retry fingerprint scan";
break;
case MATCH_SWIPE_TOO_SHORT:
retry = true;
m_sPrompt = "Swipe too short - try again";
m_sFailureReason = "";
retry = true;
m_sPrompt = "Swipe too short - try again";
break;
case MATCH_FINGER_NOT_CENTERED:
retry = true;
m_sPrompt = "Finger not centered - try again";
m_sFailureReason = "";
retry = true;
m_sPrompt = "Finger not centered - try again";
break;
case MATCH_REMOVE_AND_RETRY:
retry = true;
m_sPrompt = "Remove your finger and try again";
m_sFailureReason = "";
retry = true;
m_sPrompt = "Remove your finger and try again";
break;
case MATCH_DISCONNECTED:
m_sPrompt = "";
m_sFailureReason = "Fingerprint device disconnected";
m_sDBUSState.abort = true;
break;
}

if (!authenticated && !retry)
g_pAuth->enqueueFail();
g_pAuth->enqueueFail(m_sFailureReason, AUTH_IMPL_FINGERPRINT);

if (done || m_sDBUSState.abort)
m_sDBUSState.done = true;
Expand Down Expand Up @@ -248,20 +233,16 @@ void CFingerprint::startVerify(bool isRetry) {
m_sDBUSState.device->callMethodAsync("VerifyStart").onInterface(DEVICE).withArguments(finger).uponReplyInvoke([this, isRetry](std::optional<sdbus::Error> e) {
if (e) {
Debug::log(WARN, "fprint: could not start verifying, {}", e->what());
if (isRetry) {
m_sPrompt = "";
if (isRetry)
m_sFailureReason = "Fingerprint auth disabled (failed to restart)";
}

} else {
Debug::log(LOG, "fprint: started verifying");
if (isRetry) {
m_sDBUSState.retries++;
m_sPrompt = "Could not match fingerprint. Try again.";
m_sFailureReason = "";
} else {
m_sPrompt = m_sFingerprintReady;
m_sFailureReason = "";
}
m_sPrompt = "Could not match fingerprint. Try again.";
} else
m_sPrompt = m_sFingerprintReady;
}
g_pHyprlock->enqueueForceUpdateTimers();
});
Expand Down
4 changes: 1 addition & 3 deletions src/auth/Pam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ void CPam::init() {
return;

if (!AUTHENTICATED)
g_pAuth->enqueueFail();
g_pAuth->enqueueFail(m_sConversationState.failText, AUTH_IMPL_PAM);
else {
g_pAuth->enqueueUnlock();
return;
Expand Down Expand Up @@ -124,7 +124,6 @@ bool CPam::auth() {
handle = nullptr;

m_sConversationState.waitingForPamAuth = false;
g_pAuth->postActivity(AUTH_IMPL_PAM);

if (ret != PAM_SUCCESS) {
if (!m_sConversationState.failTextFromPam)
Expand Down Expand Up @@ -156,7 +155,6 @@ void CPam::waitForInput() {
}

void CPam::handleInput(const std::string& input) {
g_pAuth->postActivity(AUTH_IMPL_PAM);
std::unique_lock<std::mutex> lk(m_sConversationState.inputMutex);

if (!m_sConversationState.inputRequested)
Expand Down
48 changes: 26 additions & 22 deletions src/renderer/widgets/IWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ int IWidget::roundingForBorderBox(const CBox& borderBox, int roundingConfig, int

static void replaceAllAttempts(std::string& str) {

const size_t ATTEMPTS = g_pAuth->m_iFailedAttempts;
const size_t ATTEMPTS = g_pAuth->getFailedAttempts();
const std::string STR = std::to_string(ATTEMPTS);
size_t pos = 0;

Expand Down Expand Up @@ -118,16 +118,14 @@ static void replaceAllLayout(std::string& str) {
}
}

static bool logMissingTzOnce = true;
static bool logMissingTzOnce = true;
static std::chrono::hh_mm_ss<std::chrono::system_clock::duration> getTime() {
const std::chrono::time_zone* pCurrentTz = nullptr;
try {
auto name = std::getenv("TZ");
if (name)
pCurrentTz = std::chrono::locate_zone(name);
} catch (std::runtime_error&) {
Debug::log(WARN, "Invalid TZ value. Falling back to current timezone!");
}
} catch (std::runtime_error&) { Debug::log(WARN, "Invalid TZ value. Falling back to current timezone!"); }

if (!pCurrentTz)
pCurrentTz = std::chrono::current_zone();
Expand All @@ -150,15 +148,15 @@ static std::chrono::hh_mm_ss<std::chrono::system_clock::duration> getTime() {

static std::string getTime24h() {
const auto HHMMSS = getTime();
const auto HRS = HHMMSS.hours().count();
const auto MINS = HHMMSS.minutes().count();
const auto HRS = HHMMSS.hours().count();
const auto MINS = HHMMSS.minutes().count();
return (HRS < 10 ? "0" : "") + std::to_string(HRS) + ":" + (MINS < 10 ? "0" : "") + std::to_string(MINS);
}

static std::string getTime12h() {
const auto HHMMSS = getTime();
const auto HRS = HHMMSS.hours().count();
const auto MINS = HHMMSS.minutes().count();
const auto HRS = HHMMSS.hours().count();
const auto MINS = HHMMSS.minutes().count();
return (HRS == 12 || HRS == 0 ? "12" : (HRS % 12 < 10 ? "0" : "") + std::to_string(HRS % 12)) + ":" + (MINS < 10 ? "0" : "") + std::to_string(MINS) +
(HRS < 12 ? " AM" : " PM");
}
Expand Down Expand Up @@ -190,31 +188,37 @@ IWidget::SFormatResult IWidget::formatString(std::string in) {
result.updateEveryMs = result.updateEveryMs != 0 && result.updateEveryMs < 1000 ? result.updateEveryMs : 1000;
}

if (in.contains("$FAIL")) {
const auto FAIL = g_pAuth->getFailText(AUTH_IMPL_PAM);
replaceInString(in, "$FAIL", FAIL.value_or(""));
if (in.contains("$ATTEMPTS")) {
replaceAllAttempts(in);
result.allowForceUpdate = true;
}

if (in.contains("$PROMPT")) {
const auto PROMPT = g_pAuth->getPrompt(AUTH_IMPL_PAM);
replaceInString(in, "$PROMPT", PROMPT.value_or(""));
if (in.contains("$LAYOUT")) {
replaceAllLayout(in);
result.allowForceUpdate = true;
}

if (in.contains("$ATTEMPTS")) {
replaceAllAttempts(in);
if (in.contains("$FAIL")) {
const auto FAIL = g_pAuth->getCurrentFailText();
replaceInString(in, "$FAIL", FAIL);
result.allowForceUpdate = true;
}

if (in.contains("$LAYOUT")) {
replaceAllLayout(in);
if (in.contains("$PAMFAIL")) {
const auto FAIL = g_pAuth->getFailText(AUTH_IMPL_PAM);
replaceInString(in, "$PAMFAIL", FAIL.value_or(""));
result.allowForceUpdate = true;
}

if (in.contains("$PAMPROMPT")) {
const auto PROMPT = g_pAuth->getPrompt(AUTH_IMPL_PAM);
replaceInString(in, "$PAMPROMPT", PROMPT.value_or(""));
result.allowForceUpdate = true;
}

if (in.contains("$FPRINTMESSAGE")) {
const auto FPRINTMESSAGE = g_pAuth->getFailText(AUTH_IMPL_FINGERPRINT);
replaceInString(in, "$FPRINTMESSAGE", FPRINTMESSAGE.value_or(""));
if (in.contains("$FPRINTFAIL")) {
const auto FPRINTFAIL = g_pAuth->getFailText(AUTH_IMPL_FINGERPRINT);
replaceInString(in, "$FPRINTFAIL", FPRINTFAIL.value_or(""));
result.allowForceUpdate = true;
}

Expand Down
Loading

0 comments on commit dccf1f7

Please sign in to comment.