Added certainty question, fixed streamer dependency

This commit is contained in:
boltgolt 2020-06-22 17:58:09 +02:00
parent f62de10972
commit 23810ef3c9
No known key found for this signature in database
GPG key ID: BECEC9937E1AAE26
7 changed files with 121 additions and 73 deletions

4
debian/control vendored
View file

@ -9,8 +9,8 @@ Vcs-Git: https://github.com/boltgolt/howdy
Package: howdy
Homepage: https://github.com/boltgolt/howdy
Architecture: all
Depends: ${misc:Depends}, curl|wget, python3, python3-pip, python3-dev, python3-setuptools, libpam-python, fswebcam, libopencv-dev, cmake, fswebcam
Recommends: libatlas-base-dev | libopenblas-dev | liblapack-dev
Depends: ${misc:Depends}, curl|wget, python3, python3-pip, python3-dev, python3-setuptools, libpam-python, libopencv-dev, cmake
Recommends: libatlas-base-dev | libopenblas-dev | liblapack-dev, streamer
Suggests: nvidia-cuda-dev (>= 7.5)
Description: Howdy: Windows Hello style authentication for Linux.
Use your built-in IR emitters and camera in combination with face recognition

6
debian/postinst vendored
View file

@ -196,10 +196,14 @@ handleStatus(subprocess.call(["pip3", "install", "--no-cache-dir", "opencv-pytho
log("Configuring howdy")
campath = picked.split(";")[0]
cert = picked.split(";")[1]
# Manually change the camera id to the one picked
for line in fileinput.input(["/lib/security/howdy/config.ini"], inplace=1):
line = line.replace("device_path = none", "device_path = " + picked)
line = line.replace("device_path = none", "device_path = " + campath)
line = line.replace("use_cnn = false", "use_cnn = " + str(cuda_used).lower())
line = line.replace("certainty = 3.5", "certainty = " + cert)
print(line, end="")

129
debian/preinst vendored
View file

@ -7,6 +7,7 @@ def col(id):
if id == 1: return "\033[32m"
if id == 2: return "\033[33m"
if id == 3: return "\033[31m"
if id == 4: return "\033[1m"
return "\033[0m"
@ -38,7 +39,6 @@ if "install" not in sys.argv:
# The default picked video device id
picked = "none"
print(col(1) + "Starting IR camera check...\n" + col(0))
# If prompting has been disabled, skip camera check
if "HOWDY_NO_PROMPT" in os.environ:
@ -46,67 +46,104 @@ 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("none")
out_file.write("none;3.5")
sys.exit(0)
# Get all devices
devices = os.listdir("/dev/v4l/by-path")
fscheck = subprocess.call(["which", "streamer"], stdout=subprocess.PIPE)
# Loop though all devices
for dev in devices:
time.sleep(.5)
if fscheck == 1:
print(col(2) + "\nWARNING: Could not automatically find the right webcam, manual configuration after installation required\n" + col(0))
else:
print(col(1) + "Starting IR camera check...\n" + col(0))
# 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")
# Get all devices
devices = os.listdir("/dev/v4l/by-path")
# 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 all devices
for dev in devices:
time.sleep(.5)
# Show what device we're using
print("Trying " + device_name)
# 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")
# Let fswebcam keep the camera open in the background
sub = subprocess.Popen(
"fswebcam -l 1 -d /dev/v4l/by-path/%s" % dev,
shell=True,
preexec_fn=os.setsid,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE)
# 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) + '"'
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
# Show what device we're using
print("Trying " + device_name)
# 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,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE)
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
os.killpg(os.getpgid(sub.pid), signal.SIGTERM)
raise
# 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))
# 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 == "none":
print(col(3) + "No suitable IR camera found, aborting install." + col(0))
sys.exit(23)
# Abort if no camera was picked
if picked == "none":
print(col(3) + "No suitable IR camera found, aborting install." + col(0))
sys.exit(23)
cert = 3.5
# Give time to read
time.sleep(.5)
print(col(1) + "\nStarting certainty auto config..." + col(0))
# Give more time to read
time.sleep(.5)
print("\n\nAfter detection, Howdy knows how certain it is that the match is correct.")
print("How certain Howdy needs to be before authenticating you can be customized.")
print(col(4) + "\nF: Fast." + col(0))
print("Allows more fuzzy matches, but speeds up the scanning process greatly.")
print(col(4) + "\nB: Balanced." + col(0))
print("Still relatively quick detection, but might not log you in when further away.")
print(col(4) + "\nS: Secure." + col(0))
print("The safest option, but will take much longer to authenticate you.")
print("\nYou can always change this setting in the config.")
prof = input("What profile would you like to use? [f/b/s]: ")
if prof.lower().strip() == "f" or prof.lower().strip() == "fast":
cert = 1.5
elif prof.lower().strip() == "b" or prof.lower().strip() == "balanced":
cert = 2.8
elif prof.lower().strip() == "s" or prof.lower().strip() == "secure":
cert = 4
# 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("/dev/v4l/by-path/" + picked)
out_file.write("/dev/v4l/by-path/" + picked + ";" + str(cert))
# Add a line break
print("")

View file

@ -2,6 +2,7 @@ tar-ignore = ".git"
tar-ignore = ".gitignore"
tar-ignore = ".github"
tar-ignore = "models"
tar-ignore = "snapshots"
tar-ignore = "tests"
tar-ignore = "README.md"
tar-ignore = ".travis.yml"

View file

@ -26,38 +26,44 @@ if user == "root" or user is None:
user = env_user
# Basic command setup
parser = argparse.ArgumentParser(description="Command line interface for Howdy face authentication.",
formatter_class=argparse.RawDescriptionHelpFormatter,
add_help=False,
prog="howdy",
epilog="For support please visit\nhttps://github.com/boltgolt/howdy")
parser = argparse.ArgumentParser(
description="Command line interface for Howdy face authentication.",
formatter_class=argparse.RawDescriptionHelpFormatter,
add_help=False,
prog="howdy",
epilog="For support please visit\nhttps://github.com/boltgolt/howdy")
# Add an argument for the command
parser.add_argument("command",
help="The command option to execute, can be one of the following: add, clear, config, disable, list, remove, snapshot, test or version.",
metavar="command",
choices=["add", "clear", "config", "disable", "list", "remove", "snapshot", "test", "version"])
parser.add_argument(
"command",
help="The command option to execute, can be one of the following: add, clear, config, disable, list, remove, snapshot, test or version.",
metavar="command",
choices=["add", "clear", "config", "disable", "list", "remove", "snapshot", "test", "version"])
# Add an argument for the extra arguments of diable and remove
parser.add_argument("argument",
help="Either 0 (enable) or 1 (disable) for the disable command, or the model ID for the remove command.",
nargs="?")
parser.add_argument(
"argument",
help="Either 0 (enable) or 1 (disable) for the disable command, or the model ID for the remove command.",
nargs="?")
# Add the user flag
parser.add_argument("-U", "--user",
default=user,
help="Set the user account to use.")
parser.add_argument(
"-U", "--user",
default=user,
help="Set the user account to use.")
# Add the -y flag
parser.add_argument("-y",
help="Skip all questions.",
action="store_true")
parser.add_argument(
"-y",
help="Skip all questions.",
action="store_true")
# Overwrite the default help message so we can use a uppercase S
parser.add_argument("-h", "--help",
action="help",
default=argparse.SUPPRESS,
help="Show this help message and exit.")
parser.add_argument(
"-h", "--help",
action="help",
default=argparse.SUPPRESS,
help="Show this help message and exit.")
# If we only have 1 argument we print the help text
if len(sys.argv) < 2:

View file

@ -25,7 +25,7 @@ try:
encodings = json.load(open(enc_file))
except FileNotFoundError:
print("No face model known for the user " + user + ", please run:")
print("\n\thowdy " + user + " add\n")
print("\n\tsudo howdy -U " + user + " add\n")
sys.exit(1)
# Print a header

View file

@ -22,4 +22,4 @@ fi
# Uncompress the data files and delete the original archive
echo "Unpacking..."
bzip2 -d *.bz2
bzip2 -d -f *.bz2