commit: adcf14d0464bf339541542338f32425f3b0dabae
Author: Pavlos Ratis <dastergon <AT> gentoo <DOT> org>
AuthorDate: Sun Aug 17 00:18:14 2014 +0000
Commit: Brian Dolbec <brian.dolbec <AT> gmail <DOT> com>
CommitDate: Sun Aug 17 00:20:35 2014 +0000
URL:
http://sources.gentoo.org/gitweb/?p=proj/gentoo-keys.git;a=commit;h=adcf14d0
add support for gkey checks
Features:
* Enable colons listing
* Checks for expired, invalid and revoked keys
* Checks for keys capabilities
---
gkeys/actions.py | 38 +++++++++++++++++++++++++++++++++++++-
gkeys/lib.py | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 88 insertions(+), 4 deletions(-)
diff --git a/gkeys/actions.py b/gkeys/actions.py
index b80f203..030424f 100644
--- a/gkeys/actions.py
+++ b/gkeys/actions.py
@@ -14,6 +14,7 @@ from __future__ import print_function
import os
+from collections import defaultdict
from json import load
from shutil import rmtree
from sslfetch.connections import Connector
@@ -24,7 +25,7 @@ from gkeys.config import GKEY
Available_Actions = ['listseed', 'addseed', 'removeseed', 'moveseed',
'fetchseed',
'listseedfiles', 'listkey', 'installkey', 'removekey', 'movekey',
- 'installed', 'importkey', 'verify']
+ 'installed', 'importkey', 'verify', 'checkkey']
class Actions(object):
@@ -232,6 +233,41 @@ class Actions(object):
return ["Completed"]
return ["No seeds to search or install"]
+ def checkkey(self, args):
+ '''Check keys actions'''
+ if not args.seeds:
+ return ["Please specify seeds type (-s)."]
+ self.logger.debug("ACTIONS: checkkey; args: %s" % str(args))
+ installed_keys = self.installed(args)[1]
+ keydir = self.config.get_key(args.seeds + "-keydir")
+ self.logger.debug("ACTIONS: checkkey; keysdir = %s" % keydir)
+ self.gpg = GkeysGPG(self.config, keydir)
+ results = {}
+ failed = defaultdict(list)
+ self.output('', '\n Checking keys...')
+ for gkey in installed_keys:
+ self.logger.debug("ACTIONS: checkkey; gkey = %s" % gkey)
+ for key in gkey.keyid:
+ results[gkey.name] = self.gpg.check_keys(gkey.keydir, key)
+ if results[gkey.name].expired:
+ failed['expired'].append("%s(%s): %s" % (gkey.name,
gkey.nick, key))
+ if results[gkey.name].revoked:
+ failed['revoked'].append("%s(%s): %s" % (gkey.name,
gkey.nick, key))
+ if results[gkey.name].invalid:
+ failed['invalid'].append("%s(%s): %s" % (gkey.name,
gkey.nick, key))
+ if not results[gkey.name].sign:
+ failed['sign'].append("%s(%s): %s " % (gkey.name,
gkey.nick, key))
+ if failed['expired']:
+ self.output([failed['expired']], '\nExpired keys:\n')
+ if failed['revoked']:
+ self.output([failed['revoked']], '\nRevoked keys:\n')
+ if failed['invalid']:
+ self.output([failed['invalid']], '\nInvalid keys:\n')
+ if failed['sign']:
+ self.output([failed['sign']], '\nNo signing capabilities keys:\n')
+ return ['\nFound:\n-------', 'Expired: %d\nRevoked: %d\nInvalid:
%d\nNo signing capabilities: %d'
+ % (len(failed['expired']), len(failed['revoked']),
+ len(failed['invalid']), len(failed['sign']))]
def removekey(self, args):
'''Remove an installed key'''
diff --git a/gkeys/lib.py b/gkeys/lib.py
index 0a23d2b..a8af408 100644
--- a/gkeys/lib.py
+++ b/gkeys/lib.py
@@ -24,6 +24,7 @@ from os.path import abspath, pardir
from os.path import join as pjoin
from pyGPG.gpg import GPG
+from gkeys.config import GKEY_CHECK
from gkeys.fileops import ensure_dirs
from gkeys.log import logger
from gkeys.seed import Seeds
@@ -184,27 +185,74 @@ class GkeysGPG(GPG):
return []
- def list_keys(self, keydir):
+ def list_keys(self, keydir, colons=False):
'''List all keys in the specified keydir or
all keys in all keydir if keydir=None
@param keydir: the keydir to list the keys for
+ @param colons: bool to enable colon listing
'''
if not keydir:
logger.debug("LIB: list_keys(), invalid keydir parameter: %s"
% str(keydir))
return []
self.set_keydir(keydir, 'list-keys')
- if '--with-colons' in self.config['tasks']['list-keys']:
- self.config['tasks']['list-keys'].remove('--with-colons')
logger.debug("** Calling runGPG with Running 'gpg %s --list-keys %s'"
% (' '.join(self.config['tasks']['list-keys']), keydir)
)
+ if colons:
+ task_value = ['--with-colons']
+ self.config.options['tasks']['list-keys'].extend(task_value)
result = self.runGPG(task='list-keys', inputfile=keydir)
logger.info('GPG return code: ' + str(result.returncode))
return result
+ def check_keys(self, keydir, keyid):
+ '''Check specified or all keys based on the seed type
+
+ @param keydir: the keydir to list the keys for
+ @param keyid: the keyid to check
+ '''
+ result = self.list_keys(keydir, colons=True)
+ revoked = expired = invalid = False
+ sign = True
+ for data in result.status.data:
+ if data.name == "PUB":
+ if data.long_keyid == keyid[2:]:
+ # check if revoked
+ if 'r' in data.validity:
+ revoked = True
+ logger.debug("ERROR in key %s : revoked" %
data.long_keyid)
+ break
+ # if primary key expired, all subkeys expire
+ if 'e' in data.validity:
+ expired = True
+ logger.debug("ERROR in key %s : expired" %
data.long_keyid)
+ break
+ # check if invalid
+ if 'i' in data.validity:
+ invalid = True
+ logger.debug("ERROR in key %s : invalid" %
data.long_keyid)
+ break
+ if data.name == "SUB":
+ if data.long_keyid == keyid[2:]:
+ # check if subkey has signing capabilities
+ if 's' not in data.key_capabilities:
+ sign = False
+ logger.debug("ERROR in subkey %s : No signing
capabilities" % data.long_keyid)
+ # check if expired
+ if 'e' in data.validity:
+ logger.debug("WARNING in subkey %s : expired" %
data.long_keyid)
+ # check if revoked
+ if 'r' in data.validity:
+ logger.debug("WARNING in subkey %s : revoked" %
data.long_keyid)
+ # check if invalid
+ if 'i' in data.validity:
+ logger.debug("WARNING in subkey %s : invalid" %
data.long_keyid)
+ return GKEY_CHECK(keyid, revoked, expired, invalid, sign)
+
+
def list_keydirs(self):
'''List all available keydirs
'''