Merge pull request #94 from boltgolt/dev

Version 2.4.0
This commit is contained in:
boltgolt 2018-11-09 21:44:01 +01:00 committed by GitHub
commit b4ecafe61c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 115 additions and 104 deletions

View file

@ -11,8 +11,8 @@ _Please describe the issue in as much detail as possible, including any errors a
----
- [ ] I've searched for similar issues already, and my issue has not been reported yet.
I've searched for similar issues already, and my issue has not been reported yet.
Linux distribution (if applicable):
Linux distribution (if applicable):
Howdy version:
Howdy version:

View file

@ -1,24 +1,26 @@
sudo: required
language: python
python:
- "3.4"
- "3.6"
install:
# Install build tools and ack-grep for checks
- sudo apt install devscripts dh-make ack-grep -y
python: "3.6"
script:
# Build the binary (.deb)
- debuild -i -us -uc -b
# Install the binary, also fireing the debian scripts
# Install the binary, running the debian scripts in the process
- sudo apt install ../*.deb -y
# Confirm the cv2 module has been installed correctly
- sudo /usr/bin/env python3 -c "import cv2; print(cv2.__version__);"
# Confirm the face_recognition module has been installed correctly
- sudo /usr/bin/env python3 -c "import face_recognition; print(face_recognition.__version__);"
# Check if the username passthough works correctly with sudo
- 'howdy | ack-grep --passthru --color "current active user: travis"'
- 'sudo howdy | ack-grep --passthru --color "current active user: travis"'
# Remove howdy from the installation
- sudo apt purge howdy -y
notifications:
email:
on_success: never
@ -27,3 +29,8 @@ notifications:
addons:
apt:
update: true
packages:
- dh-make
- ack-grep
- devscripts
- fakeroot

10
debian/changelog vendored
View file

@ -1,3 +1,13 @@
howdy (2.4.0) xenial; urgency=medium
* Cameras are now selected by path instead of by video device number (thanks @Rhiyo!)
* Added fallbacks to $EDITOR for the config command (thanks @yassineim!)
* Fixed missing cv2 module after installation (thanks @bendandersen and many others!)
* Fixed file permissions crashing Howdy in some cases (thanks @GJDitchfield!)
* Fixed howdy using python3 from local virtual environment (thanks @EdwardJB!)
-- boltgolt <boltgolt@gmail.com> Fri, 09 Nov 2018 20:59:45 +0100
howdy (2.3.1) xenial; urgency=high
* Fixed issue where `frame_width` and `frame_height` would be completely ignored (thanks @janecz-n!)

4
debian/control vendored
View file

@ -2,14 +2,14 @@ Source: howdy
Section: misc
Priority: optional
Standards-Version: 3.9.7
Build-Depends: python, dh-python, devscripts, dh-make, debhelper
Build-Depends: python, dh-python, devscripts, dh-make, debhelper, fakeroot
Maintainer: boltgolt <boltgolt@gmail.com>
Vcs-Git: https://github.com/boltgolt/howdy
Package: howdy
Homepage: https://github.com/boltgolt/howdy
Architecture: all
Depends: ${misc:Depends}, git, python3, python3-pip, python3-dev, python3-setuptools, build-essential, libpam-python, fswebcam, libopencv-dev, python-opencv, cmake
Depends: ${misc:Depends}, git, python3, python3-pip, python3-dev, python3-setuptools, libpam-python, fswebcam, libopencv-dev, python-opencv, cmake, streamer
Description: Howdy: Windows Hello style authentication for Linux.
Use your built-in IR emitters and camera in combination with face recognition
to prove who you are.

7
debian/howdy.lintian-overrides vendored Normal file
View file

@ -0,0 +1,7 @@
# W: Don't require ugly linebreaks in last 5 chars
howdy: debian-changelog-line-too-long
# E: Allows the name Howdy to show up in Ubuntu updater
howdy: description-starts-with-package-name
# E: Allows python for installation scripts
howdy: unknown-control-interpreter

54
debian/postinst vendored
View file

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/python3
# Installation script to install howdy
# Executed after primary apt install
@ -53,6 +53,11 @@ if not os.path.exists("/tmp/howdy_picked_device"):
# Go through every setting in the old config and apply it to the new file
for section in oldConf.sections():
for (key, value) in oldConf.items(section):
# If config is still using the old device_id parameter, convert it to a path
if key == "device_id":
key = "device_path"
value = "/dev/video" + value
try:
newConf.set(section, key, value)
# Add a new section where needed
@ -98,7 +103,7 @@ print("Temporary dlib files removed")
log("Installing python dependencies")
# Install face_recognition though pip
# Install direct dependencies so pip does not freak out with the manual dlib install
handleStatus(subprocess.call(["pip3", "install", "--cache-dir", "/tmp/pip_howdy", "face_recognition_models==0.3.0", "Click>=6.0", "numpy", "Pillow"]))
log("Installing face_recognition")
@ -106,19 +111,26 @@ log("Installing face_recognition")
# Install face_recognition though pip
handleStatus(subprocess.call(["pip3", "install", "--cache-dir", "/tmp/pip_howdy", "--no-deps", "face_recognition==1.2.2"]))
try:
import cv2
except Exception as e:
log("Reinstalling opencv2")
handleStatus(subprocess.call(["pip3", "install", "opencv-python"]))
log("Configuring howdy")
# Manually change the camera id to the one picked
for line in fileinput.input(["/lib/security/howdy/config.ini"], inplace = 1):
print(line.replace("device_id = 1", "device_id = " + picked), end="")
print(line.replace("device_path = none", "device_path = " + picked), end="")
print("Camera ID saved")
# Secure the howdy folder
handleStatus(subprocess.call(["chmod 600 -R /lib/security/howdy/"], shell=True))
handleStatus(subprocess.call(["chmod 744 -R /lib/security/howdy/"], shell=True))
# Allow anyone to execute the python CLI
handleStatus(subprocess.call(["chmod 755 /lib/security/howdy"], shell=True))
handleStatus(subprocess.call(["chmod 744 /lib/security/howdy/cli.py"], shell=True))
handleStatus(subprocess.call(["chmod 744 -R /lib/security/howdy/cli"], shell=True))
handleStatus(subprocess.call(["chmod 755 /lib/security/howdy/cli.py"], shell=True))
handleStatus(subprocess.call(["chmod 755 -R /lib/security/howdy/cli"], shell=True))
print("Permissions set")
# Make the CLI executable as howdy
@ -198,33 +210,5 @@ common_auth = open("/etc/pam.d/common-auth", "w")
common_auth.write("".join(outlines))
common_auth.close()
# From here onwards the installation is complete
# We want to gather more information about the types or IR camera's
# used though, and the following lines are data gathering
# No data is ever uploaded without permission
if "HOWDY_NO_PROMPT" not in os.environ:
# List all video devices
diag_out = "Video devices [IR=" + picked + "]\n"
diag_out += "```\n"
diag_out += subprocess.check_output(['ls /dev/ | grep video'], shell=True).decode("utf-8")
diag_out += "```\n"
# Get some info from the USB kernel listings
diag_out += "Lsusb output\n"
diag_out += "```\n"
diag_out += subprocess.check_output(['lsusb -vvvv | grep -i "Camera\|iFunction"'], shell=True).decode("utf-8")
diag_out += "```\n"
# Get camera information from video4linux
diag_out += "Udevadm\n"
diag_out += "```\n"
diag_out += subprocess.check_output(['udevadm info -r --query=all -n /dev/video' + picked + ' | grep -i "ID_BUS\|ID_MODEL_ID\|ID_VENDOR_ID\|ID_V4L_PRODUCT\|ID_MODEL"'], shell=True).decode("utf-8")
diag_out += "```"
# Print it all as a clickable link to a new github issue
print("https://github.com/boltgolt/howdy-reports/issues/new?title=Post-installation%20camera%20information&body=" + urllib.parse.quote_plus(diag_out) + "\n")
# Let the user know what to do with the link
# Sign off
print("Installation complete.")
print(col(2) + "If you want to help the development, please use the link above to post some camera-related information to github!" + col(0))

76
debian/preinst vendored
View file

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/python3
# Used to check cameras before commiting to install
# Executed before primary apt install of files
@ -35,7 +35,7 @@ if "install" not in sys.argv:
sys.exit(0)
# The default picked video device id
picked = -1
picked = "none"
print(col(1) + "Starting IR camera check...\n" + col(0))
@ -45,64 +45,62 @@ if "HOWDY_NO_PROMPT" in os.environ:
# Write the default device to disk and exit
with open("/tmp/howdy_picked_device", "w") as out_file:
out_file.write("0")
out_file.write("none")
sys.exit(0)
# Get all devices
devices = os.listdir("/dev")
devices = os.listdir("/dev/v4l/by-path")
# Loop though all devices
for dev in devices:
# Only use the video devices
if (dev[:5] == "video"):
time.sleep(.5)
time.sleep(.5)
# The full path to the device is the default name
device_name = "/dev/" + dev
# Get the udevadm details to try to get a better name
udevadm = subprocess.check_output(["udevadm info -r --query=all -n " + device_name], shell=True).decode("utf-8")
# The full path to the device is the default name
device_name = "/dev/v4l/by-path/" + dev
# Get the udevadm details to try to get a better name
udevadm = subprocess.check_output(["udevadm info -r --query=all -n " + device_name], shell=True).decode("utf-8")
# Loop though udevadm to search for a better name
for line in udevadm.split("\n"):
# Match it and encase it in quotes
re_name = re.search('product.*=(.*)$', line, re.IGNORECASE)
if re_name:
device_name = '"' + re_name.group(1) + '"'
# Loop though udevadm to search for a better name
for line in udevadm.split("\n"):
# Match it and encase it in quotes
re_name = re.search('product.*=(.*)$', line, re.IGNORECASE)
if re_name:
device_name = '"' + re_name.group(1) + '"'
# Show what device we're using
print("Trying " + device_name)
# Show what device we're using
print("Trying " + device_name)
# Let fswebcam keep the camera open in the background
sub = subprocess.Popen(["fswebcam -S 9999999999 -d /dev/" + dev + " /dev/null 2>/dev/null"], shell=True, preexec_fn=os.setsid)
# Let fswebcam keep the camera open in the background
sub = subprocess.Popen(["streamer -t 1:0:0 -c /dev/v4l/by-path/" + dev + " -b 16 -f rgb24 -o /dev/null 1>/dev/null 2>/dev/null"], shell=True, preexec_fn=os.setsid)
try:
# Ask the user if this is the right one
print(col(2) + "One of your cameras should now be on." + col(0))
ans = input("Did your IR emitters turn on? [y/N]: ")
except KeyboardInterrupt:
# Kill fswebcam if the user aborts
os.killpg(os.getpgid(sub.pid), signal.SIGTERM)
raise
# The user has answered, kill fswebcam
try:
# Ask the user if this is the right one
print(col(2) + "One of your cameras should now be on." + col(0))
ans = input("Did your IR emitters turn on? [y/N]: ")
except KeyboardInterrupt:
# Kill fswebcam if the user aborts
os.killpg(os.getpgid(sub.pid), signal.SIGTERM)
raise
# Set this camera as picked if the answer was yes, go to the next one if no
if ans.lower().strip() == "y" or ans.lower().strip() == "yes":
picked = dev[5:]
break
else:
print("Interpreting as a " + col(3) + "\"NO\"\n" + col(0))
# The user has answered, kill fswebcam
os.killpg(os.getpgid(sub.pid), signal.SIGTERM)
# Set this camera as picked if the answer was yes, go to the next one if no
if ans.lower().strip() == "y" or ans.lower().strip() == "yes":
picked = dev
break
else:
print("Interpreting as a " + col(3) + "\"NO\"\n" + col(0))
# Abort if no camera was picked
if picked == -1:
if picked == "none":
print(col(3) + "No suitable IR camera found, aborting install." + col(0))
sys.exit(23)
# Write the result to disk so postinst can have a look at it
with open("/tmp/howdy_picked_device", "w") as out_file:
out_file.write(str(picked))
out_file.write("/dev/v4l/by-path/" + picked)
# Add a line break
print("")

2
debian/prerm vendored
View file

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/python3
# Executed on deinstallation
# Completely remove howdy from the system

3
debian/rules vendored
View file

@ -6,6 +6,3 @@ include /usr/share/dpkg/default.mk
%:
dh $@
binary:
dh binary

View file

@ -79,7 +79,7 @@ insert_model = {
}
# Open the camera
video_capture = cv2.VideoCapture(int(config.get("video", "device_id")))
video_capture = cv2.VideoCapture(config.get("video", "device_path"))
# Force MJPEG decoding if true
if config.get("video", "force_mjpeg") == "true":

View file

@ -1,12 +1,20 @@
# Open the config file in gedit
# Open the config file in an editor
# Import required modules
import os
import time
import subprocess
# Let the user know what we're doing
print("Opening config.ini in the default editor")
# Open gedit as a subprocess and fork it
subprocess.call(["/etc/alternatives/editor", os.path.dirname(os.path.realpath(__file__)) + "/../config.ini"])
# Default to the nano editor
editor = "/bin/nano"
# Use the user preferred editor if available
if os.path.isfile("/etc/alternatives/editor"):
editor = "/etc/alternatives/editor"
elif "EDITOR" in os.environ:
editor = os.environ["EDITOR"]
# Open the editor as a subprocess and fork it
subprocess.call([editor, os.path.dirname(os.path.realpath(__file__)) + "/../config.ini"])

View file

@ -18,7 +18,7 @@ config = configparser.ConfigParser()
config.read(path + "/../config.ini")
# Start capturing from the configured webcam
video_capture = cv2.VideoCapture(int(config.get("video", "device_id")))
video_capture = cv2.VideoCapture(config.get("video", "device_path"))
# Force MJPEG decoding if true
if config.get("video", "force_mjpeg") == "true":

View file

@ -58,7 +58,7 @@ for model in models:
timings.append(time.time())
# Start video capture on the IR camera
video_capture = cv2.VideoCapture(int(config.get("video", "device_id")))
video_capture = cv2.VideoCapture(config.get("video", "device_path"))
# Force MJPEG decoding if true
if config.get("video", "force_mjpeg") == "true":

View file

@ -29,9 +29,9 @@ certainty = 3.5
# The number of seconds to search before timing out
timout = 4
# The /dev/videoX id to capture frames from
# The path of the device to capture frames from
# Should be set automatically by the installer
device_id = 1
device_path = none
# Scale down the video feed to this maximum height
# Speeds up face recognition but can make it less precise

View file

@ -13,7 +13,7 @@ config = ConfigParser.ConfigParser()
config.read(os.path.dirname(os.path.abspath(__file__)) + "/config.ini")
def doAuth(pamh):
"""Start authentication in a seperate process"""
"""Starts authentication in a seperate process"""
# Abort is Howdy is disabled
if config.get("core", "disabled") == "true":
@ -25,7 +25,7 @@ def doAuth(pamh):
sys.exit(0)
# Run compare as python3 subprocess to circumvent python version and import issues
status = subprocess.call(["python3", os.path.dirname(os.path.abspath(__file__)) + "/compare.py", pamh.get_user()])
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:
@ -62,9 +62,9 @@ def pam_sm_open_session(pamh, flags, args):
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 return true"""
"""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 return true"""
"""We don't need set any credentials, so returns true"""
return pamh.PAM_SUCCESS