Issues with decrypting project

Pappy is no longer reading the salt correctly, and now fails out
when raising an exception. Need to fix exception handling.
master
Nich 8 years ago
parent 61dc550f9e
commit 2df463fc79
  1. 14
      pappyproxy/config.py
  2. 38
      pappyproxy/crypto.py
  3. 19
      pappyproxy/pappy.py

@ -130,14 +130,11 @@ class PappyConfig(object):
:Default: False :Default: False
.. data: salt_file .. data: salt_len
Clear-text file containing the salt generated for key derivation. A new salt Length of the nonce-salt value appended to the end of `crypt_file`
will be generated each time the project is encrypted. After successfully
decrypting the project file (``project.crypt``), the salt file (``project.salt``)
will be deleted.
:Default: ``project.salt`` :Default: 16
""" """
def __init__(self): def __init__(self):
@ -170,8 +167,7 @@ class PappyConfig(object):
self.crypt_dir = 'crypt' self.crypt_dir = 'crypt'
self.crypt_file = 'project.crypt' self.crypt_file = 'project.crypt'
self.crypt_session = False self.crypt_session = False
self.crypt_success = False self.salt_len = 16
self.salt_file = 'project.salt'
def get_default_config(self): def get_default_config(self):
default_config_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), default_config_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
@ -185,8 +181,6 @@ class PappyConfig(object):
pp = os.getcwd() + os.sep pp = os.getcwd() + os.sep
project_files = [pp+f for f in file_glob if os.path.isfile(pp+f)] project_files = [pp+f for f in file_glob if os.path.isfile(pp+f)]
if self.salt_file in project_files:
project_files.remove(self.salt_file)
if self.crypt_file in project_files: if self.crypt_file in project_files:
project_files.remove(self.crypt_file) project_files.remove(self.crypt_file)

@ -1,6 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
import crochet import crochet
import getpass
import glob import glob
import os import os
import pappyproxy import pappyproxy
@ -55,6 +56,7 @@ class Crypto(object):
# Delete clear-text files # Delete clear-text files
self.delete_clear_files() self.delete_clear_files()
return True
def decrypt_project(self): def decrypt_project(self):
""" """
@ -74,7 +76,10 @@ class Crypto(object):
# Otherwise, decrypt and decompress the project # Otherwise, decrypt and decompress the project
else: else:
archive_crypt = open(self.config.crypt_file, 'rb').read() cf = self.config.crypt_file
sl = self.config.salt_len
crl = os.path.getsize(cf) - sl
archive_crypt = open(cf, 'rb').read(crl)
archive_file = open(self.config.archive, 'wb') archive_file = open(self.config.archive, 'wb')
retries = 3 retries = 3
@ -103,11 +108,7 @@ class Crypto(object):
self.compressor.decompress_project() self.compressor.decompress_project()
# Force generation of new salt and crypt archive
self.delete_crypt_files()
os.chdir(self.config.crypt_dir) os.chdir(self.config.crypt_dir)
self.config.crypt_success = True
return True return True
def confirm_password_retry(self): def confirm_password_retry(self):
@ -130,27 +131,40 @@ class Crypto(object):
""" """
encoded_passwd = "" encoded_passwd = ""
try: try:
passwd = raw_input("Enter a password: ").strip() passwd = getpass.getpass("Enter a password: ").strip()
self.password = passwd.encode("utf-8") self.password = passwd.encode("utf-8")
except: except:
raise PappyException("Invalid password, try again") raise PappyException("Invalid password, try again")
def set_salt(self): def set_salt(self):
if os.path.isfile(self.config.salt_file): if os.path.isfile(self.config.crypt_file):
self.set_salt_from_file() self.set_salt_from_file()
else: else:
self.salt = os.urandom(16) self.salt = os.urandom(16)
def set_salt_from_file(self): def set_salt_from_file(self):
try: try:
salt_file = open(self.config.salt_file, 'rb') # Seek to `salt_len` bytes before the EOF
self.salt = salt_file.readline().strip() # then read `salt_len` bytes to retrieve the salt
# WARNING: must open `crypt_file` in `rb` mode
# or `salt_file.seek()` will result in undefined
# behavior.
salt_file = open(self.config.crypt_file, 'rb')
sl = self.config.salt_len
salt_file.seek(sl, 2)
self.salt = salt_file.read(sl)
except: except:
raise PappyException("Unable to read project.salt") cf = self.config.crypt_file
raise PappyException("Unable to read %s" % cf)
def create_salt_file(self): def create_salt_file(self):
salt_file = open(self.config.salt_file, 'wb') # WARNING: must open `crypt_file` in `wb` mode
# or `salt_file.seek()` will result in undefined
# behavior.
salt_file = open(self.config.crypt_file, 'wb')
# Seek to the end of the encrypted archive
salt_file.seek(0,2)
salt_file.write(self.salt) salt_file.write(self.salt)
salt_file.close() salt_file.close()

@ -26,6 +26,7 @@ from . import context
from . import crypto from . import crypto
from . import http from . import http
from .console import ProxyCmd from .console import ProxyCmd
from .util import PappyException
from twisted.enterprise import adbapi from twisted.enterprise import adbapi
from twisted.internet import reactor, defer from twisted.internet import reactor, defer
from twisted.internet.error import CannotListenError from twisted.internet.error import CannotListenError
@ -71,9 +72,7 @@ class PappySession(object):
from . import proxy, plugin from . import proxy, plugin
if self.config.crypt_session: if self.config.crypt_session:
self.decrypt() if self.decrypt():
if self.config.crypt_success:
self.config.load_from_file('./config.json') self.config.load_from_file('./config.json')
self.config.global_load_from_file() self.config.global_load_from_file()
self.delete_data_on_quit = False self.delete_data_on_quit = False
@ -150,17 +149,23 @@ class PappySession(object):
self.complete_defer = deferToThread(self.cons.cmdloop) self.complete_defer = deferToThread(self.cons.cmdloop)
self.complete_defer.addCallback(self.cleanup) self.complete_defer.addCallback(self.cleanup)
@defer.inlineCallbacks
def encrypt(self): def encrypt(self):
yield self.crypto.encrypt_project() if self.crypto.encrypt_project():
return True
else:
errmsg = "There was an issue encrypting the project."
raise PappyException(errmsg)
reactor.stop()
defer.returnValue(None)
@defer.inlineCallbacks
def decrypt(self): def decrypt(self):
# Attempt to decrypt project archive # Attempt to decrypt project archive
if self.crypto.decrypt_project(): if self.crypto.decrypt_project():
yield True return True
# Quit pappy on failure # Quit pappy on failure
else: else:
errmsg = "There was an issue encrypting the project."
raise PappyException(errmsg)
reactor.stop() reactor.stop()
defer.returnValue(None) defer.returnValue(None)

Loading…
Cancel
Save