add tools for handling keyring data
- add model/keyringanalyzer.py inspired by Debian qa's carnivore's extract_data - add model/keyfinder.py using the database built by model/keyringanalyzer.py - store the keyring search directory in model/ddportfolio.ini
This commit is contained in:
parent
f1841af0ee
commit
1bf24010d5
3 changed files with 160 additions and 0 deletions
|
@ -1,3 +1,6 @@
|
|||
[DEFAULT]
|
||||
keyring.dir=/usr/share/keyrings
|
||||
|
||||
[overview]
|
||||
urls=ddpo,alladdresses
|
||||
ddpo.pattern=http://qa.debian.org/developer.php?login=%(email)s
|
||||
|
|
48
ddportfolioservice/model/keyfinder.py
Normal file
48
ddportfolioservice/model/keyfinder.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This module provides tools for finding PGP key information from a
|
||||
given keyring.
|
||||
"""
|
||||
|
||||
db = None
|
||||
|
||||
def _get_keyring_cache():
|
||||
if db = None:
|
||||
import anydbm
|
||||
import pkg_resources
|
||||
import os.path
|
||||
filename = pkg_resources.resource_filename(__name__,
|
||||
'keyringcache')
|
||||
assert os.path.exists(filename) and os.path.isfile(filename)
|
||||
db = anydbm.open(filename, 'r')
|
||||
return db
|
||||
|
||||
def _get_cached(cachekey):
|
||||
cache = _get_keyring_cache()
|
||||
if cachekey in cache:
|
||||
return cache[cachekey].split(':')
|
||||
return None
|
||||
|
||||
def getFingerprintByEmail(email):
|
||||
"""Gets the fingerprints associated with the given email address
|
||||
if available."""
|
||||
return _get_cached('fpr:email:%s' % email)
|
||||
|
||||
|
||||
def getRealnameByEmail(email):
|
||||
"""Gets the real names associated with the given email address if
|
||||
available."""
|
||||
return _get_cached('name:email:%s' % email)
|
||||
|
||||
|
||||
def getLoginByEmail(email):
|
||||
"""Gets the logins associated with the given email address if
|
||||
available."""
|
||||
return _get_cached('login:email:%s' % email)
|
||||
|
||||
|
||||
def getLoginByFingerprint(fpr):
|
||||
"""Gets the login associated with the given fingerprint if
|
||||
available."""
|
||||
return _get_cached('login:fpr:%s' % fpr)
|
109
ddportfolioservice/model/keyringanalyzer.py
Normal file
109
ddportfolioservice/model/keyringanalyzer.py
Normal file
|
@ -0,0 +1,109 @@
|
|||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This is a tool that analyzes GPG and PGP keyrings and stores the
|
||||
retrieved data in a file database. The tool was inspired by Debian
|
||||
qa's carnivore.
|
||||
"""
|
||||
|
||||
import anydbm
|
||||
import pkg_resources
|
||||
import glob
|
||||
import ConfigParser
|
||||
import os
|
||||
|
||||
|
||||
def _get_keyrings():
|
||||
"""Gets the available keyring files from the keyring directory
|
||||
configured in ddportfolio.ini."""
|
||||
my_config = ConfigParser.ConfigParser()
|
||||
my_config.readfp(pkg_resources.resource_stream(__name__, 'ddportfolio.ini'))
|
||||
keyrings = glob.glob(my_config.get('DEFAULT', 'keyring.dir') +
|
||||
'/*.gpg')
|
||||
keyrings.extend(glob.glob(my_config.get('DEFAULT', 'keyring.dir') +
|
||||
'/*.pgp'))
|
||||
keyrings.sort()
|
||||
return keyrings
|
||||
|
||||
|
||||
def _parse_uid(uid):
|
||||
"""Parse a uid of the form 'Real Name <email@example.com>' into
|
||||
email and realname parts."""
|
||||
uid = uid.strip()
|
||||
# First, strip comment
|
||||
s = uid.find('(')
|
||||
e = uid.find(')')
|
||||
if s >= 0 and e >= 0:
|
||||
uid = uid[:s] + uid[e+1:]
|
||||
s = uid.find('<')
|
||||
e = uid.find('>')
|
||||
email = None
|
||||
if s >= 0 and e >= 0:
|
||||
email = uid[s+1:e]
|
||||
uid = uid[:s] + uid[e+1:]
|
||||
uid = uid.strip()
|
||||
if not email and uid.find('@') >= 0:
|
||||
email, uid = uid, email
|
||||
return (uid, email)
|
||||
|
||||
resultdict = {}
|
||||
|
||||
def _get_canonical(key):
|
||||
if not key in resultdict:
|
||||
resultdict[key] = []
|
||||
return key
|
||||
|
||||
|
||||
def _add_to_result(key, newvalue):
|
||||
thekey = _get_canonical(key)
|
||||
if newvalue not in resultdict[thekey]:
|
||||
resultdict[thekey].append(newvalue)
|
||||
|
||||
|
||||
def process_keyrings():
|
||||
"""Process the keyrings and store the extracted data in an anydbm
|
||||
file."""
|
||||
for keyring in _get_keyrings():
|
||||
contents = os.popen("gpg --no-default-keyring \
|
||||
--no-expensive-trust-checks \
|
||||
--keyring %s --list-keys \
|
||||
--with-colons --fingerprint" % (keyring))
|
||||
fpr = None
|
||||
entry = None
|
||||
lastpub = None
|
||||
for line in contents.readlines():
|
||||
items = line.split(':')
|
||||
uid = None
|
||||
if items[0] == 'pub':
|
||||
fpr = entry = None
|
||||
lastpub = items[9].strip()
|
||||
continue
|
||||
elif items[0] == 'fpr':
|
||||
fpr = items[9].strip()
|
||||
uid = lastpub
|
||||
elif items[0] == 'uid':
|
||||
uid = items[9].strip()
|
||||
else:
|
||||
continue
|
||||
# Do stuff with 'uid'
|
||||
uid, email = _parse_uid(uid)
|
||||
if email:
|
||||
if email.endswith('@debian.org'):
|
||||
login = email[0:-len('@debian.org')]
|
||||
_add_to_result('login:email:%s' % email, login)
|
||||
_add_to_result('login:fpr:%s' % fpr, login)
|
||||
_add_to_result('email:fpr:%s' % fpr, email)
|
||||
if uid:
|
||||
_add_to_result('name:fpr:%s' % fpr, uid)
|
||||
if email:
|
||||
_add_to_result('name:email:%s' % email, uid)
|
||||
contents.close()
|
||||
db = anydbm.open(pkg_resources.resource_filename(__name__,
|
||||
'keyringcache'), 'c')
|
||||
for key in resultdict:
|
||||
db[key] = ":".join(resultdict[key])
|
||||
db.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
process_keyrings()
|
Loading…
Reference in a new issue