Project

General

Profile

« Previous | Next » 

Revision cf157731

Added by dsorber almost 9 years ago

pwmgr v0.3.0 -- Improved security of encryption/decryption operations, bound ENTER to dialog OK buttons to improve ease of use, and implemented key bindings for common operations.

View differences:

software/pwmgr/pwmgr.py
#!/usr/bin/python3
import glob
import os
import shutil
import subprocess
......
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Pango
from gi.repository import Gtk, Pango, Gdk
MOUNT_PATH = '/mnt/pw_ramdisk'
PWD_FILE_PATH = '/home/dsorber/Desktop/network'
......
ENC_FILE_PATH = '/home/dsorber/Documents/chicken_soup.enc'
SCRATCH_FILE_PATH = '/mnt/pw_ramdisk/chicken_soup.txt'
ENC_TMP_FILE_PATH = '/home/dsorber/Documents/chicken_soup.enc.tmp'
KEY_FILE_PATH = '/mnt/pw_ramdisk/.f05d11ef-000c-45c2-ae14-56b56c23e1c5'
VERSION = '0.0.2'
VERSION = '0.0.3'
class SearchDialog(Gtk.Dialog):
......
box.add(label)
self.entry = Gtk.Entry()
self.entry.set_activates_default(True)
box.add(self.entry)
# Make hitting ENTER trigger the OK button
ok_button = self.get_widget_for_response(response_id=Gtk.ResponseType.OK)
ok_button.set_can_default(True)
ok_button.grab_default()
self.show_all()
......
Gtk.MessageType.QUESTION,
Gtk.ButtonsType.OK_CANCEL,
message)
dialog.set_title(title)
box = dialog.get_content_area()
......
pw_entry.set_visibility(False)
pw_entry.set_invisible_char('*')
pw_entry.set_size_request(200, 0)
pw_entry.set_activates_default(True)
box.add(pw_entry)
#~ box.pack_end(pw_entry, False, False, 0)
# Make hitting ENTER trigger the OK button
ok_button = dialog.get_widget_for_response(response_id=Gtk.ResponseType.OK)
ok_button.set_can_default(True)
ok_button.grab_default()
dialog.show_all()
response = dialog.run()
......
self.create_textview()
self.create_toolbar()
self.create_bottom()
self.connect("key-press-event", self._key_press_event)
self.mounted = False
self.pwd_file_fd = None
self.pwd = None
def _key_press_event(self, widget, event):
keyval = event.keyval
keyval_name = Gdk.keyval_name(keyval)
state = event.state
ctrl = (state & Gdk.ModifierType.CONTROL_MASK)
# Bind existing handlers to keys
if ctrl and keyval_name == 'f':
self.on_search_clicked(widget)
elif ctrl and keyval_name == 'o':
self.open_pwd_file(widget)
elif ctrl and keyval_name == 's':
self.save_pwd_file(widget)
elif ctrl and keyval_name == 'q':
self.close_pwd_file(widget, None)
else:
return False
return True
def create_toolbar(self):
toolbar = Gtk.Toolbar()
......
"""
Open handler
"""
# Get password
self.pwd = get_user_pw(self, 'Please enter your password', 'Password')
if self.pwd is None:
passwd = get_user_pw(self, 'Please enter your password', 'Password')
if passwd is None:
return
#~ print('User entered: {:s}'.format(self.pwd))
if not self.mounted:
os.makedirs(MOUNT_PATH, 0o600, exist_ok=True)
......
subprocess.call(mnt_cmd, shell=True, timeout=5)
self.mounted = True
cmd = 'openssl enc -aes-256-cbc -d -in {:s} -out {:s} -pass pass:{:s}'
cmd = cmd.format(ENC_FILE_PATH, SCRATCH_FILE_PATH, self.pwd)
# Store password
with open(KEY_FILE_PATH, 'w') as pass_wd_file:
pass_wd_file.write(passwd)
os.chmod(KEY_FILE_PATH, 0o600)
# Decrypt password store
cmd = 'openssl enc -aes-256-cbc -d -in {:s} -out {:s} -pass file:{:s}'
cmd = cmd.format(ENC_FILE_PATH, SCRATCH_FILE_PATH, KEY_FILE_PATH)
subprocess.call(cmd, shell=True, timeout=5)
# Open and load file; make textview editable
......
if self.mounted:
# Write the password store datat to the sratch file
with open(SCRATCH_FILE_PATH, 'w') as pwd_file_fd:
pwd_file_fd.write(
self.textbuffer.get_text(self.textbuffer.get_start_iter(),
......
True))
print('Write complete')
cmd = 'openssl enc -aes-256-cbc -salt -in {:s} -out {:s} -pass pass:{:s}'
cmd = cmd.format(SCRATCH_FILE_PATH, ENC_TMP_FILE_PATH, self.pwd)
# Encrypt the password store
cmd = 'openssl enc -aes-256-cbc -salt -in {:s} -out {:s} -pass file:{:s}'
cmd = cmd.format(SCRATCH_FILE_PATH, ENC_TMP_FILE_PATH, KEY_FILE_PATH)
subprocess.call(cmd, shell=True, timeout=5)
print('enc complete')
print('Enc complete')
# Remove the key file, then copy over the encrypted file with the
# just created temp one
os.remove(KEY_FILE_PATH)
os.remove(ENC_FILE_PATH)
os.rename(ENC_TMP_FILE_PATH, ENC_FILE_PATH)
# Clear the buffer and disable the textview
self.textbuffer.set_text('')
self.textview.set_editable(False)
self.textview.set_cursor_visible(False)
def _remove_mount_files(self):
# Remove files in the mount path
for file_ in glob.glob('{:s}/*'.format(MOUNT_PATH)):
os.remove(file_)
def close_pwd_file(self, widget, other):
"""
Close handler
......
#~ response = dialog.run()
#~ dialog.destroy()
# Clear the buffer and disable the textview
self.textbuffer.set_text('')
self.textview.set_editable(False)
self.textview.set_cursor_visible(False)
rand_write_cmd = 'dd if=/dev/urandom of={:s} bs=16M count=1 status=none'
rand_write_cmd = rand_write_cmd.format(os.path.join(MOUNT_PATH, 'data'))
......
zero_write_cmd = zero_write_cmd.format(os.path.join(MOUNT_PATH, 'data'))
if self.mounted:
#~ shutil.rmtree(os.path.join(MOUNT_PATH, '*'), ignore_errors=True)
rm_cmd = 'rm -rf {:s}'.format(os.path.join(MOUNT_PATH, '*'))
subprocess.call(rm_cmd, shell=True, timeout=5)
self._remove_mount_files()
# Overwrite a few times
for ctr in range(10):
print(ctr)
subprocess.call(rand_write_cmd, shell=True, timeout=5)
subprocess.call(rm_cmd, shell=True, timeout=5)
self._remove_mount_files()
subprocess.call(zero_write_cmd, shell=True, timeout=5)
subprocess.call(rm_cmd, shell=True, timeout=5)
self._remove_mount_files()
umount_cmd = 'umount {:s}'.format(MOUNT_PATH)
subprocess.call(umount_cmd, shell=True, timeout=5)
......
match = start.forward_search(text, 0, end)
if match != None:
match_start, match_end = match
match_start, match_end = match
self.textbuffer.apply_tag(self.tag_found, match_start, match_end)
# Scroll so the match appears in the middle of the screen

Also available in: Unified diff