diff --git a/lastpass/account.py b/lastpass/account.py index 3ab94d9..d16746f 100644 --- a/lastpass/account.py +++ b/lastpass/account.py @@ -32,6 +32,7 @@ def fields(self): def __str__(self): return "name: {}\n\tusername: {}\n\tpassword: {}\n\turl: {}\n\tgroup: {}\n\tnotes: {}".format(self.name, self.username, self.password, self.url, self.group, self.notes_string()) + class SecureNote(Account): """ Lastpass Secure Note @@ -43,4 +44,4 @@ def __str__(self): try: return getattr(self, 'unparsed_notes_0').decode() except AttributeError: - return '\n'.join( [ '\t\t{}: {}'.format(field, getattr(self, field).decode() ) for field in self.fields() ] ) + return '\n'.join(['\t\t{}: {}'.format(field, getattr(self, field).decode()) for field in self.fields()]) diff --git a/lastpass/fetcher.py b/lastpass/fetcher.py index d395fd2..859b7f1 100644 --- a/lastpass/fetcher.py +++ b/lastpass/fetcher.py @@ -60,7 +60,7 @@ def request_iteration_count(username, web_client=http): try: count = int(response.content) - except: + except Exception: raise InvalidResponseError('Key iteration count is invalid') if count > 0: diff --git a/lastpass/parser.py b/lastpass/parser.py index 3a60b55..c4e9f1d 100644 --- a/lastpass/parser.py +++ b/lastpass/parser.py @@ -43,6 +43,7 @@ compress = zlib.compress decompress = zlib.decompress + def extract_chunks(blob): """Splits the blob into chucks grouped by kind.""" chunks = [] @@ -150,7 +151,7 @@ def parse_secure_note_server(notes): info[last_field] = b'' if last_field: old_bytes = info[last_field] - info[last_field] = (old_bytes.decode()+'\n'+line.decode()).encode() + info[last_field] = (old_bytes.decode() + '\n' + line.decode()).encode() continue # Split only once so that strings like "Hostname:host.example.com:80" @@ -242,6 +243,7 @@ def encode_base64(data): b64data = b64encode(data) return b64data + def decode_aes256_plain_auto(data, encryption_key): """Guesses AES cipher (EBC or CBD) from the length of the plain data.""" assert isinstance(data, bytes) @@ -322,10 +324,20 @@ def pad(data): # see http://passingcuriosity.com/2009/aes-encryption-in-python-with-m2crypto/ padded = (BS - len(data) % BS) * chr(BS - len(data) % BS) if isinstance(data, str): - data = str.encode(data, 'latin1') + try: + data = str.encode(data, 'latin1') + except Exception: + data = bytes(data) if isinstance(padded, str): - padded = str.encode(padded, 'latin1') - return data + padded + try: + padded = str.encode(padded, 'latin1') + except Exception: + padded = bytes(data) + try: + result = bytes(data + padded) + except Exception: + result = data + padded + return result def unpad(data): @@ -334,9 +346,13 @@ def unpad(data): """ # see http://passingcuriosity.com/2009/aes-encryption-in-python-with-m2crypto/ if isinstance(data, str): - data = str.encode(data, 'latin1') + try: + data = str.encode(data, 'latin1') + except Exception: + data = bytes(data) return data[0:-ord(data[-1:])] + def decode_aes256(cipher, iv, data, encryption_key): """ Decrypt AES-256 bytes. diff --git a/lastpass/vault.py b/lastpass/vault.py index 5d004a6..df88a9d 100644 --- a/lastpass/vault.py +++ b/lastpass/vault.py @@ -3,6 +3,7 @@ from . import parser from .exceptions import InvalidResponseError + class Vault(object): """ Lastpass Vault diff --git a/scripts/lpass b/scripts/lpass index 25fbc69..c5e5fbe 100755 --- a/scripts/lpass +++ b/scripts/lpass @@ -36,6 +36,7 @@ LastPass CLI in Python. Very Minimal. --------------------------------------------- """ +from __future__ import print_function import argparse import getpass import json @@ -68,8 +69,8 @@ S_WHITE = '\033[37m' S_RESET = '\033[0m' LPASS_ENCRYPTION_KEY = '1234567890ABCDEF' -LPASS_CONFIG_FILE = os.path.expanduser("~/.lpass-config") -LPASS_BLOB_FILE = os.path.expanduser("~/.lpass-blob") +LPASS_CONFIG_FILE = os.getenv('LPASS_CONFIG_FILE', os.path.expanduser("~/.lpass-config")) +LPASS_BLOB_FILE = os.getenv('LPASS_BLOB_FILE', os.path.expanduser("~/.lpass-blob")) CLIENT_ID = None # Usually the IMEI. @@ -138,7 +139,7 @@ def command_login(args): if os.path.exists(LPASS_CONFIG_FILE): if not args.force: raise Exception('Unable to Overwrite Configuration.') - (_, password) = __get_login(args.username, None, args.mfa) + (_, password) = __get_login(args.username, os.getenv('LPASS_PASSWORD', None), args.mfa) __print_message('Logged into {}'.format(__colored(args.username, S_YELLOW))) __write_config(args.username, password, args.mfa) @@ -273,7 +274,7 @@ def main(): parser_login.add_argument('--plaintext-key', default=True, action='store_true') parser_login.add_argument('--mfa', default=False, action='store_true') parser_login.add_argument('--force', '-f', default=False, action='store_true') - parser_login.add_argument('username', type=str, default=None) + parser_login.add_argument('username', type=str, default=os.getenv('LPASS_USER', None)) parser_login.set_defaults(func=command_login) parser_logout = subparsers.add_parser('logout', help='Logout from Lasspass.')