Skip to content

Commit e495bda

Browse files
authored
Merge pull request #370 from boltgolt/dev
Version 2.6.0
2 parents d001f0f + c3b11d1 commit e495bda

22 files changed

Lines changed: 573 additions & 220 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ ENV/
103103
# generated models
104104
/src/models
105105

106+
# snapshots
107+
/src/snapshots
108+
106109
# build files
107110
debian/howdy.substvars
108111
debian/files

.travis.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
sudo: required
2+
dist: xenial
23
language: python
3-
python: "3.6"
4+
python:
5+
- "3.4"
6+
- "3.6"
7+
- "3.7"
8+
- "3.8-dev"
49

510
script:
611
# Build the binary (.deb)

debian/changelog

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
howdy (2.6.0) xenial; urgency=medium
2+
3+
* Added new options to capture a snapshot of failed or even successful logins
4+
* Added command that creates a new snapshot and saves it
5+
* Added version command
6+
* Added question to automatically set certainty value on installation
7+
* Added automatic logging to system-wide auth.log
8+
* Added clearer feedback when login is rejected due to dark frames (thanks @andrewmv!)
9+
* Refactored video capture logic (thanks @AnthonyWharton!)
10+
* Reordered the editor priorities for the config command
11+
* Fixed gstreamer warnings showing up in console (thanks @ajnart!)
12+
* Fixed issue where add command would never end
13+
* Fixed test command overlay not being in color (thanks @PetePriority!)
14+
* Fixed typo preventing timeout config option from working (thanks @Ajayneethikannan!)
15+
* Fixed old numpy installation failure (thanks @rushabh-v!)
16+
* Fixed issue where no PAM response would be returned
17+
* Fixed CLAHE not being applied equally to all video commands (thanks @PetePriority!)
18+
* Fixed an incorrect suggested command (thanks @TheButlah!)
19+
* Fixed missing release method in video capture class
20+
* Removed deprecated dlib flags (thanks @rhysperry111!)
21+
* Removed streamer as a required dependency
22+
23+
-- boltgolt <boltgolt@gmail.com> Mon, 22 Jun 2020 16:11:46 +0200
24+
125
howdy (2.5.1) xenial; urgency=medium
226

327
* Removed dismiss_lockscreen as it could lock users out of their system (thanks @ujjwalbe, @ju916 and many others!)

debian/control

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ Vcs-Git: https://github.com/boltgolt/howdy
99
Package: howdy
1010
Homepage: https://github.com/boltgolt/howdy
1111
Architecture: all
12-
Depends: ${misc:Depends}, curl|wget, python3, python3-pip, python3-dev, python3-setuptools, libpam-python, fswebcam, libopencv-dev, cmake, streamer
13-
Recommends: libatlas-base-dev | libopenblas-dev | liblapack-dev
12+
Depends: ${misc:Depends}, curl|wget, python3, python3-pip, python3-dev, python3-setuptools, libpam-python, libopencv-dev, cmake
13+
Recommends: libatlas-base-dev | libopenblas-dev | liblapack-dev, streamer
1414
Suggests: nvidia-cuda-dev (>= 7.5)
1515
Description: Howdy: Windows Hello style authentication for Linux.
1616
Use your built-in IR emitters and camera in combination with face recognition

debian/postinst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ log("Upgrading pip to the latest version")
109109
# Update pip
110110
handleStatus(sc(["pip3", "install", "--upgrade", "pip"]))
111111

112+
113+
log("Upgrading numpy to the lateset version")
114+
115+
# Update numpy
116+
handleStatus(subprocess.call(["pip3", "install", "--upgrade", "numpy"]))
117+
112118
log("Downloading and unpacking data files")
113119

