Skip to content

Commit

Permalink
Merge branch 'beta' into fix-polkit
Browse files Browse the repository at this point in the history
  • Loading branch information
boltgolt authored Feb 1, 2025
2 parents d1385da + 0a68a4b commit b3e783e
Show file tree
Hide file tree
Showing 16 changed files with 58 additions and 37 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ To install them on Debian/Ubuntu for example:
sudo apt-get update && sudo apt-get install -y \
python3 python3-pip python3-setuptools python3-wheel \
cmake make build-essential \
libpam0g-dev libinih-dev libevdev-dev \
libpam0g-dev libinih-dev libevdev-dev python3-opencv \
python3-dev libopencv-dev
```

Expand Down
2 changes: 1 addition & 1 deletion howdy-gtk/bin/howdy-gtk.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh

env python3 "@script_path@" "$@"
@python_path@ "@script_path@" "$@"
2 changes: 1 addition & 1 deletion howdy-gtk/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ interface_files = files(
install_data(interface_files, install_dir: datadir)

cli_path = join_paths(pysourcesinstalldir, 'init.py')
conf_data = configuration_data({ 'script_path': cli_path })
conf_data = configuration_data({ 'script_path': cli_path, 'python_path': py.full_path() })

bin_name = 'howdy-gtk'
bin = configure_file(
Expand Down
1 change: 0 additions & 1 deletion howdy-gtk/src/init.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
# Opens auth ui if requested, otherwise starts normal ui
import sys

Expand Down
7 changes: 4 additions & 3 deletions howdy-gtk/src/tab_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from i18n import _
from gi.repository import Gtk as gtk
from gi.repository import GObject as gobject


def on_user_change(self, select):
Expand Down Expand Up @@ -73,13 +74,13 @@ def on_model_add(self, button):
dialog = gtk.MessageDialog(parent=self, flags=gtk.DialogFlags.MODAL, buttons=gtk.ButtonsType.NONE)
dialog.set_title(_("Creating Model"))
dialog.props.text = _("Please look directly into the camera")
dialog.get_child().connect("map", lambda w: execute_add(self, dialog, entered_name, self.active_user))
dialog.show_all()

# Wait a bit to allow the user to read the dialog
gobject.timeout_add(600, lambda: execute_add(self, dialog, entered_name))

def execute_add(box, dialog, entered_name, user):

time.sleep(1)
def execute_add(box, dialog, entered_name):

status, output = subprocess.getstatusoutput(["howdy add '" + entered_name + "' -y -U " + box.active_user])

Expand Down
2 changes: 1 addition & 1 deletion howdy/src/bin/howdy.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh

env python3 "@script_path@" "$@"
@python_path@ "@script_path@" "$@"
1 change: 0 additions & 1 deletion howdy/src/cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
# CLI directly called by running the howdy command

# Import required modules
Expand Down
4 changes: 2 additions & 2 deletions howdy/src/cli/snap.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Import required modules
import os
import configparser
import datetime
from datetime import timezone, datetime
import snapshot
import paths_factory
from recorders.video_capture import VideoCapture
Expand Down Expand Up @@ -41,7 +41,7 @@
# Generate a snapshot image from the frames
file = snapshot.generate(frames, [
_("GENERATED SNAPSHOT"),
_("Date: ") + datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S UTC"),
_("Date: ") + datetime.now(timezone.utc).strftime("%Y/%m/%d %H:%M:%S UTC"),
_("Dark threshold config: ") + str(config.getfloat("video", "dark_threshold", fallback=60.0)),
_("Certainty config: ") + str(config.getfloat("video", "certainty", fallback=3.5))
])
Expand Down
5 changes: 2 additions & 3 deletions howdy/src/compare.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
# Compare incoming video with known faces
# Running in a local python instance to get around PATH issues

Expand All @@ -17,7 +16,7 @@
import configparser
import dlib
import cv2
import datetime
from datetime import timezone, datetime
import atexit
import subprocess
import snapshot
Expand Down Expand Up @@ -71,7 +70,7 @@ def make_snapshot(type):
"""Generate snapshot after detection"""
snapshot.generate(snapframes, [
type + _(" LOGIN"),
_("Date: ") + datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S UTC"),
_("Date: ") + datetime.now(timezone.utc).strftime("%Y/%m/%d %H:%M:%S UTC"),
_("Scan time: ") + str(round(time.time() - timings["fr"], 2)) + "s",
_("Frames: ") + str(frames) + " (" + str(round(frames / (time.time() - timings["fr"]), 2)) + "FPS)",
_("Hostname: ") + os.uname().nodename,
Expand Down
7 changes: 4 additions & 3 deletions howdy/src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ if meson.is_subproject()
project('howdy', 'cpp', license: 'MIT', version: 'beta', meson_version: '>= 0.64.0')
endif

py = import('python').find_installation()
py.dependency()

datadir = get_option('prefix') / get_option('datadir') / 'howdy'
py_conf = configuration_data(paths_dict)
py_conf.set('data_dir', datadir)

py = import('python').find_installation(paths_dict.get('python_path'))
py.dependency()

py_paths = configure_file(
input: 'paths.py.in',
output: 'paths.py',
Expand Down Expand Up @@ -153,7 +154,7 @@ install_man('../howdy.1')
# endif

cli_path = join_paths(pysourcesinstalldir, 'cli.py')
conf_data = configuration_data({ 'script_path': cli_path })
conf_data = configuration_data({ 'script_path': cli_path, 'python_path': py.full_path() })

bin_name = 'howdy'
bin = configure_file(
Expand Down
23 changes: 7 additions & 16 deletions howdy/src/pam/main.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include <cerrno>
#include <csignal>
#include <cstdlib>
#include <ostream>

#include <glob.h>
#include <libintl.h>
Expand All @@ -16,22 +15,15 @@
#include <syslog.h>
#include <unistd.h>

#include <atomic>
#include <chrono>
#include <condition_variable>
#include <cstring>
#include <fstream>
#include <functional>
#include <future>
#include <iostream>
#include <iterator>
#include <memory>
#include <mutex>
#include <string>
#include <system_error>
#include <thread>
#include <tuple>
#include <vector>

#include <INIReader.h>

Expand All @@ -42,12 +34,11 @@
#include "enter_device.hh"
#include "main.hh"
#include "optional_task.hh"
#include "paths.hh"
#include <paths.hh>

const auto DEFAULT_TIMEOUT =
std::chrono::duration<int, std::chrono::milliseconds::period>(100);
const auto MAX_RETRIES = 5;
const auto PYTHON_EXECUTABLE = "python3";

#define S(msg) gettext(msg)

Expand Down Expand Up @@ -139,7 +130,7 @@ auto howdy_status(char *username, int status, const INIReader &config,
* @return Returns PAM_AUTHINFO_UNAVAIL if it shouldn't be enabled,
* PAM_SUCCESS otherwise
*/
auto check_enabled(const INIReader &config, const char* username) -> int {
auto check_enabled(const INIReader &config, const char *username) -> int {
// Stop executing if Howdy has been disabled in the config
if (config.GetBoolean("core", "disabled", false)) {
syslog(LOG_INFO, "Skipped authentication, Howdy is disabled");
Expand All @@ -148,8 +139,8 @@ auto check_enabled(const INIReader &config, const char* username) -> int {

// Stop if we're in a remote shell and configured to exit
if (config.GetBoolean("core", "abort_if_ssh", true)) {
if (getenv("SSH_CONNECTION") != nullptr ||
getenv("SSH_CLIENT") != nullptr || getenv("SSHD_OPTS") != nullptr) {
if (checkenv("SSH_CONNECTION") || checkenv("SSH_CLIENT") ||
checkenv("SSH_TTY") || checkenv("SSHD_OPTS")) {
syslog(LOG_INFO, "Skipped authentication, SSH session detected");
return PAM_AUTHINFO_UNAVAIL;
}
Expand Down Expand Up @@ -268,12 +259,12 @@ auto identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
}
}

const char *const args[] = {PYTHON_EXECUTABLE, // NOLINT
const char *const args[] = {PYTHON_EXECUTABLE_PATH, // 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_PATH, nullptr, nullptr,
const_cast<char *const *>(args), nullptr) != 0) {
syslog(LOG_ERR, "Can't spawn the howdy process: %s (%d)", strerror(errno),
errno);
Expand All @@ -290,7 +281,7 @@ auto identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
// zombie process)
optional_task<int> child_task([&] {
int status;
wait(&status);
waitpid(child_pid, &status, 0);
{
std::unique_lock<std::mutex> lock(mutx);
if (confirmation_type == ConfirmationType::Unset) {
Expand Down
27 changes: 27 additions & 0 deletions howdy/src/pam/main.hh
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#ifndef MAIN_H_
#define MAIN_H_

#include <cstring>
#include <string>
#include <unistd.h>

enum class ConfirmationType { Unset, Howdy, Pam };

Expand Down Expand Up @@ -29,4 +31,29 @@ inline auto get_workaround(const std::string &workaround) -> Workaround {
return Workaround::Off;
}

/**
* Check if an environment variable exists either in the environ array or using
* getenv.
* @param name The name of the environment variable.
* @return The value of the environment variable or nullptr if it doesn't exist
* or environ is nullptr.
* @note This function was created because `getenv` wasn't working properly in
* some contexts (like sudo).
*/
auto checkenv(const char *name) -> bool {
if (std::getenv(name) != nullptr) {
return true;
}

auto len = strlen(name);

for (char **env = environ; *env != nullptr; env++) {
if (strncmp(*env, name, len) == 0) {
return true;
}
}

return false;
}

#endif // MAIN_H_
3 changes: 2 additions & 1 deletion howdy/src/pam/paths.hh.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const auto COMPARE_PROCESS_PATH = "@compare_script_path@";
const auto CONFIG_FILE_PATH = "@config_file_path@";
const auto USER_MODELS_DIR = "@user_models_dir@";
const auto USER_MODELS_DIR = "@user_models_dir@";
const auto PYTHON_EXECUTABLE_PATH = "@python_path@";
4 changes: 2 additions & 2 deletions howdy/src/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Import modules
import cv2
import os
import datetime
from datetime import timezone, datetime
import numpy as np
import paths_factory

Expand Down Expand Up @@ -53,7 +53,7 @@ def generate(frames, text_lines):
os.makedirs(paths_factory.snapshots_dir_path())

# Generate a filename based on the current time
filename = datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%S.jpg")
filename = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%S.jpg")
filepath = paths_factory.snapshot_path(filename)
# Write the image to that file
cv2.imwrite(filepath, snap)
Expand Down
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ dlibdatadir = get_option('dlib_data_dir') != '' ? get_option('dlib_data_dir') :
confdir = get_option('config_dir') != '' ? get_option('config_dir') : join_paths(get_option('prefix'), get_option('sysconfdir'), 'howdy')
usermodelsdir = get_option('user_models_dir') != '' ? get_option('user_models_dir') : join_paths(confdir, 'models')
logpath = get_option('log_path')
pythonpath = get_option('python_path')

config_path = join_paths(confdir, 'config.ini')

Expand All @@ -12,6 +13,7 @@ paths_dict = {
'dlib_data_dir': dlibdatadir,
'user_models_dir': usermodelsdir,
'log_path': logpath,
'python_path': pythonpath
}

# We need to keep this order beause howdy-gtk defines the gtk script path which is used later in howdy
Expand Down
3 changes: 2 additions & 1 deletion meson.options
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ option('log_path', type: 'string', value: '/var/log/howdy', description: 'Set th
option('install_in_site_packages', type: 'boolean', value: false, description: 'Install howdy python files in site packages')
option('py_sources_dir', type: 'string', value: '', description: 'Set the python sources directory')
option('install_pam_config', type: 'boolean', value: false, description: 'Install pam config file (for Debian/Ubuntu)')
option('with_polkit', type: 'boolean', value: false, description: 'Install polkit policy config file')
option('python_path', type: 'string', value: '/usr/bin/python', description: 'Set the path to the python executable')
option('with_polkit', type: 'boolean', value: false, description: 'Install polkit policy config file')

0 comments on commit b3e783e

Please sign in to comment.