summaryrefslogtreecommitdiff
path: root/keymanager
diff options
context:
space:
mode:
Diffstat (limited to 'keymanager')
-rw-r--r--keymanager/CHANGELOG7
-rw-r--r--keymanager/changes/VERSION_COMPAT0
-rw-r--r--keymanager/src/leap/keymanager/__init__.py3
-rw-r--r--keymanager/src/leap/keymanager/errors.py6
-rw-r--r--keymanager/src/leap/keymanager/openpgp.py83
5 files changed, 67 insertions, 32 deletions
diff --git a/keymanager/CHANGELOG b/keymanager/CHANGELOG
index e20b86c8..a081cc50 100644
--- a/keymanager/CHANGELOG
+++ b/keymanager/CHANGELOG
@@ -1,3 +1,10 @@
+0.3.7 Dec 6:
+ o Fix error return values on openpgp backend.
+ o Remove address check when sending email and rely in the email
+ client to verify that is correct. Closes #4491.
+ o Support sending encrypted mails to addresses using the '+' sign.
+ o Improve exception names and handling.
+
0.3.6 Nov 15:
o Default encoding to 'utf-8' in case of system encodings not
set. Closes #4427.
diff --git a/keymanager/changes/VERSION_COMPAT b/keymanager/changes/VERSION_COMPAT
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/keymanager/changes/VERSION_COMPAT
diff --git a/keymanager/src/leap/keymanager/__init__.py b/keymanager/src/leap/keymanager/__init__.py
index dbc54891..6cfbf710 100644
--- a/keymanager/src/leap/keymanager/__init__.py
+++ b/keymanager/src/leap/keymanager/__init__.py
@@ -425,6 +425,9 @@ class KeyManager(object):
:type data: str
:param privkey: The key used to decrypt.
:type privkey: OpenPGPKey
+ :param passphrase: The passphrase for the secret key used for
+ decryption.
+ :type passphrase: str
:param verify: The key used to verify a signature.
:type verify: OpenPGPKey
diff --git a/keymanager/src/leap/keymanager/errors.py b/keymanager/src/leap/keymanager/errors.py
index 27180dbd..ebe4fd5e 100644
--- a/keymanager/src/leap/keymanager/errors.py
+++ b/keymanager/src/leap/keymanager/errors.py
@@ -58,21 +58,21 @@ class InvalidSignature(Exception):
pass
-class EncryptionFailed(Exception):
+class EncryptError(Exception):
"""
Raised upon failures of encryption.
"""
pass
-class DecryptionFailed(Exception):
+class DecryptError(Exception):
"""
Raised upon failures of decryption.
"""
pass
-class EncryptionDecryptionFailed(Exception):
+class GPGError(Exception):
"""
Raised upon failures of encryption/decryption.
"""
diff --git a/keymanager/src/leap/keymanager/openpgp.py b/keymanager/src/leap/keymanager/openpgp.py
index f6223d57..856b21e4 100644
--- a/keymanager/src/leap/keymanager/openpgp.py
+++ b/keymanager/src/leap/keymanager/openpgp.py
@@ -297,7 +297,11 @@ class OpenPGPScheme(EncryptionScheme):
:rtype: OpenPGPKey
@raise KeyNotFound: If the key was not found on local storage.
"""
- leap_assert(is_address(address), 'Not an user address: %s' % address)
+ # Remove the identity suffix after the '+' until the '@'
+ # e.g.: test_user+something@provider.com becomes test_user@probider.com
+ # since the key belongs to the identity without the '+' suffix.
+ address = re.sub(r'\+.*\@', '@', address)
+
doc = self._get_key_doc(address, private)
if doc is None:
raise errors.KeyNotFound(address)
@@ -337,6 +341,7 @@ class OpenPGPScheme(EncryptionScheme):
leap_assert(match is not None, 'No user address in key data.')
address = match.group(1)
+ openpgp_privkey = None
if privkey is not None:
match = re.match(mail_regex, privkey['uids'].pop())
leap_assert(match is not None, 'No user address in key data.')
@@ -370,6 +375,7 @@ class OpenPGPScheme(EncryptionScheme):
"""
leap_assert_type(key_data, (str, unicode))
+ openpgp_privkey = None
try:
openpgp_pubkey, openpgp_privkey = self.parse_ascii_key(key_data)
except (errors.KeyAddressMismatch, errors.KeyFingerprintMismatch) as e:
@@ -465,14 +471,18 @@ class OpenPGPScheme(EncryptionScheme):
def _assert_gpg_result_ok(result):
"""
Check if GPG result is 'ok' and log stderr outputs.
- :param result: The GPG results
- :type result:
+
+ :param result: GPG results, which have a field calld 'ok' that states
+ whether the gpg operation was successful or not.
+ :type result: object
+
+ :raise GPGError: Raised when the gpg operation was not successful.
"""
stderr = getattr(result, 'stderr', None)
if stderr:
logger.debug("%s" % (stderr,))
if getattr(result, 'ok', None) is not True:
- raise errors.EncryptionDecryptionFailed(
+ raise errors.GPGError(
'Failed to encrypt/decrypt: %s' % stderr)
def encrypt(self, data, pubkey, passphrase=None, sign=None,
@@ -491,6 +501,8 @@ class OpenPGPScheme(EncryptionScheme):
:return: The encrypted data.
:rtype: str
+
+ :raise EncryptError: Raised if failed encrypting for some reason.
"""
leap_assert_type(pubkey, OpenPGPKey)
leap_assert(pubkey.private is False, 'Key is not public.')
@@ -509,8 +521,12 @@ class OpenPGPScheme(EncryptionScheme):
# in the ciphertext.
# result.ok - (bool) indicates if the operation succeeded
# result.data - (bool) contains the result of the operation
- self._assert_gpg_result_ok(result)
- return result.data
+ try:
+ self._assert_gpg_result_ok(result)
+ return result.data
+ except errors.GPGError as e:
+ logger.error('Failed to decrypt: %s.' % str(e))
+ raise error.EncryptError()
def decrypt(self, data, privkey, passphrase=None, verify=None):
"""
@@ -520,14 +536,18 @@ class OpenPGPScheme(EncryptionScheme):
:type data: str
:param privkey: The key used to decrypt.
:type privkey: OpenPGPKey
+ :param passphrase: The passphrase for the secret key used for
+ decryption.
+ :type passphrase: str
:param verify: The key used to verify a signature.
:type verify: OpenPGPKey
:return: The decrypted data.
:rtype: unicode
- @raise InvalidSignature: Raised if unable to verify the signature with
- C{verify} key.
+ :raise DecryptError: Raised if failed decrypting for some reason.
+ :raise InvalidSignature: Raised if unable to verify the signature with
+ C{verify} key.
"""
leap_assert(privkey.private is True, 'Key is not private.')
keys = [privkey]
@@ -536,26 +556,31 @@ class OpenPGPScheme(EncryptionScheme):
leap_assert(verify.private is False)
keys.append(verify)
with self._temporary_gpgwrapper(keys) as gpg:
- result = gpg.decrypt(
- data, passphrase=passphrase, always_trust=True)
- self._assert_gpg_result_ok(result)
- # verify signature
- if (verify is not None):
- if result.valid is False or \
- verify.fingerprint != result.pubkey_fingerprint:
- raise errors.InvalidSignature(
- 'Failed to verify signature with key %s: %s' %
- (verify.key_id, stderr))
-
- # XXX: this is the encoding used by gpg module
- # https://github.com/isislovecruft/python-gnupg/\
- # blob/master/gnupg/_meta.py#L121
- encoding = locale.getpreferredencoding()
- if encoding is None:
- encoding = sys.stdin.encoding
- if encoding is None:
- encoding = 'utf-8'
- return result.data.decode(encoding, 'replace')
+ try:
+ result = gpg.decrypt(
+ data, passphrase=passphrase, always_trust=True)
+ self._assert_gpg_result_ok(result)
+ # verify signature
+ if (verify is not None):
+ if result.valid is False or \
+ verify.fingerprint != result.pubkey_fingerprint:
+ raise errors.InvalidSignature(
+ 'Failed to verify signature with key %s: %s' %
+ (verify.key_id, result.stderr))
+
+ # XXX: this is the encoding used by gpg module
+ # https://github.com/isislovecruft/python-gnupg/\
+ # blob/master/gnupg/_meta.py#L121
+ encoding = locale.getpreferredencoding()
+ if encoding is None:
+ encoding = sys.stdin.encoding
+ if encoding is None:
+ encoding = 'utf-8'
+ return result.data.decode(encoding, 'replace')
+ except errors.GPGError as e:
+ logger.error('Failed to decrypt: %s.' % str(e))
+ raise errors.DecryptError(str(e))
+
def is_encrypted(self, data):
"""
@@ -608,7 +633,7 @@ class OpenPGPScheme(EncryptionScheme):
if result.fingerprint is None:
raise errors.SignFailed(
'Failed to sign with key %s: %s' %
- (privkey['keyid'], stderr))
+ (privkey['keyid'], result.stderr))
leap_assert(
result.fingerprint == kfprint,
'Signature and private key fingerprints mismatch: '