114120
# Run the bash script to download and unpack the .dat files needed
@@ -190,10 +196,14 @@ handleStatus(subprocess.call(["pip3", "install", "--no-cache-dir", "opencv-pytho
190196

191197
log("Configuring howdy")
192198

199+
campath = picked.split(";")[0]
200+
cert = picked.split(";")[1]
201+
193202
# Manually change the camera id to the one picked
194203
for line in fileinput.input(["/lib/security/howdy/config.ini"], inplace=1):
195-
line = line.replace("device_path = none", "device_path = " + picked)
204+
line = line.replace("device_path = none", "device_path = " + campath)
196205
line = line.replace("use_cnn = false", "use_cnn = " + str(cuda_used).lower())
206+
line = line.replace("certainty = 3.5", "certainty = " + cert)
197207

198208
print(line, end="")
199209

debian/preinst

Lines changed: 84 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ def col(id):
77
if id == 1: return "\033[32m"
88
if id == 2: return "\033[33m"
99
if id == 3: return "\033[31m"
10+
if id == 4: return "\033[1m"
1011
return "\033[0m"
1112

1213

@@ -38,70 +39,111 @@ if "install" not in sys.argv:
3839
# The default picked video device id
3940
picked = "none"
4041

41-
print(col(1) + "Starting IR camera check...\n" + col(0))
4242

4343
# If prompting has been disabled, skip camera check
4444
if "HOWDY_NO_PROMPT" in os.environ:
4545
print(col(2) + "AUTOMATED INSTALL, YOU WILL NOT BE ASKED FOR INPUT AND CHECKS WILL BE SKIPPED" + col(0))
4646

4747
# Write the default device to disk and exit
4848
with open("/tmp/howdy_picked_device", "w") as out_file:
49-
out_file.write("none")
49+
out_file.write("none;3.5")
5050

5151
sys.exit(0)
5252

53-
# Get all devices
54-
devices = os.listdir("/dev/v4l/by-path")
53+
fscheck = subprocess.call(["which", "streamer"], stdout=subprocess.PIPE)
54+
55+
if fscheck == 1:
56+
print(col(2) + "\nWARNING: Could not automatically find the right webcam, manual configuration after installation required\n" + col(0))
57+
else:
58+
print(col(1) + "Starting IR camera check...\n" + col(0))
59+
60+
# Get all devices
61+
devices = os.listdir("/dev/v4l/by-path")
62+
63+
# Loop though all devices
64+
for dev in devices:
65+
time.sleep(.5)
66+
67+
# The full path to the device is the default name
68+
device_name = "/dev/v4l/by-path/" + dev
69+
# Get the udevadm details to try to get a better name
70+
udevadm = subprocess.check_output(["udevadm info -r --query=all -n " + device_name], shell=True).decode("utf-8")
71+
72+
# Loop though udevadm to search for a better name
73+
for line in udevadm.split("\n"):
74+
# Match it and encase it in quotes
75+
re_name = re.search('product.*=(.*)$', line, re.IGNORECASE)
76+
if re_name:
77+
device_name = '"' + re_name.group(1) + '"'
78+
79+
# Show what device we're using
80+
print("Trying " + device_name)
81+
82+
# Let fswebcam keep the camera open in the background
83+
sub = subprocess.Popen(
84+
["streamer -t 1:0:0 -c /dev/v4l/by-path/" + dev + " -b 16 -f rgb24 -o /dev/null 1>/dev/null 2>/dev/null"],
85+
shell=True,
86+
preexec_fn=os.setsid,
87+
stdout=subprocess.PIPE,
88+
stdin=subprocess.PIPE)
89+
90+
try:
91+
# Ask the user if this is the right one
92+
print(col(2) + "One of your cameras should now be on." + col(0))
93+
ans = input("Did your IR emitters turn on? [y/N]: ")
94+
except KeyboardInterrupt:
95+
# Kill fswebcam if the user aborts
96+
os.killpg(os.getpgid(sub.pid), signal.SIGTERM)
97+
raise
98+
99+
# The user has answered, kill fswebcam
100+
os.killpg(os.getpgid(sub.pid), signal.SIGTERM)
55101

56-
# Loop though all devices
57-
for dev in devices:
58-
time.sleep(.5)
102+
# Set this camera as picked if the answer was yes, go to the next one if no
103+
if ans.lower().strip() == "y" or ans.lower().strip() == "yes":
104+
picked = dev
105+
break
106+
else:
107+
print("Interpreting as a " + col(3) + "\"NO\"\n" + col(0))
59108

60-
# The full path to the device is the default name
61-
device_name = "/dev/v4l/by-path/" + dev
62-
# Get the udevadm details to try to get a better name
63-
udevadm = subprocess.check_output(["udevadm info -r --query=all -n " + device_name], shell=True).decode("utf-8")
109+
# Abort if no camera was picked
110+
if picked == "none":
111+
print(col(3) + "No suitable IR camera found, aborting install." + col(0))
112+
sys.exit(23)
64113

65-
# Loop though udevadm to search for a better name
66-
for line in udevadm.split("\n"):
67-
# Match it and encase it in quotes
68-
re_name = re.search('product.*=(.*)$', line, re.IGNORECASE)
69-
if re_name:
70-
device_name = '"' + re_name.group(1) + '"'
114+
cert = 3.5
71115

72-
# Show what device we're using
73-
print("Trying " + device_name)
116+
# Give time to read
117+
time.sleep(.5)
74118

75-
# Let fswebcam keep the camera open in the background
76-
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)
119+
print(col(1) + "\nStarting certainty auto config..." + col(0))
77120

78-
try:
79-
# Ask the user if this is the right one
80-
print(col(2) + "One of your cameras should now be on." + col(0))
81-
ans = input("Did your IR emitters turn on? [y/N]: ")
82-
except KeyboardInterrupt:
83-
# Kill fswebcam if the user aborts
84-
os.killpg(os.getpgid(sub.pid), signal.SIGTERM)
85-
raise
121+
# Give more time to read
122+
time.sleep(.5)
123+
124+
print("\n\nAfter detection, Howdy knows how certain it is that the match is correct.")
125+
print("How certain Howdy needs to be before authenticating you can be customized.")
86126

87-
# The user has answered, kill fswebcam
88-
os.killpg(os.getpgid(sub.pid), signal.SIGTERM)
127+
print(col(4) + "\nF: Fast." + col(0))
128+
print("Allows more fuzzy matches, but speeds up the scanning process greatly.")
129+
print(col(4) + "\nB: Balanced." + col(0))
130+
print("Still relatively quick detection, but might not log you in when further away.")
131+
print(col(4) + "\nS: Secure." + col(0))
132+
print("The safest option, but will take much longer to authenticate you.")
89133

90-
# Set this camera as picked if the answer was yes, go to the next one if no
91-
if ans.lower().strip() == "y" or ans.lower().strip() == "yes":
92-
picked = dev
93-
break
94-
else:
95-
print("Interpreting as a " + col(3) + "\"NO\"\n" + col(0))
134+
print("\nYou can always change this setting in the config.")
135+
prof = input("What profile would you like to use? [f/b/s]: ")
96136

97-
# Abort if no camera was picked
98-
if picked == "none":
99-
print(col(3) + "No suitable IR camera found, aborting install." + col(0))
100-
sys.exit(23)
137+
if prof.lower().strip() == "f" or prof.lower().strip() == "fast":
138+
cert = 1.5
139+
elif prof.lower().strip() == "b" or prof.lower().strip() == "balanced":
140+
cert = 2.8
141+
elif prof.lower().strip() == "s" or prof.lower().strip() == "secure":
142+
cert = 4
101143

102144
# Write the result to disk so postinst can have a look at it
103145
with open("/tmp/howdy_picked_device", "w") as out_file:
104-
out_file.write("/dev/v4l/by-path/" + picked)
146+
out_file.write("/dev/v4l/by-path/" + picked + ";" + str(cert))
105147

106148
# Add a line break
107149
print("")

debian/source/options

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ tar-ignore = ".git"
22
tar-ignore = ".gitignore"
33
tar-ignore = ".github"
44
tar-ignore = "models"
5+
tar-ignore = "snapshots"
56
tar-ignore = "tests"
67
tar-ignore = "README.md"
78
tar-ignore = ".travis.yml"

fedora/howdy.spec

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Version: 2.5.1
99
%if %{with_snapshot}
1010
Release: 0.1.git.%{date}%{shortcommit}%{?dist}
1111
%else
12-
Release: 3%{?dist}
12+
Release: 4%{?dist}
1313
%endif
1414
Summary: Windows Hello™ style authentication for Linux
1515

@@ -27,12 +27,9 @@ BuildRequires: polkit-devel
2727
%if 0%{?fedora}
2828
# We need python3-devel for pathfix.py
2929
BuildRequires: python3-devel
30-
Requires: python3dist(dlib) >= 6.0
31-
Requires: python3dist(v4l2)
32-
Requires: python3-face_recognition
33-
Supplements: python3-face_recognition_models
30+
Requires: python3dist(dlib) >= 6.0
3431
Requires: python3-opencv
35-
Requires: python3-pam
32+
Requires: pam_python
3633
%endif
3734

3835

src/cli.py

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,38 +26,44 @@
2626
user = env_user
2727

2828
# Basic command setup
29-
parser = argparse.ArgumentParser(description="Command line interface for Howdy face authentication.",
30-
formatter_class=argparse.RawDescriptionHelpFormatter,
31-
add_help=False,
32-
prog="howdy",
33-
epilog="For support please visit\nhttps://github.com/boltgolt/howdy")
29+
parser = argparse.ArgumentParser(
30+
description="Command line interface for Howdy face authentication.",
31+
formatter_class=argparse.RawDescriptionHelpFormatter,
32+
add_help=False,
33+
prog="howdy",
34+
epilog="For support please visit\nhttps://github.com/boltgolt/howdy")
3435

3536
# Add an argument for the command
36-
parser.add_argument("command",
37-
help="The command option to execute, can be one of the following: add, clear, config, disable, list, remove or test.",
38-
metavar="command",
39-
choices=["add", "clear", "config", "disable", "list", "remove", "test"])
37+
parser.add_argument(
38+
"command",
39+
help="The command option to execute, can be one of the following: add, clear, config, disable, list, remove, snapshot, test or version.",
40+
metavar="command",
41+
choices=["add", "clear", "config", "disable", "list", "remove", "snapshot", "test", "version"])
4042

4143
# Add an argument for the extra arguments of diable and remove
42-
parser.add_argument("argument",
43-
help="Either 0 (enable) or 1 (disable) for the disable command, or the model ID for the remove command.",
44-
nargs="?")
44+
parser.add_argument(
45+
"argument",
46+
help="Either 0 (enable) or 1 (disable) for the disable command, or the model ID for the remove command.",
47+
nargs="?")
4548

4649
# Add the user flag
47-
parser.add_argument("-U", "--user",
48-
default=user,
49-
help="Set the user account to use.")
50+
parser.add_argument(
51+
"-U", "--user",
52+
default=user,
53+
help="Set the user account to use.")
5054

5155
# Add the -y flag
52-
parser.add_argument("-y",
53-
help="Skip all questions.",
54-
action="store_true")
56+
parser.add_argument(
57+
"-y",
58+
help="Skip all questions.",
59+
action="store_true")
5560

5661
# Overwrite the default help message so we can use a uppercase S
57-
parser.add_argument("-h", "--help",
58-
action="help",
59-
default=argparse.SUPPRESS,
60-
help="Show this help message and exit.")
62+
parser.add_argument(
63+
"-h", "--help",
64+
action="help",
65+
default=argparse.SUPPRESS,
66+
help="Show this help message and exit.")
6167

6268
# If we only have 1 argument we print the help text
6369
if len(sys.argv) < 2:
@@ -97,5 +103,9 @@
97103
import cli.list
98104
elif args.command == "remove":
99105
import cli.remove
106+
elif args.command == "snapshot":
107+
import cli.snap
100108
elif args.command == "test":
101109
import cli.test
110+
else:
111+
print("Howdy 2.6.0")

0 commit comments

Comments
 (0)