From 3ebb6be0c628b3a2b45a28690b6b6dc1bb2ae850 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Sun, 12 Oct 2014 03:21:47 -0500 Subject: Basic validation levels support --- src/leap/keymanager/validation.py | 94 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/leap/keymanager/validation.py (limited to 'src/leap/keymanager/validation.py') diff --git a/src/leap/keymanager/validation.py b/src/leap/keymanager/validation.py new file mode 100644 index 0000000..6dceb78 --- /dev/null +++ b/src/leap/keymanager/validation.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# __init__.py +# Copyright (C) 2014 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Validation levels implementation for key managment. + +See: + https://lists.riseup.net/www/arc/leap-discuss/2014-09/msg00000.html +""" + + +from datetime import datetime +from enum import Enum + + +ValidationLevel = Enum( + "Weak_Chain", + "Provider_Trust", + "Provider_Endorsement", + "Third_Party_Endorsement", + "Third_Party_Consensus", + "Historically_Auditing", + "Known_Key", + "Fingerprint") + + +def toValidationLevel(value): + """ + Convert a string representation of a validation level into + C{ValidationLevel} + + :param value: validation level + :type value: str + :rtype: ValidationLevel + :raises ValueError: if C{value} is not a validation level + """ + for level in ValidationLevel: + if value == str(level): + return level + raise ValueError("Not valid validation level: %s" % (value,)) + + +def can_upgrade(new_key, old_key): + """ + :type new_key: EncryptionKey + :type old_key: EncryptionKey + :rtype: bool + """ + # XXX not succesfully used and strict high validation level (#6211) + # XXX implement key signature checking (#6120) + + # First contact + if old_key is None: + return True + + if new_key.address != old_key.address: + # XXX how do we map multiple IDs? (#6212) + return False + + # An update of the same key + if new_key.fingerprint == old_key.fingerprint: + # XXX wich one is newer? is that a downgrade attack? (#6210) + return True + + # Manually verified fingerprint + if new_key.validation == ValidationLevel.Fingerprint: + return True + + # Expired key and higher validation level + if old_key.expiry_date: + old_expiry_date = datetime.fromtimestamp(int(old_key.expiry_date)) + if (old_expiry_date < datetime.now() and + new_key.validation >= old_key.validation): + return True + + # No expiration date and higher validation level + elif new_key.validation >= old_key.validation: + return True + + return False -- cgit v1.2.3 From d9df76ea2504a78865209cda3ae6e41613d5e5aa Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Thu, 30 Oct 2014 21:54:32 -0600 Subject: Merge keys when updating an exisiting key This is needed to prevent roll back attacks where the attacker push us to accept a key with an old expiration date that could be use to push an untrusted key when after it's expiration. --- src/leap/keymanager/validation.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src/leap/keymanager/validation.py') diff --git a/src/leap/keymanager/validation.py b/src/leap/keymanager/validation.py index 6dceb78..7d68966 100644 --- a/src/leap/keymanager/validation.py +++ b/src/leap/keymanager/validation.py @@ -73,7 +73,6 @@ def can_upgrade(new_key, old_key): # An update of the same key if new_key.fingerprint == old_key.fingerprint: - # XXX wich one is newer? is that a downgrade attack? (#6210) return True # Manually verified fingerprint -- cgit v1.2.3 From c223cca848e854d0015314ef517a6a4f928a2d0a Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Tue, 4 Nov 2014 11:53:56 -0600 Subject: Use datetime for key expiration --- src/leap/keymanager/validation.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/leap/keymanager/validation.py') diff --git a/src/leap/keymanager/validation.py b/src/leap/keymanager/validation.py index 7d68966..cf5b4a8 100644 --- a/src/leap/keymanager/validation.py +++ b/src/leap/keymanager/validation.py @@ -80,11 +80,10 @@ def can_upgrade(new_key, old_key): return True # Expired key and higher validation level - if old_key.expiry_date: - old_expiry_date = datetime.fromtimestamp(int(old_key.expiry_date)) - if (old_expiry_date < datetime.now() and - new_key.validation >= old_key.validation): - return True + if (old_key.expiry_date is not None and + old_key.expiry_date < datetime.now() and + new_key.validation >= old_key.validation): + return True # No expiration date and higher validation level elif new_key.validation >= old_key.validation: -- cgit v1.2.3 From f07d407523e6b76076824fa53e4c3568bc88764f Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Mon, 10 Nov 2014 18:36:59 -0600 Subject: Implement multi uid support --- src/leap/keymanager/validation.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/leap/keymanager/validation.py') diff --git a/src/leap/keymanager/validation.py b/src/leap/keymanager/validation.py index cf5b4a8..245013e 100644 --- a/src/leap/keymanager/validation.py +++ b/src/leap/keymanager/validation.py @@ -67,10 +67,6 @@ def can_upgrade(new_key, old_key): if old_key is None: return True - if new_key.address != old_key.address: - # XXX how do we map multiple IDs? (#6212) - return False - # An update of the same key if new_key.fingerprint == old_key.fingerprint: return True -- cgit v1.2.3 From c6e5296ed7e9c5021d09dde381d77d2d17d5715d Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Fri, 19 Dec 2014 07:38:42 -0600 Subject: Fix key upgrade on no expiration date and higher validation level --- src/leap/keymanager/validation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/leap/keymanager/validation.py') diff --git a/src/leap/keymanager/validation.py b/src/leap/keymanager/validation.py index 245013e..87de2af 100644 --- a/src/leap/keymanager/validation.py +++ b/src/leap/keymanager/validation.py @@ -82,7 +82,8 @@ def can_upgrade(new_key, old_key): return True # No expiration date and higher validation level - elif new_key.validation >= old_key.validation: + if (old_key.expiry_date is None and + new_key.validation > old_key.validation): return True return False -- cgit v1.2.3 From 963c3afaf1f9674d876465dd4bffc1c11ce1cb51 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Fri, 19 Dec 2014 08:15:43 -0600 Subject: Upgrade keys if not successfully used and strict high validation level --- src/leap/keymanager/validation.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/leap/keymanager/validation.py') diff --git a/src/leap/keymanager/validation.py b/src/leap/keymanager/validation.py index 87de2af..b3aff3e 100644 --- a/src/leap/keymanager/validation.py +++ b/src/leap/keymanager/validation.py @@ -60,7 +60,6 @@ def can_upgrade(new_key, old_key): :type old_key: EncryptionKey :rtype: bool """ - # XXX not succesfully used and strict high validation level (#6211) # XXX implement key signature checking (#6120) # First contact @@ -86,4 +85,9 @@ def can_upgrade(new_key, old_key): new_key.validation > old_key.validation): return True + # Not successfully used and strict high validation level + if (not (old_key.sign_used and old_key.encr_used) and + new_key.validation > old_key.validation): + return True + return False -- cgit v1.2.3 From 6fa8b2a9e7f02c59f794e9dd080fac574841e50b Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Fri, 19 Dec 2014 22:37:40 -0600 Subject: upgrade key when signed by old key --- src/leap/keymanager/validation.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/leap/keymanager/validation.py') diff --git a/src/leap/keymanager/validation.py b/src/leap/keymanager/validation.py index b3aff3e..c6fe478 100644 --- a/src/leap/keymanager/validation.py +++ b/src/leap/keymanager/validation.py @@ -60,8 +60,6 @@ def can_upgrade(new_key, old_key): :type old_key: EncryptionKey :rtype: bool """ - # XXX implement key signature checking (#6120) - # First contact if old_key is None: return True @@ -90,4 +88,8 @@ def can_upgrade(new_key, old_key): new_key.validation > old_key.validation): return True + # New key signed by the old key + if old_key.key_id in new_key.signatures: + return True + return False -- cgit v1.2.3 From 82d027b1f471517213bdcdc773dc8eea677fe330 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Mon, 5 Jan 2015 08:54:24 -0600 Subject: Port validation levels to enum34 --- src/leap/keymanager/validation.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/leap/keymanager/validation.py') diff --git a/src/leap/keymanager/validation.py b/src/leap/keymanager/validation.py index c6fe478..c81d533 100644 --- a/src/leap/keymanager/validation.py +++ b/src/leap/keymanager/validation.py @@ -24,17 +24,17 @@ See: from datetime import datetime -from enum import Enum +from enum import IntEnum -ValidationLevel = Enum( - "Weak_Chain", - "Provider_Trust", - "Provider_Endorsement", - "Third_Party_Endorsement", - "Third_Party_Consensus", - "Historically_Auditing", - "Known_Key", +ValidationLevel = IntEnum("ValidationLevel", + "Weak_Chain " + "Provider_Trust " + "Provider_Endorsement " + "Third_Party_Endorsement " + "Third_Party_Consensus " + "Historically_Auditing " + "Known_Key " "Fingerprint") @@ -49,7 +49,7 @@ def toValidationLevel(value): :raises ValueError: if C{value} is not a validation level """ for level in ValidationLevel: - if value == str(level): + if value == level.name: return level raise ValueError("Not valid validation level: %s" % (value,)) -- cgit v1.2.3 From 58ed7b51ccc63155c166a025336e325fc5ffda77 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Tue, 7 Apr 2015 12:56:20 +0200 Subject: [doc] added the right link the validation levels documentation The mailing list was linked, but now there is a proper documentation page. - Releases: 0.4.0 --- src/leap/keymanager/validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/keymanager/validation.py') diff --git a/src/leap/keymanager/validation.py b/src/leap/keymanager/validation.py index c81d533..dfe6432 100644 --- a/src/leap/keymanager/validation.py +++ b/src/leap/keymanager/validation.py @@ -19,7 +19,7 @@ Validation levels implementation for key managment. See: - https://lists.riseup.net/www/arc/leap-discuss/2014-09/msg00000.html + https://leap.se/en/docs/design/transitional-key-validation """ -- cgit v1.2.3 From d7acaf356d16c795f1481fefc7a75ffc8a36b1d0 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Fri, 26 Jun 2015 18:12:22 +0200 Subject: [bug] remove the dependency on enum34 * Resolves: #7188 --- src/leap/keymanager/validation.py | 73 +++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 22 deletions(-) (limited to 'src/leap/keymanager/validation.py') diff --git a/src/leap/keymanager/validation.py b/src/leap/keymanager/validation.py index dfe6432..3bb4032 100644 --- a/src/leap/keymanager/validation.py +++ b/src/leap/keymanager/validation.py @@ -24,34 +24,63 @@ See: from datetime import datetime -from enum import IntEnum -ValidationLevel = IntEnum("ValidationLevel", - "Weak_Chain " - "Provider_Trust " - "Provider_Endorsement " - "Third_Party_Endorsement " - "Third_Party_Consensus " - "Historically_Auditing " - "Known_Key " - "Fingerprint") +class ValidationLevel(object): + """ + A validation level + + Meant to be used to compare levels or get it's string representation. + """ + def __init__(self, name, value): + self.name = name + self.value = value + + def __cmp__(self, other): + return cmp(self.value, other.value) + + def __str__(self): + return self.name + + def __repr__(self): + return "" % (self.name, self.value) -def toValidationLevel(value): +class _ValidationLevels(object): """ - Convert a string representation of a validation level into - C{ValidationLevel} + Handler class to manage validation levels. It should have only one global + instance 'ValidationLevels'. - :param value: validation level - :type value: str - :rtype: ValidationLevel - :raises ValueError: if C{value} is not a validation level + The levels are attributes of the instance and can be used like: + ValidationLevels.Weak_Chain + ValidationLevels.get("Weak_Chain") """ - for level in ValidationLevel: - if value == level.name: - return level - raise ValueError("Not valid validation level: %s" % (value,)) + _level_names = ("Weak_Chain", + "Provider_Trust", + "Provider_Endorsement", + "Third_Party_Endorsement", + "Third_Party_Consensus", + "Historically_Auditing", + "Known_Key", + "Fingerprint") + + def __init__(self): + for name in self._level_names: + setattr(self, name, + ValidationLevel(name, self._level_names.index(name))) + + def get(self, name): + """ + Get the ValidationLevel of a name + + :param name: name of the level + :type name: str + :rtype: ValidationLevel + """ + return getattr(self, name) + + +ValidationLevels = _ValidationLevels() def can_upgrade(new_key, old_key): @@ -69,7 +98,7 @@ def can_upgrade(new_key, old_key): return True # Manually verified fingerprint - if new_key.validation == ValidationLevel.Fingerprint: + if new_key.validation == ValidationLevels.Fingerprint: return True # Expired key and higher validation level -- cgit v1.2.3 From ec0757c5972588d05224ea2d56d75ee9cd57c41f Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 29 Jun 2015 12:05:51 -0400 Subject: [style] spelling typo --- src/leap/keymanager/validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/keymanager/validation.py') diff --git a/src/leap/keymanager/validation.py b/src/leap/keymanager/validation.py index 3bb4032..734cfce 100644 --- a/src/leap/keymanager/validation.py +++ b/src/leap/keymanager/validation.py @@ -30,7 +30,7 @@ class ValidationLevel(object): """ A validation level - Meant to be used to compare levels or get it's string representation. + Meant to be used to compare levels or get its string representation. """ def __init__(self, name, value): self.name = name -- cgit v1.2.3