Skip to content

Commit f084411

Browse files
committed
Uninstaller working and comments in installer
1 parent 818be92 commit f084411

3 files changed

Lines changed: 103 additions & 11 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ Any python errors get logged directly into the console and should indicate what
2828

2929
If you encounter an error that hasn't been reported yet, don't be afraid to open a new issue.
3030

31+
### Uninstalling
32+
33+
There is an uninstaller available, run `sudo python3 /lib/security/howdy/uninstall.py` to remove Howdy from your system.
34+
3135
### A note on security
3236

3337
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.

installer.py

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Installation script to install howdy
2+
# Runs completely independent of the others
3+
4+
# Import required modules
15
import subprocess
26
import time
37
import sys
@@ -8,87 +12,112 @@
812
import urllib.parse
913

1014
def log(text):
15+
"""Print a nicely formatted line to stdout"""
1116
print("\n>>> \033[32m" + text + "\033[0m\n")
1217

1318
def handleStatus(status):
19+
"""Abort if a command fails"""
1420
if (status != 0):
1521
print("\033[31mError while running last command\033[0m")
1622
sys.exit()
1723

24+
# Check if we're running as root
1825
user = os.getenv("SUDO_USER")
19-
2026
if user is None:
2127
print("Please run this script as a sudo user")
2228
sys.exit()
2329

30+
# Print some nice intro text
2431
print("\n\033[33m HOWDY INSTALLER FOR UBUNTU\033[0m")
2532
print(" Version 1, 2016/02/05\n")
2633

34+
# Let it sink in
2735
time.sleep(.5)
2836
log("Installing required apt packages")
2937

38+
# Install packages though apt
3039
handleStatus(subprocess.call(["apt", "install", "-y", "libpam-python", "fswebcam", "libopencv-dev", "python-opencv"]))
3140

3241
log("Starting camera check")
3342

43+
# Get all devices
3444
devices = os.listdir("/dev")
45+
# The picked video device id
3546
picked = False
3647

48+
# Loop though all devices
3749
for dev in devices:
50+
# Only use the video devices
3851
if (dev[:5] == "video"):
3952
time.sleep(.5)
4053

54+
# The full path to the device is the default name
4155
device_name = "/dev/" + dev
56+
# Get the udevadm details to try to get a better name
4257
udevadm = subprocess.check_output(["udevadm info -r --query=all -n " + device_name], shell=True).decode("utf-8")
4358

59+
# Loop though udevadm to search for a better name
4460
for line in udevadm.split("\n"):
61+
# Match it and encase it in quotes
4562
re_name = re.search('product.*=(.*)$', line, re.IGNORECASE)
46-
4763
if re_name:
4864
device_name = '"' + re_name.group(1) + '"'
4965

66+
# Show what device we're using
5067
print("Trying " + device_name)
5168

69+
# Let fswebcam keep the camera open in the background
5270
sub = subprocess.Popen(["fswebcam -S 9999999999 -d /dev/" + dev + " /dev/null 2>/dev/null"], shell=True, preexec_fn=os.setsid)
5371

72+
# Ask the user if this is the right one
5473
print("\033[33mOne of your cameras should now be on.\033[0m")
5574
ans = input("Did your IR emitters turn on? [y/N]: ")
5675

76+
# The user has answered, kill fswebcam
5777
os.killpg(os.getpgid(sub.pid), signal.SIGTERM)
5878

79+
# Set this camera as picked if the answer was yes, go to the next one if no
5980
if (ans.lower() == "y"):
6081
picked = dev[5:]
6182
break
6283
else:
6384
print("Inerpeting as a \"NO\"\n")
6485

86+
# Abort if no camera was picked
6587
if (picked == False):
6688
print("\033[31mNo suitable IR camera found\033[0m")
6789
sys.exit()
6890

6991
log("Cloning dlib")
7092

93+
# Clone the git to /tmp
7194
handleStatus(subprocess.call(["git", "clone", "https://github.com/davisking/dlib.git", "/tmp/dlib_clone"]))
7295

7396
log("Building dlib")
7497

98+
# Start the build without GPU
7599
handleStatus(subprocess.call(["cd /tmp/dlib_clone/; python3 setup.py install --yes USE_AVX_INSTRUCTIONS --no DLIB_USE_CUDA"], shell=True))
76100

77101
log("Cleaning up dlib")
78102

103+
# Remove the no longer needed git clone
79104
handleStatus(subprocess.call(["rm", "-rf", "/tmp/dlib_clone"]))
80105

81106
log("Installing face_recognition")
82107

108+
# Install face_recognition though pip
83109
handleStatus(subprocess.call(["pip3", "install", "face_recognition"]))
84110

85111
log("Cloning howdy")
86112

113+
# Make sure /lib/security exists
87114
if not os.path.exists("/lib/security"):
88115
os.makedirs("/lib/security")
89116

117+
# Clone howdy into it
90118
handleStatus(subprocess.call(["git", "clone", "https://github.com/Boltgolt/howdy.git", "/lib/security/howdy"]))
91119

120+
# Manually change the camera id to the one picked
92121
for line in fileinput.input(["/lib/security/howdy/config.ini"], inplace = 1):
93122
print(line.replace("device_id = 1", "device_id = " + picked), end="")
94123

@@ -104,76 +133,103 @@ def handleStatus(status):
104133

105134
log("Adding howdy as PAM module")
106135

136+
# Will be filled with the actual output lines
107137
outlines = []
138+
# Will be fillled with lines that contain coloring
108139
printlines = []
140+
# Track if the new lines have been insterted yet
109141
inserted = False
110142

