diff --git a/README.md b/README.md index 555b8ee8..35914e02 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,42 @@ -# Howdy for Linux [![](https://img.shields.io/travis/Boltgolt/howdy/master.svg)](https://travis-ci.org/Boltgolt/howdy) [![](https://img.shields.io/github/release/Boltgolt/howdy.svg?colorB=4c1)](https://github.com/Boltgolt/howdy/releases) ![](https://boltgolt.nl/howdy_badge/installs.php?nc) ![](https://boltgolt.nl/howdy_badge/views.php) +# Howdy for Linux [![](https://img.shields.io/travis/boltgolt/howdy/master.svg)](https://travis-ci.org/boltgolt/howdy) [![](https://img.shields.io/github/release/boltgolt/howdy.svg?colorB=4c1)](https://github.com/boltgolt/howdy/releases) ![](https://boltgolt.nl/howdy_badge/installs.php?nc) ![](https://boltgolt.nl/howdy_badge/views.php) -Windows Hello™ style authentication for Ubuntu. Use your built-in IR emitters and camera in combination with face recognition to prove who you are. +Windows Hello™ style authentication for Linux. Use your built-in IR emitters and camera in combination with face recognition to prove who you are. -Using the central authentication system in Linux (PAM), this works everywhere you would otherwise need your password: Login, lock screen, sudo, su, etc. +Using the central authentication system (PAM), this works everywhere you would otherwise need your password: Login, lock screen, sudo, su, etc. -### Installation +## Installation -* Ubuntu: Add the following ppa with ``` sudo add-apt-repository ppa:boltgolt/howdy ``` and ``` sudo apt update```. Then install Howdy with ``` sudo apt install howdy ```. - -* Arch Linux: Install the following package from the AUR: ``` howdy ```. Please read the [ArchWiki entry](https://wiki.archlinux.org/index.php/Howdy) for additional information. +Howdy is currently available for Ubuntu/Debian and Arch Linux. If you’re interested in packaging Howdy for your distro, don’t hesitate to open an issue. **Note:** The build of dlib can hang on 100% for over a minute, give it time. -This will guide you through the installation. When that's done run `sudo howdy add` to add a face model. +### Ubuntu (apt) + +Run the installer by pasting (`ctrl+shift+V`) the following commands into the terminal one at a time: + +``` +sudo add-apt-repository ppa:boltgolt/howdy +sudo apt update +sudo apt install howdy +``` + +This will guide you through the installation. + +### Arch Linux + +Install the `howdy` package from the AUR. For AUR installation instructions, take a look at this [wiki page](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages). + +You will need to do some additional configuration steps. Please read the [ArchWiki entry](https://wiki.archlinux.org/index.php/Howdy) for more information. + +## Setup + +After installation, you need to let Howdy learn your face. Run `sudo howdy add` to add a face model. If nothing went wrong we should be able to run sudo by just showing your face. Open a new terminal and run `sudo -i` to see it in action. -If you're curious you can run `sudo howdy config` to open the central config file and see the options Howdy has. +If you're curious you can run `sudo howdy config` to open the central config file and see the options Howdy has. On most systems this will open the nano editor, where you have to press `ctrl`+`x` to save your changes. -### CLI +## CLI The installer adds a `howdy` command to manage face models for the current user. Use `howdy --help` or `man howdy` to list the available options. @@ -37,17 +55,17 @@ howdy [-U user] [-y] command [argument] | `remove` | Remove a specific model for an user | | `test` | Test the camera and recognition methods | -### Contributing [![](https://img.shields.io/travis/Boltgolt/howdy/dev.svg?label=dev%20build)](https://github.com/Boltgolt/howdy/tree/dev) [![](https://img.shields.io/github/issues-raw/Boltgolt/howdy/enhancement.svg?label=feature+requests&colorB=4c1)](https://github.com/Boltgolt/howdy/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement) +## Contributing [![](https://img.shields.io/travis/boltgolt/howdy/dev.svg?label=dev%20build)](https://github.com/boltgolt/howdy/tree/dev) [![](https://img.shields.io/github/issues-raw/boltgolt/howdy/enhancement.svg?label=feature+requests&colorB=4c1)](https://github.com/boltgolt/howdy/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement) You can contribute in many ways. The easiest are reporting bugs and opening github issues for features you'd like to see in howdy. Code contributions are also very welcome. -### Troubleshooting +## Troubleshooting Any python errors get logged directly into the console and should indicate what went wrong. If authentication still fails but no errors are printed you could take a look at the last lines in `/var/log/auth.log` to see if anything has been reported there. If you encounter an error that hasn't been reported yet, don't be afraid to open a new issue. -### A note on security +## A note on security This script is in no way as secure as a password and will never be. Although it's harder to fool than normal face recognition, a person who looks similar to you or well-printed photo of you could be enough to do it. diff --git a/debian/changelog b/debian/changelog index c0842b79..d22b35a1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +howdy (2.3.0) xenial; urgency=medium + + * Added a config option to set the frame height and width (thanks @wzrdtales!) + * Rewrote the code that fetches the non-root username (thanks @dmig!) + * Changed the config command so it uses the default editor (thanks @stellarpower and @dmig!) + * Fixed issue where a "y" could be interpreted as a no (thanks @ramkrishna757575!) + * Fixed division by zeno (thanks @stellarpower!) + + -- boltgolt Thu, 28 Jun 2018 14:59:52 +0100 + howdy (2.2.2) xenial; urgency=medium * Fixed fetching of wrong config section (thanks @halcyoncheng and @arifeinberg!) diff --git a/debian/control b/debian/control index 87f91239..0bf354c4 100644 --- a/debian/control +++ b/debian/control @@ -4,12 +4,12 @@ Priority: optional Standards-Version: 3.9.7 Build-Depends: python, dh-python, devscripts, dh-make, debhelper Maintainer: boltgolt -Vcs-Git: https://github.com/Boltgolt/howdy +Vcs-Git: https://github.com/boltgolt/howdy Package: howdy -Homepage: https://github.com/Boltgolt/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 -Description: Howdy: Windows Hello style authentication for Ubuntu. +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. diff --git a/debian/howdy.1 b/debian/howdy.1 index 7254e432..e617eb4c 100644 --- a/debian/howdy.1 +++ b/debian/howdy.1 @@ -1,7 +1,7 @@ .\" Please adjust this date whenever revising the manpage. .TH HOWDY 1 "April 9, 2018" "Howdy help" "User Commands" .SH NAME -howdy \- Windows Hello style authentication for Ubuntu +howdy \- Windows Hello style authentication for Linux .SH DESCRIPTION Howdy IR face recognition implements a PAM module to use your face as a authentication method. .SS "Usage:" @@ -44,4 +44,4 @@ Skip all questions. Show this help message and exit. .PP .SH AUTHOR -Howdy was written by boltgolt. For more information visit https://github.com/Boltgolt/howdy +Howdy was written by boltgolt. For more information visit https://github.com/boltgolt/howdy diff --git a/debian/postinst b/debian/postinst index 5c40df6b..665b2f3a 100755 --- a/debian/postinst +++ b/debian/postinst @@ -187,7 +187,7 @@ if "HOWDY_NO_PROMPT" not in os.environ: ans = input("Apply this change? [y/N]: ") # Abort the whole thing if it's not - if (ans.lower() != "y"): + if ans.lower().strip() != "y" or ans.lower().strip() == "yes": print("Interpreting as a \"NO\", aborting") sys.exit(1) @@ -223,7 +223,7 @@ if "HOWDY_NO_PROMPT" not in os.environ: 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") + 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 print("Installation complete.") diff --git a/debian/preinst b/debian/preinst index 33572beb..a918b1b7 100755 --- a/debian/preinst +++ b/debian/preinst @@ -89,7 +89,7 @@ for dev in devices: 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() == "y" or ans.lower() == "yes": + if ans.lower().strip() == "y" or ans.lower().strip() == "yes": picked = dev[5:] break else: diff --git a/src/cli.py b/src/cli.py index 8ec350af..a9375943 100755 --- a/src/cli.py +++ b/src/cli.py @@ -10,10 +10,13 @@ import builtins # Try to get the original username (not "root") from shell -user = subprocess.check_output("echo $(logname 2>/dev/null || echo $SUDO_USER)", shell=True).decode("ascii").strip() +try: + user = os.getlogin() +except: + user = os.environ.get("SUDO_USER") # If that fails, try to get the direct user -if user == "root" or user == "": +if user == "root" or user == None: env_user = getpass.getuser().strip() # If even that fails, error out @@ -28,7 +31,7 @@ formatter_class=argparse.RawDescriptionHelpFormatter, add_help=False, prog="howdy", - epilog="For support please visit\nhttps://github.com/Boltgolt/howdy") + epilog="For support please visit\nhttps://github.com/boltgolt/howdy") # Add an argument for the command parser.add_argument("command", @@ -73,7 +76,8 @@ # Check if we have rootish rights # This is this far down the file so running the command for help is always possible if os.getenv("SUDO_USER") is None: - print("Please run this command with sudo") + print("Please run this command as root:\n") + print("\tsudo howdy " + " ".join(sys.argv[1:])) sys.exit(1) # Beond this point the user can't change anymore, if we still have root as user we need to abort diff --git a/src/cli/config.py b/src/cli/config.py index 0df3a15c..9606f243 100644 --- a/src/cli/config.py +++ b/src/cli/config.py @@ -6,10 +6,7 @@ import subprocess # Let the user know what we're doing -print("Opening config.ini in gedit") +print("Opening config.ini in the default editor") # Open gedit as a subprocess and fork it -subprocess.Popen(["gedit", os.path.dirname(os.path.realpath(__file__)) + "/../config.ini"], - cwd="/", - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) +subprocess.call(["/etc/alternatives/editor", os.path.dirname(os.path.realpath(__file__)) + "/../config.ini"]) diff --git a/src/cli/test.py b/src/cli/test.py index ca34470e..6321d987 100644 --- a/src/cli/test.py +++ b/src/cli/test.py @@ -24,6 +24,13 @@ if config.get("video", "force_mjpeg") == "true": video_capture.set(cv2.CAP_PROP_FOURCC, 1196444237) +# Set the frame width and height if requested +if int(config.get("video", "frame_width")) != -1: + video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, int(config.get("video", "frame_width"))) + +if int(config.get("video", "frame_height")) != -1: + video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, int(config.get("video", "frame_height"))) + # Let the user know what's up print(""" Opening a window with a test feed diff --git a/src/compare.py b/src/compare.py index a1a08697..03d89dce 100644 --- a/src/compare.py +++ b/src/compare.py @@ -62,8 +62,16 @@ def stop(status): # Force MJPEG decoding if true if config.get("video", "force_mjpeg") == "true": + # Set a magic number, will enable MJPEG but is badly documentated video_capture.set(cv2.CAP_PROP_FOURCC, 1196444237) +# Set the frame width and height if requested +if int(config.get("video", "frame_width")) != -1: + video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, int(config.get("video", "frame_width"))) + +if int(config.get("video", "frame_height")) != -1: + video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, int(config.get("video", "frame_height"))) + # Capture a single frame so the camera becomes active # This will let the camera adjust its light levels while we're importing for faster scanning video_capture.read() @@ -97,6 +105,11 @@ def stop(status): # All values combined for percentage calculation hist_total = int(sum(hist)[0]) + # If the image is fully black, skip to the next frame + if hist_total == 0: + dark_tries += 1 + continue + # Scrip the frame if it exceeds the threshold if float(hist[0]) / hist_total * 100 > float(config.get("video", "dark_threshold")): dark_tries += 1 @@ -159,5 +172,5 @@ def print_timing(label, offset): print("Winning model: " + str(match_index) + " (\"" + models[match_index]["label"] + "\")") - # End peacegully + # End peacefully stop(0) diff --git a/src/config.ini b/src/config.ini index ac5e06dd..ef657866 100644 --- a/src/config.ini +++ b/src/config.ini @@ -1,4 +1,5 @@ # Howdy config file +# Press CTRL + X to save in the nano editor [core] # Do not print anything when a face verification succeeds @@ -37,6 +38,12 @@ max_height = 320 # YUYV raw frame deconding force_mjpeg = false +# Set the camera input profile to this width and height +# The largest profile will be used if set to -1 +# Automatically ignored if not a valid profile +frame_width = -1 +frame_height = -1 + # Because of flashing IR emitters, some frames can be completely unlit # Skip the frame if the lowest 1/8 of the histogram is above this percentage # of the total @@ -46,5 +53,3 @@ dark_threshold = 50 [debug] # Show a short but detailed diagnostic report in console end_report = false - -dummy = true