Small fixes to update PR
This commit is contained in:
parent
373f002f96
commit
024451fd05
8 changed files with 25 additions and 167 deletions
|
|
@ -64,6 +64,8 @@ class OnboardingWindow(gtk.Window):
|
||||||
self.execute_slide5()
|
self.execute_slide5()
|
||||||
|
|
||||||
def execute_slide1(self):
|
def execute_slide1(self):
|
||||||
|
conf_path = "/etc/howdy"
|
||||||
|
|
||||||
self.downloadoutputlabel = self.builder.get_object("downloadoutputlabel")
|
self.downloadoutputlabel = self.builder.get_object("downloadoutputlabel")
|
||||||
eventbox = self.builder.get_object("downloadeventbox")
|
eventbox = self.builder.get_object("downloadeventbox")
|
||||||
eventbox.modify_bg(gtk.StateType.NORMAL, gdk.Color(red=0, green=0, blue=0))
|
eventbox.modify_bg(gtk.StateType.NORMAL, gdk.Color(red=0, green=0, blue=0))
|
||||||
|
|
@ -74,10 +76,10 @@ class OnboardingWindow(gtk.Window):
|
||||||
else:
|
else:
|
||||||
lib_site = None
|
lib_site = None
|
||||||
|
|
||||||
if lib_site:
|
if lib_site is None:
|
||||||
conf_path = lib_site + "/security/howdy"
|
self.downloadoutputlabel.set_text(_("Unable to find Howdy's installation location"))
|
||||||
else:
|
return
|
||||||
conf_path = "/etc/howdy"
|
|
||||||
|
|
||||||
if os.path.exists(conf_path + "/dlib-data/shape_predictor_5_face_landmarks.dat"):
|
if os.path.exists(conf_path + "/dlib-data/shape_predictor_5_face_landmarks.dat"):
|
||||||
self.downloadoutputlabel.set_text(_("Datafiles have already been downloaded!\nClick Next to continue"))
|
self.downloadoutputlabel.set_text(_("Datafiles have already been downloaded!\nClick Next to continue"))
|
||||||
|
|
|
||||||
|
|
@ -106,11 +106,6 @@ if "upgrade" in sys.argv:
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
log("Downloading and unpacking data files")
|
|
||||||
|
|
||||||
# Run the bash script to download and unpack the .dat files needed
|
|
||||||
handleStatus(subprocess.call(["./install.sh"], shell=True, cwd="/etc/howdy/dlib-data"))
|
|
||||||
|
|
||||||
log("Downloading dlib")
|
log("Downloading dlib")
|
||||||
|
|
||||||
dlib_archive = "/tmp/v19.16.tar.gz"
|
dlib_archive = "/tmp/v19.16.tar.gz"
|
||||||
|
|
|
||||||
|
|
@ -9,24 +9,17 @@ import sys
|
||||||
if "upgrade" in sys.argv:
|
if "upgrade" in sys.argv:
|
||||||
# Try to copy the config file as a backup
|
# Try to copy the config file as a backup
|
||||||
try:
|
try:
|
||||||
if os.path.exists("/lib/security/howdy/config.ini") and not os.path.exists("/etc/howdy/config.ini"):
|
# Try to copy the new location first
|
||||||
subprocess.call(["cp /lib/security/howdy/config.ini /tmp/howdy_config_backup_v" + sys.argv[2] + ".ini"], shell=True)
|
if os.path.exists("/etc/howdy/config.ini"):
|
||||||
else os.path.exists("/etc/howdy/config.ini"):
|
|
||||||
subprocess.call(["cp /etc/howdy/config.ini /tmp/howdy_config_backup_v" + sys.argv[2] + ".ini"], shell=True)
|
subprocess.call(["cp /etc/howdy/config.ini /tmp/howdy_config_backup_v" + sys.argv[2] + ".ini"], shell=True)
|
||||||
|
# If that does not exist, try copying the old location
|
||||||
|
else:
|
||||||
|
subprocess.call(["cp /lib/security/howdy/config.ini /tmp/howdy_config_backup_v" + sys.argv[2] + ".ini"], shell=True)
|
||||||
|
|
||||||
# Let the user know so he knows where to look on a failed install
|
# Let the user know so he knows where to look on a failed install
|
||||||
print("Backup of Howdy config file created in /tmp/howdy_config_backup_v" + sys.argv[2] + ".ini")
|
print("Backup of Howdy config file created in /tmp/howdy_config_backup_v" + sys.argv[2] + ".ini")
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
try:
|
print("Could not make an backup of old Howdy config file")
|
||||||
if os.path.exists("/lib/security/howdy/config.ini") and not os.path.exists("/etc/howdy/config.ini"):
|
|
||||||
subprocess.call(["cp /lib/security/howdy/config.ini /tmp/howdy_config_backup_v" + sys.argv[2] + ".ini"], shell=True)
|
|
||||||
else os.path.exists("/etc/howdy/config.ini"):
|
|
||||||
subprocess.call(["cp /etc/howdy/config.ini /tmp/howdy_config_backup_v" + sys.argv[2] + ".ini"], shell=True)
|
|
||||||
|
|
||||||
# Let the user know so he knows where to look on a failed install
|
|
||||||
print("Backup of Howdy config file created in /tmp/howdy_config_backup_v" + sys.argv[2] + ".ini")
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
print("Could not make an backup of old Howdy config file")
|
|
||||||
|
|
||||||
# Don't continue setup when we're just upgrading
|
# Don't continue setup when we're just upgrading
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
|
||||||
|
|
@ -26,15 +26,13 @@ except ImportError as err:
|
||||||
# OpenCV needs to be imported after dlib
|
# OpenCV needs to be imported after dlib
|
||||||
import cv2
|
import cv2
|
||||||
|
|
||||||
# Get the absolute path to the current directory
|
# Define the absolute path to the config directory
|
||||||
path = os.path.abspath(__file__ + "/..")
|
|
||||||
config_path = "/etc/howdy"
|
config_path = "/etc/howdy"
|
||||||
models_path = "/etc/howdy/models"
|
|
||||||
|
|
||||||
# Test if at lest 1 of the data files is there and abort if it's not
|
# Test if at lest 1 of the data files is there and abort if it's not
|
||||||
if not os.path.isfile(path + "/../dlib-data/shape_predictor_5_face_landmarks.dat"):
|
if not os.path.isfile(config_path + "/dlib-data/shape_predictor_5_face_landmarks.dat"):
|
||||||
print(_("Data files have not been downloaded, please run the following commands:"))
|
print(_("Data files have not been downloaded, please run the following commands:"))
|
||||||
print("\n\tcd " + os.path.realpath(path + "/../dlib-data"))
|
print("\n\tcd " + config_path + "/dlib-data")
|
||||||
print("\tsudo ./install.sh\n")
|
print("\tsudo ./install.sh\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
@ -44,23 +42,23 @@ config.read(config_path + "/config.ini")
|
||||||
|
|
||||||
use_cnn = config.getboolean("core", "use_cnn", fallback=False)
|
use_cnn = config.getboolean("core", "use_cnn", fallback=False)
|
||||||
if use_cnn:
|
if use_cnn:
|
||||||
face_detector = dlib.cnn_face_detection_model_v1(path + "/../dlib-data/mmod_human_face_detector.dat")
|
face_detector = dlib.cnn_face_detection_model_v1(config_path + "/dlib-data/mmod_human_face_detector.dat")
|
||||||
else:
|
else:
|
||||||
face_detector = dlib.get_frontal_face_detector()
|
face_detector = dlib.get_frontal_face_detector()
|
||||||
|
|
||||||
pose_predictor = dlib.shape_predictor(path + "/../dlib-data/shape_predictor_5_face_landmarks.dat")
|
pose_predictor = dlib.shape_predictor(config_path + "/dlib-data/shape_predictor_5_face_landmarks.dat")
|
||||||
face_encoder = dlib.face_recognition_model_v1(path + "/../dlib-data/dlib_face_recognition_resnet_model_v1.dat")
|
face_encoder = dlib.face_recognition_model_v1(config_path + "/dlib-data/dlib_face_recognition_resnet_model_v1.dat")
|
||||||
|
|
||||||
user = builtins.howdy_user
|
user = builtins.howdy_user
|
||||||
# The permanent file to store the encoded model in
|
# The permanent file to store the encoded model in
|
||||||
enc_file = models_path + "/" + user + ".dat"
|
enc_file = config_path + "/models/" + user + ".dat"
|
||||||
# Known encodings
|
# Known encodings
|
||||||
encodings = []
|
encodings = []
|
||||||
|
|
||||||
# Make the ./models folder if it doesn't already exist
|
# Make the ./models folder if it doesn't already exist
|
||||||
if not os.path.exists(models_path):
|
if not os.path.exists(config_path + "/models"):
|
||||||
print(_("No face model folder found, creating one"))
|
print(_("No face model folder found, creating one"))
|
||||||
os.makedirs(models_path)
|
os.makedirs(config_path + "/models")
|
||||||
|
|
||||||
# To try read a premade encodings file if it exists
|
# To try read a premade encodings file if it exists
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ if not builtins.howdy_args.y:
|
||||||
|
|
||||||
# Abort if they don't answer y or Y
|
# Abort if they don't answer y or Y
|
||||||
if (ans.lower() != "y"):
|
if (ans.lower() != "y"):
|
||||||
print(_('\nInerpeting as a "NO", aborting'))
|
print(_('\nInterpreting as a "NO", aborting'))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Delete otherwise
|
# Delete otherwise
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ for enc in encodings:
|
||||||
# Format the time as ISO in the local timezone
|
# Format the time as ISO in the local timezone
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(enc["time"])), end="")
|
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(enc["time"])), end="")
|
||||||
|
|
||||||
# Seperate with commas again for machines, spaces otherwise
|
# Separate with commas again for machines, spaces otherwise
|
||||||
print("," if builtins.howdy_args.plain else " ", end="")
|
print("," if builtins.howdy_args.plain else " ", end="")
|
||||||
|
|
||||||
# End with the label
|
# End with the label
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ face_encoder = None
|
||||||
|
|
||||||
# Try to load the face model from the models folder
|
# Try to load the face model from the models folder
|
||||||
try:
|
try:
|
||||||
models = json.load(open("/etc/howdy/models/" + user + ".dat"))
|
models = json.load(open(PATH + "/models/" + user + ".dat"))
|
||||||
|
|
||||||
for model in models:
|
for model in models:
|
||||||
encodings += model["data"]
|
encodings += model["data"]
|
||||||
|
|
@ -142,7 +142,7 @@ if len(models) < 1:
|
||||||
|
|
||||||
# Read config from disk
|
# Read config from disk
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read("/etc/howdy/config.ini")
|
config.read(PATH + "/config.ini")
|
||||||
|
|
||||||
# Get all config values needed
|
# Get all config values needed
|
||||||
use_cnn = config.getboolean("core", "use_cnn", fallback=False)
|
use_cnn = config.getboolean("core", "use_cnn", fallback=False)
|
||||||
|
|
|
||||||
130
howdy/src/pam.py
130
howdy/src/pam.py
|
|
@ -1,130 +0,0 @@
|
||||||
# PAM interface in python, launches compare.py
|
|
||||||
|
|
||||||
# Import required modules
|
|
||||||
import subprocess
|
|
||||||
import os
|
|
||||||
import glob
|
|
||||||
import syslog
|
|
||||||
|
|
||||||
# pam-python is running python 2, so we use the old module here
|
|
||||||
import ConfigParser
|
|
||||||
|
|
||||||
# Read config from disk
|
|
||||||
config = ConfigParser.ConfigParser()
|
|
||||||
config.read(os.path.dirname("/etc/howdy") + "/config.ini")
|
|
||||||
|
|
||||||
|
|
||||||
def doAuth(pamh):
|
|
||||||
"""Starts authentication in a seperate process"""
|
|
||||||
|
|
||||||
# Abort if Howdy is disabled
|
|
||||||
if config.getboolean("core", "disabled"):
|
|
||||||
return pamh.PAM_AUTHINFO_UNAVAIL
|
|
||||||
|
|
||||||
# Abort if we're in a remote SSH env
|
|
||||||
if config.getboolean("core", "ignore_ssh"):
|
|
||||||
if "SSH_CONNECTION" in os.environ or "SSH_CLIENT" in os.environ or "SSHD_OPTS" in os.environ:
|
|
||||||
return pamh.PAM_AUTHINFO_UNAVAIL
|
|
||||||
|
|
||||||
# Abort if lid is closed
|
|
||||||
if config.getboolean("core", "ignore_closed_lid"):
|
|
||||||
if any("closed" in open(f).read() for f in glob.glob("/proc/acpi/button/lid/*/state")):
|
|
||||||
return pamh.PAM_AUTHINFO_UNAVAIL
|
|
||||||
|
|
||||||
# Abort if the video device does not exist
|
|
||||||
if not os.path.exists(config.get("video", "device_path")):
|
|
||||||
if config.getboolean("video", "warn_no_device"):
|
|
||||||
print("Camera path is not configured correctly, please edit the 'device_path' config value.")
|
|
||||||
return pamh.PAM_AUTHINFO_UNAVAIL
|
|
||||||
|
|
||||||
# Set up syslog
|
|
||||||
syslog.openlog("[HOWDY]", 0, syslog.LOG_AUTH)
|
|
||||||
|
|
||||||
# Alert the user that we are doing face detection
|
|
||||||
if config.getboolean("core", "detection_notice"):
|
|
||||||
pamh.conversation(pamh.Message(pamh.PAM_TEXT_INFO, "Attempting face detection"))
|
|
||||||
|
|
||||||
syslog.syslog(syslog.LOG_INFO, "Attempting facial authentication for user " + pamh.get_user())
|
|
||||||
|
|
||||||
# Run compare as python3 subprocess to circumvent python version and import issues
|
|
||||||
status = subprocess.call(["/usr/bin/python3", os.path.dirname(os.path.abspath(__file__)) + "/compare.py", pamh.get_user()])
|
|
||||||
|
|
||||||
# Status 10 means we couldn't find any face models
|
|
||||||
if status == 10:
|
|
||||||
if not config.getboolean("core", "suppress_unknown"):
|
|
||||||
pamh.conversation(pamh.Message(pamh.PAM_ERROR_MSG, "No face model known"))
|
|
||||||
|
|
||||||
syslog.syslog(syslog.LOG_NOTICE, "Failure, no face model known")
|
|
||||||
syslog.closelog()
|
|
||||||
return pamh.PAM_USER_UNKNOWN
|
|
||||||
|
|
||||||
# Status 11 means we exceded the maximum retry count
|
|
||||||
elif status == 11:
|
|
||||||
if config.getboolean("core", "timeout_notice"):
|
|
||||||
pamh.conversation(pamh.Message(pamh.PAM_ERROR_MSG, "Face detection timeout reached"))
|
|
||||||
syslog.syslog(syslog.LOG_INFO, "Failure, timeout reached")
|
|
||||||
syslog.closelog()
|
|
||||||
return pamh.PAM_AUTH_ERR
|
|
||||||
|
|
||||||
# Status 12 means we aborted
|
|
||||||
elif status == 12:
|
|
||||||
syslog.syslog(syslog.LOG_INFO, "Failure, general abort")
|
|
||||||
syslog.closelog()
|
|
||||||
return pamh.PAM_AUTH_ERR
|
|
||||||
|
|
||||||
# Status 13 means the image was too dark
|
|
||||||
elif status == 13:
|
|
||||||
pamh.conversation(pamh.Message(pamh.PAM_ERROR_MSG, "Face detection image too dark"))
|
|
||||||
syslog.syslog(syslog.LOG_INFO, "Failure, image too dark")
|
|
||||||
syslog.closelog()
|
|
||||||
return pamh.PAM_AUTH_ERR
|
|
||||||
|
|
||||||
# Status 14 means a rubberstamp could not be given
|
|
||||||
elif status == 14:
|
|
||||||
pamh.conversation(pamh.Message(pamh.PAM_ERROR_MSG, "Rubberstamp denied"))
|
|
||||||
syslog.syslog(syslog.LOG_INFO, "Failure, rubberstamp did not succeed")
|
|
||||||
syslog.closelog()
|
|
||||||
return pamh.PAM_AUTH_ERR
|
|
||||||
|
|
||||||
# Status 1 is probably a python crash
|
|
||||||
elif status == 1:
|
|
||||||
pamh.conversation(pamh.Message(pamh.PAM_ERROR_MSG, "Howdy encountered error, check stderr"))
|
|
||||||
syslog.syslog(syslog.LOG_INFO, "Failure, process crashed while authenticating")
|
|
||||||
syslog.closelog()
|
|
||||||
return pamh.PAM_SYSTEM_ERR
|
|
||||||
|
|
||||||
# Status 0 is a successful exit
|
|
||||||
elif status == 0:
|
|
||||||
# Show the success message if it isn't suppressed
|
|
||||||
if not config.getboolean("core", "no_confirmation"):
|
|
||||||
pamh.conversation(pamh.Message(pamh.PAM_TEXT_INFO, "Identified face as " + pamh.get_user()))
|
|
||||||
|
|
||||||
syslog.syslog(syslog.LOG_INFO, "Login approved")
|
|
||||||
syslog.closelog()
|
|
||||||
return pamh.PAM_SUCCESS
|
|
||||||
|
|
||||||
# Otherwise, we can't discribe what happend but it wasn't successful
|
|
||||||
pamh.conversation(pamh.Message(pamh.PAM_ERROR_MSG, "Unknown error: " + str(status)))
|
|
||||||
syslog.syslog(syslog.LOG_INFO, "Failure, unknown error" + str(status))
|
|
||||||
syslog.closelog()
|
|
||||||
return pamh.PAM_SYSTEM_ERR
|
|
||||||
|
|
||||||
|
|
||||||
def pam_sm_authenticate(pamh, flags, args):
|
|
||||||
"""Called by PAM when the user wants to authenticate, in sudo for example"""
|
|
||||||
return doAuth(pamh)
|
|
||||||
|
|
||||||
|
|
||||||
def pam_sm_open_session(pamh, flags, args):
|
|
||||||
"""Called when starting a session, such as su"""
|
|
||||||
return doAuth(pamh)
|
|
||||||
|
|
||||||
|
|
||||||
def pam_sm_close_session(pamh, flags, argv):
|
|
||||||
"""We don't need to clean anyting up at the end of a session, so returns true"""
|
|
||||||
return pamh.PAM_SUCCESS
|
|
||||||
|
|
||||||
|
|
||||||
def pam_sm_setcred(pamh, flags, argv):
|
|
||||||
"""We don't need set any credentials, so returns true"""
|
|
||||||
return pamh.PAM_SUCCESS
|
|
||||||
Loading…
Reference in a new issue