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]
|
[overview]
|
||||||
urls=ddpo,alladdresses
|
urls=ddpo,alladdresses
|
||||||
ddpo.pattern=http://qa.debian.org/developer.php?login=%(email)s
|
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