1
1
#!/usr/bin/env python
2
2
3
- # _ _ _ _ _
3
+ # _ _ _ _ _
4
4
# | | | | (_) | |
5
5
# _ _ ___| |__ | | _ _| | |
6
6
# | | | |/___) _ \| |_/ ) | | |
@@ -92,11 +92,11 @@ def __add__(self, other):
92
92
93
93
def log (settings , msg ):
94
94
log_file = settings ['log_file' ]
95
-
95
+
96
96
contents = '\n {0} {1}\n Current state:\n ' .format (str (datetime .now ()), msg )
97
97
with open (log_file , 'a+' ) as log :
98
98
log .write (contents )
99
-
99
+
100
100
# Log current USB state
101
101
if CURRENT_PLATFORM .startswith ("DARWIN" ):
102
102
os .system ("system_profiler SPUSBDataType >> " + log_file )
@@ -105,7 +105,7 @@ def log(settings, msg):
105
105
106
106
def shred (settings ):
107
107
shredder = settings ['remove_file_cmd' ]
108
-
108
+
109
109
# List logs and settings to be removed
110
110
if settings ['melt_usbkill' ]:
111
111
settings ['folders_to_remove' ].append (os .path .dirname (settings ['log_file' ]))
@@ -116,39 +116,39 @@ def shred(settings):
116
116
else :
117
117
settings ['files_to_remove' ].append (os .path .realpath (__file__ ))
118
118
settings ['files_to_remove' ].append (usbkill_folder + "/usbkill.ini" )
119
-
119
+
120
120
# Remove files and folders
121
121
for _file in settings ['files_to_remove' ] + settings ['folders_to_remove' ]:
122
122
os .system (shredder + _file )
123
-
123
+
124
124
def kill_computer (settings ):
125
125
# Log what is happening:
126
126
if not settings ['melt_usbkill' ]: # No need to spend time on logging if logs will be removed
127
127
log (settings , "Detected a USB change. Dumping the list of connected devices and killing the computer..." )
128
-
128
+
129
129
# Shred as specified in settings
130
130
shred (settings )
131
-
131
+
132
132
# Execute kill commands in order.
133
133
for command in settings ['kill_commands' ]:
134
134
os .system (command )
135
-
135
+
136
136
if settings ['do_sync' ]:
137
137
# Sync the filesystem to save recent changes
138
138
os .system ("sync" )
139
139
else :
140
140
# If syncing is risky because it might take too long, then sleep for 5ms.
141
141
# This will still allow for syncing in most cases.
142
142
sleep (0.05 )
143
-
143
+
144
144
# Wipe ram and/or swap
145
145
if settings ['do_wipe_ram' ] and settings ['do_wipe_swap' ]:
146
146
os .system (settings ['wipe_ram_cmd' ] + " & " + settings ['wipe_swap_cmd' ])
147
147
elif settings ['do_wipe_ram' ]:
148
148
os .system (settings ['wipe_ram_cmd' ])
149
149
elif settings ['do_wipe_swap' ]:
150
150
os .system (settings ['wipe_swap_cmd' ])
151
-
151
+
152
152
if settings ['shut_down' ]: # (Use argument --no-shut-down to prevent a shutdown.)
153
153
# Finally poweroff computer immediately
154
154
if CURRENT_PLATFORM .startswith ("DARWIN" ):
@@ -160,7 +160,7 @@ def kill_computer(settings):
160
160
else :
161
161
# Linux-based systems - Will shutdown
162
162
os .system ("poweroff -f" )
163
-
163
+
164
164
# Exit the process to prevent executing twice (or more) all commands
165
165
sys .exit (0 )
166
166
@@ -180,7 +180,7 @@ def check_inside(result, devices):
180
180
try :
181
181
result ["Built-in_Device" ]
182
182
except KeyError :
183
-
183
+
184
184
# Check if vendor_id/product_id is available for this one
185
185
try :
186
186
# Ensure vendor_id and product_id are present
@@ -209,15 +209,15 @@ def check_inside(result, devices):
209
209
for result_deep in result ["_items" ]:
210
210
# Check what's inside the _items array
211
211
check_inside (result_deep , devices )
212
-
212
+
213
213
except KeyError : {}
214
-
214
+
215
215
# Run the loop
216
216
devices = []
217
217
for result in df [0 ]["_items" ]:
218
218
check_inside (result , devices )
219
219
return devices
220
-
220
+
221
221
def lsusb ():
222
222
# A Python version of the command 'lsusb' that returns a list of connected usbids
223
223
if CURRENT_PLATFORM .startswith ("DARWIN" ):
@@ -230,9 +230,9 @@ def lsusb():
230
230
def program_present (program ):
231
231
if sys .version_info [0 ] == 3 :
232
232
# Python3
233
- from shutil import which
233
+ from shutil import which
234
234
return which (program ) != None
235
-
235
+
236
236
else :
237
237
"""
238
238
Test if an executable exist in Python2
@@ -251,7 +251,7 @@ def is_exe(fpath):
251
251
if is_exe (exe_file ):
252
252
return True
253
253
return False
254
-
254
+
255
255
def load_settings (filename ):
256
256
# Libraries that are only needed in this function:
257
257
from json import loads as jsonloads
@@ -287,7 +287,7 @@ def get_setting(name, gtype=''):
287
287
288
288
# Read all lines of settings file
289
289
config .read (filename )
290
-
290
+
291
291
# Build settings
292
292
settings = dict ({
293
293
'sleep_time' : get_setting ('sleep' , 'FLOAT' ),
@@ -300,26 +300,26 @@ def get_setting(name, gtype=''):
300
300
'do_sync' : get_setting ('do_sync' , 'BOOL' ),
301
301
'kill_commands' : jsonloads (get_setting ('kill_commands' ).strip ())
302
302
})
303
-
303
+
304
304
settings ['do_wipe_ram' ] = False
305
305
if get_setting ('do_wipe_ram' , 'BOOL' ):
306
306
settings ['do_wipe_ram' ] = True
307
307
settings ['wipe_ram_cmd' ] = get_setting ('wipe_ram_cmd' ) + " "
308
-
308
+
309
309
settings ['do_wipe_swap' ] = False
310
310
if get_setting ('do_wipe_swap' , 'BOOL' ):
311
311
settings ['do_wipe_swap' ] = True
312
312
settings ['wipe_swap_cmd' ] = get_setting ('wipe_swap_cmd' ) + " "
313
313
314
314
return settings
315
-
315
+
316
316
def loop (settings ):
317
317
# Main loop that checks every 'sleep_time' seconds if computer should be killed.
318
318
# Allows only whitelisted usb devices to connect!
319
319
# Does not allow usb device that was present during program start to disconnect!
320
320
start_devices = lsusb ()
321
321
acceptable_devices = start_devices + settings ['whitelist' ]
322
-
322
+
323
323
# Write to logs that loop is starting:
324
324
msg = "[INFO] Started patrolling the USB ports every " + str (settings ['sleep_time' ]) + " seconds..."
325
325
log (settings , msg )
@@ -331,7 +331,7 @@ def loop(settings):
331
331
current_devices = lsusb ()
332
332
333
333
# Check that all current devices are in the set of acceptable devices
334
- # and their cardinality is less than or equal to what is allowed
334
+ # and their cardinality is less than or equal to what is allowed
335
335
for device , count in current_devices .items ():
336
336
if device not in acceptable_devices :
337
337
# A device with unknown usbid detected
@@ -341,15 +341,15 @@ def loop(settings):
341
341
kill_computer (settings )
342
342
343
343
# Check that all start devices are still present in current devices
344
- # and their cardinality still the same
344
+ # and their cardinality still the same
345
345
for device , count in start_devices .items ():
346
346
if device not in current_devices :
347
347
# A usbid has disappeared completely
348
348
kill_computer (settings )
349
349
if count > current_devices [device ]:
350
350
# Count of a usbid device is lower than at program start (not enough devices for given usbid)
351
351
kill_computer (settings )
352
-
352
+
353
353
sleep (settings ['sleep_time' ])
354
354
355
355
def startup_checks ():
@@ -363,26 +363,26 @@ def startup_checks():
363
363
364
364
# Check arguments
365
365
args = sys .argv [1 :]
366
-
367
- # Check for help
366
+
367
+ # Check for help
368
368
if '-h' in args or '--help' in args :
369
369
sys .exit (help_message )
370
-
370
+
371
371
if '--version' in args :
372
372
print ('usbkill' , __version__ )
373
373
sys .exit (0 )
374
-
374
+
375
375
copy_settings = False
376
376
if '--cs' in args :
377
377
args .remove ('--cs' )
378
378
copy_settings = True
379
-
379
+
380
380
shut_down = True
381
381
if '--no-shut-down' in args :
382
382
print ("[NOTICE] Ready to execute all the (potentially destructive) commands, but NOT shut down the computer." )
383
383
args .remove ('--no-shut-down' )
384
384
shut_down = False
385
-
385
+
386
386
# Check all other args
387
387
if len (args ) > 0 :
388
388
sys .exit ("\n [ERROR] Argument not understood. Can only understand -h\n " )
@@ -408,17 +408,17 @@ def startup_checks():
408
408
sys .exit ("\n [ERROR] You have lost your settings file. Get a new copy of the usbkill.ini and place it in /etc/ or in " + sources_path + "/\n " )
409
409
print ("[NOTICE] Copying install/setting.ini to " + SETTINGS_FILE )
410
410
os .system ("cp " + sources_path + "install/usbkill.ini " + SETTINGS_FILE )
411
-
411
+
412
412
# Load settings
413
413
settings = load_settings (SETTINGS_FILE )
414
414
settings ['shut_down' ] = shut_down
415
-
415
+
416
416
# Make sure no spaces a present in paths to be wiped.
417
417
for name in settings ['folders_to_remove' ] + settings ['files_to_remove' ]:
418
418
if ' ' in name :
419
419
msg += "[ERROR][WARNING] '" + name + "'as specified in your usbkill.ini contains a space.\n "
420
420
sys .exit (msg )
421
-
421
+
422
422
# Make sure srm is present if it will be used.
423
423
if settings ['melt_usbkill' ] or len (settings ['folders_to_remove' ] + settings ['files_to_remove' ]) > 0 :
424
424
if not program_present ('srm' ):
@@ -437,32 +437,30 @@ def startup_checks():
437
437
sys .exit ("[ERROR] usbkill configured to destroy data, but srm not installed.\n " )
438
438
if not settings ['wipe_swap_cmd' ].startswith ('sswap' ):
439
439
sys .exit ("[ERROR] wipe_swap_cmd should start with `sswap'. sswap should be used for automated data overwrite.\n " )
440
-
440
+
441
441
# Make sure there is a logging folder
442
442
log_folder = os .path .dirname (settings ['log_file' ])
443
443
if not os .path .isdir (log_folder ):
444
444
os .mkdir (log_folder )
445
-
445
+
446
446
return settings
447
447
448
448
def go ():
449
449
# Run startup checks and load settings
450
450
settings = startup_checks ()
451
-
451
+
452
452
# Define exit handler now that settings are loaded...
453
453
def exit_handler (signum , frame ):
454
454
print ("\n [INFO] Exiting because exit signal was received\n " )
455
455
log (settings , "[INFO] Exiting because exit signal was received" )
456
456
sys .exit (0 )
457
-
457
+
458
458
# Register handlers for clean exit of program
459
459
for sig in [signal .SIGINT , signal .SIGTERM , signal .SIGQUIT , ]:
460
460
signal .signal (sig , exit_handler )
461
-
461
+
462
462
# Start main loop
463
463
loop (settings )
464
-
464
+
465
465
if __name__ == "__main__" :
466
466
go ()
467
-
468
-
0 commit comments