From face49317c6cf5aca02c987c66c876ce3f9122cf Mon Sep 17 00:00:00 2001 From: John Turner Date: Thu, 31 Jul 2025 00:36:16 -0400 Subject: INSERT OR IGNORE was not behaving as expected --- src/pam_xdg.cpp | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/pam_xdg.cpp b/src/pam_xdg.cpp index b397024..440b29c 100644 --- a/src/pam_xdg.cpp +++ b/src/pam_xdg.cpp @@ -29,7 +29,7 @@ void open_db(sqlite3 **db, const std::filesystem::path &path, int flags) { void init_db(sqlite3 *db) { auto rc = sqlite3_exec( - db, "CREATE TABLE IF NOT EXISTS SESSIONS(USERNAME TEXT, LOGINS INT)", + db, "CREATE TABLE SESSIONS(USERNAME TEXT, LOGINS INT)", nullptr, nullptr, nullptr); if (rc != SQLITE_OK) { @@ -39,8 +39,7 @@ void init_db(sqlite3 *db) { } void init_session(sqlite3 *db, std::string_view username) { - const auto *query = - "INSERT OR IGNORE INTO SESSIONS(USERNAME, LOGINS) VALUES(?, 0)"; + const auto *query = "INSERT INTO SESSIONS(USERNAME, LOGINS) VALUES(?, 0)"; sqlite3_stmt *stmt; int rc; @@ -159,6 +158,39 @@ bool is_logged_in(sqlite3 *db, std::string_view username) { return (logins > 0); } +bool has_session(sqlite3 *db, std::string_view username) { + const auto *query = "SELECT COUNT(*) FROM SESSIONS WHERE USERNAME=?"; + sqlite3_stmt *stmt; + int rc; + + rc = sqlite3_prepare_v2(db, query, -1, &stmt, nullptr); + + if (rc != SQLITE_OK) { + throw std::runtime_error( + std::format("failed to prepare stmt: {}", sqlite3_errmsg(db))); + } + + rc = sqlite3_bind_text(stmt, 1, username.data(), username.length(), nullptr); + + if (rc != SQLITE_OK) { + sqlite3_finalize(stmt); + throw std::runtime_error(std::string("failed to bind text")); + } + + rc = sqlite3_step(stmt); + + if (rc != SQLITE_ROW) { + sqlite3_finalize(stmt); + throw std::runtime_error(std::string("failed to step stmt")); + } + + int count = sqlite3_column_int(stmt, 0); + + sqlite3_finalize(stmt); + + return (count > 0); +} + void touch(const std::filesystem::path &path, int mode) { auto fd = creat(path.c_str(), mode); @@ -226,7 +258,9 @@ extern "C" int pam_sm_open_session(pam_handle_t *pamh, pam_xdg::open_db(&db, pam_xdg::DB_PATH, SQLITE_OPEN_READWRITE); } - pam_xdg::init_session(db, username); + if (!pam_xdg::has_session(db, username)) { + pam_xdg::init_session(db, username); + } if (!pam_xdg::is_logged_in(db, username)) { if (!std::filesystem::exists(pam_xdg::USER_DIRECTORY)) { -- cgit v1.2.3