Skip to content

Commit

Permalink
Change the display order of PAM messages
Browse files Browse the repository at this point in the history
  - do not show a message if the face model is not found

  - show a message if the user could not be recognized

  - show prompt if face model found (and enabled option)

  - enable the "detection_notice" option by default as this will only be
    shown to users who created the face model
  • Loading branch information
Gliese852 committed Aug 8, 2023
1 parent c17a834 commit 1b4f1c2
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 9 deletions.
5 changes: 5 additions & 0 deletions howdy/src/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ def send_to_ui(type, message):
if len(models) < 1:
exit(10)

# notify the PAM module so that it issues a message
sys.stdout.flush()
print("HAS_MODEL")
sys.stdout.flush()

# Read config from disk
config = configparser.ConfigParser()
config.read(PATH + "/config.ini")
Expand Down
2 changes: 1 addition & 1 deletion howdy/src/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

[core]
# Print that face detection is being attempted
detection_notice = false
detection_notice = true

# Print that face detection has timed out
timeout_notice = true
Expand Down
40 changes: 32 additions & 8 deletions howdy/src/pam/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ auto howdy_error(int status,

switch (status) {
case CompareError::NO_FACE_MODEL:
conv_function(PAM_ERROR_MSG, S("There is no face model known"));
syslog(LOG_NOTICE, "Failure, no face model known");
break;
case CompareError::TIMEOUT_REACHED:
conv_function(PAM_ERROR_MSG, S("Failure, timeout reached"));
syslog(LOG_ERR, "Failure, timeout reached");
break;
case CompareError::ABORT:
Expand Down Expand Up @@ -244,12 +244,7 @@ auto identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
textdomain(GETTEXT_PACKAGE);

// If enabled, send a notice to the user that facial login is being attempted
if (config.GetBoolean("core", "detection_notice", false)) {
if ((conv_function(PAM_TEXT_INFO, S("Attempting facial authentication"))) !=
PAM_SUCCESS) {
syslog(LOG_ERR, "Failed to send detection notice");
}
}
bool detection_notice = config.GetBoolean("core", "detection_notice", true);

// Get the username from PAM, needed to match correct face model
char *username = nullptr;
Expand All @@ -259,18 +254,46 @@ auto identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
return pam_res;
}

int conv_pipe[2];

if (pipe (conv_pipe)) {
syslog(LOG_ERR, "Pipe failed.");
return PAM_SYSTEM_ERR;
}

posix_spawn_file_actions_t action;
posix_spawn_file_actions_init(&action);
posix_spawn_file_actions_addclose(&action, conv_pipe[0]);
posix_spawn_file_actions_adddup2(&action, conv_pipe[1], 1);
posix_spawn_file_actions_addclose(&action, conv_pipe[1]);

const char *const args[] = {PYTHON_EXECUTABLE, // NOLINT
COMPARE_PROCESS_PATH, username, nullptr};
pid_t child_pid;

// Start the python subprocess
if (posix_spawnp(&child_pid, PYTHON_EXECUTABLE, nullptr, nullptr,
if (posix_spawnp(&child_pid, PYTHON_EXECUTABLE, &action, nullptr,
const_cast<char *const *>(args), nullptr) != 0) {
syslog(LOG_ERR, "Can't spawn the howdy process: %s (%d)", strerror(errno),
errno);
return PAM_SYSTEM_ERR;
}

// show the PAM message from the compare script
optional_task<void> child_conv([&] {
char buffer[100];
while(read(conv_pipe[0], buffer, 100)) {
if (!strncmp(buffer, "HAS_MODEL", 9) && detection_notice) {
if ((conv_function(PAM_TEXT_INFO,
S("Attempting facial authentication"))) !=
PAM_SUCCESS) {
syslog(LOG_ERR, "Failed to send detection notice");
}
}
}
});
child_conv.activate();

// NOTE: We should replace mutex and condition_variable by atomic wait, but
// it's too recent (C++20)
std::mutex mutx;
Expand Down Expand Up @@ -347,6 +370,7 @@ auto identify(pam_handle_t *pamh, int flags, int argc, const char **argv,

// The compare process has finished its execution
child_task.stop(false);
child_conv.stop(true);

// Get python process status code
int status = child_task.get();
Expand Down

0 comments on commit 1b4f1c2

Please sign in to comment.