143+
# Open the PAM config file
111144
with open("/etc/pam.d/common-auth") as fp:
145+
# Read the first line
112146
line = fp.readline()
113-
cnt = 1
147+
114148
while line:
149+
# Add the line to the output directly, we're not deleting anything
115150
outlines.append(line)
116151

117-
if line[:1] != "#":
152+
# Print the comments in gray and don't insert into comments
153+
if line[:1] == "#":
154+
printlines.append("\033[37m" + line + "\033[0m")
155+
else:
118156
printlines.append(line)
119157

158+
# If it's not a comment and we haven't inserted yet
120159
if not inserted:
160+
# Set both the comment and the linking line
121161
line_comment = "# Howdy IR face recognition\n"
122-
line_Link = "auth sufficient pam_python.so /lib/security/howdy/pam.py\n\n"
162+
line_link = "auth sufficient pam_python.so /lib/security/howdy/pam.py\n\n"
123163

164+
# Add them to the output without any markup
124165
outlines.append(line_comment)
125-
outlines.append(line_Link)
166+
outlines.append(line_link)
126167

168+
# Make the print orange to make it clear what's being added
127169
printlines.append("\033[33m" + line_comment + "\033[0m")
128-
printlines.append("\033[33m" + line_Link + "\033[0m")
170+
printlines.append("\033[33m" + line_link + "\033[0m")
129171

172+
# Mark as inserted
130173
inserted = True
131-
else:
132-
printlines.append("\033[37m" + line + "\033[0m")
133174

175+
# Go to the next line
134176
line = fp.readline()
135-
cnt += 1
136177

178+
# Print a file Header
137179
print("\033[33m" + ">>> START OF /etc/pam.d/common-auth" + "\033[0m")
138180

181+
# Loop though all printing lines and use the enters from the file
139182
for line in printlines:
140183
print(line, end="")
141184

185+
# Print a footer
142186
print("\033[33m" + ">>> END OF /etc/pam.d/common-auth" + "\033[0m" + "\n")
143187

188+
# Ask the user if this change is okay
144189
print("Lines will be insterted in /etc/pam.d/common-auth as shown above")
145190
ans = input("Apply this change? [y/N]: ")
146191

192+
# Abort the whole thing if it's not
147193
if (ans.lower() != "y"):
148194
print("Inerpeting as a \"NO\", aborting")
149195
sys.exit()
150196

151197
print("Adding lines to PAM\n")
152198

199+
# Write to PAM
153200
common_auth = open("/etc/pam.d/common-auth", "w")
154201
common_auth.write("".join(outlines))
155202
common_auth.close()
156203

204+
# From here onwards the installation is complete
205+
# We want to gather more information about the types or IR camera's
206+
# used though, and the following lines are data collection
207+
208+
# List all video devices
157209
diag_out = "Video devices [IR=" + picked + "]\n"
158210
diag_out += "```\n"
159211
diag_out += subprocess.check_output(['ls /dev/ | grep video'], shell=True).decode("utf-8")
160212
diag_out += "```\n"
161213

214+
# Get some info from the USB kernel listings
162215
diag_out += "Lsusb output\n"
163216
diag_out += "```\n"
164217
diag_out += subprocess.check_output(['lsusb -vvvv | grep -i "Camera\|iFunction"'], shell=True).decode("utf-8")
165218
diag_out += "```\n"
166219

220+
# Get camera information from video4linux
167221
diag_out += "Udevadm\n"
168222
diag_out += "```\n"
169223
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")
170224
diag_out += "```"
171225

226+
# Print it all as a clickable link to a new github issue
172227
print("https://github.com/Boltgolt/howdy-reports/issues/new?title=Post-installation%20camera%20information&body=" + urllib.parse.quote_plus(diag_out) + "\n")
173228

229+
# Let the user know what to do with the link
174230
print("Installation complete.")
175231
print("If you want to help the development, please use the link above to post some camera-related information to github")
176232

177-
# Remove the installer if downloaded to tmp
233+
# Remove the installer if it was downloaded to /tmp
178234
if os.path.exists("/tmp/howdy_install.py"):
179235
os.remove("/tmp/howdy_install.py")

uninstall.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,36 @@
1+
# Completely remove howdy from the system
2+
3+
# Import required modules
14
import subprocess
5+
import sys
6+
import os
7+
8+
# Check if we're running as root
9+
user = os.getenv("SUDO_USER")
10+
if user is None:
11+
print("Please run the uninstaller as a sudo user")
12+
sys.exit()
13+
14+
# Double check with the user for the last time
15+
print("This will remove Howdy and all models generated with it")
16+
ans = input("Do you want to continue? [y/N]: ")
17+
18+
# Abort if they don't say yes
19+
if (ans.lower() != "y"):
20+
sys.exit()
221

22+
# Remove files and symlinks
323
subprocess.call(["rm -rf /lib/security/howdy/"], shell=True)
424
subprocess.call(["rm /usr/bin/howdy"], shell=True)
25+
subprocess.call(["rm /etc/bash_completion.d/howdy"], shell=True)
26+
27+
# Remove face_recognition and dlib
28+
subprocess.call(["pip3 uninstall face_recognition dlib -y"], shell=True)
29+
30+
# Print a tearbending message
31+
print("""
32+
Howdy has been uninstalled :'(
33+
34+
There are still lines in /etc/pam.d/common-auth that can't be removed automatically
35+
Run "nano /etc/pam.d/common-auth" to remove them by hand\
36+
""")

0 commit comments

Comments
 (0)