X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=dak%2Fimport_keyring.py;h=ca325d0da290da53abf7e818ba8c047988461a9a;hb=cd5b29ddfd8de263c085f494b9573d683913f6f3;hp=7f35b146aaff9d1380d5f3800290385c564dce60;hpb=1dccc682e3b2de586b53306c3002493f50c9bbaf;p=dak.git diff --git a/dak/import_keyring.py b/dak/import_keyring.py index 7f35b146..ca325d0d 100755 --- a/dak/import_keyring.py +++ b/dak/import_keyring.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Imports a keyring into the database +""" Imports a keyring into the database """ # Copyright (C) 2007 Anthony Towns # This program is free software; you can redistribute it and/or modify @@ -19,7 +19,8 @@ ################################################################################ -import daklib.database, daklib.logging +from daklib import database +from daklib import utils import sys, os, re import apt_pkg, pg, ldap, email.Utils @@ -27,7 +28,6 @@ import apt_pkg, pg, ldap, email.Utils Cnf = None Options = None projectB = None -Logger = None ################################################################################ @@ -35,9 +35,9 @@ def get_uid_info(): byname = {} byid = {} q = projectB.query("SELECT id, uid, name FROM uid") - for (id, uid, name) in q.getresult(): - byname[uid] = (id, name) - byid[id] = (uid, name) + for (keyid, uid, name) in q.getresult(): + byname[uid] = (keyid, name) + byid[keyid] = (uid, name) return (byname, byid) def get_fingerprint_info(): @@ -50,121 +50,121 @@ def get_fingerprint_info(): ################################################################################ def get_ldap_name(entry): - name = [] - for k in ["cn", "mn", "sn"]: - ret = entry.get(k) - if ret and ret[0] != "" and ret[0] != "-": - name.append(ret[0]) - return " ".join(name) + name = [] + for k in ["cn", "mn", "sn"]: + ret = entry.get(k) + if ret and ret[0] != "" and ret[0] != "-": + name.append(ret[0]) + return " ".join(name) ################################################################################ class Keyring: - gpg_invocation = "gpg --no-default-keyring --keyring %s" +\ - " --with-colons --fingerprint --fingerprint" - keys = {} - fpr_lookup = {} - - def de_escape_gpg_str(self, str): - esclist = re.split(r'(\\x..)', str) - for x in range(1,len(esclist),2): - esclist[x] = "%c" % (int(esclist[x][2:],16)) - return "".join(esclist) - - def __init__(self, keyring): - k = os.popen(self.gpg_invocation % keyring, "r") - keys = self.keys - key = None - fpr_lookup = self.fpr_lookup - signingkey = False - for line in k.xreadlines(): - field = line.split(":") - if field[0] == "pub": - key = field[4] - (name, addr) = email.Utils.parseaddr(field[9]) - name = re.sub(r"\s*[(].*[)]", "", name) - if name == "" or addr == "" or "@" not in addr: - name = field[9] - addr = "invalid-uid" - name = self.de_escape_gpg_str(name) - keys[key] = {"email": addr} - if name != "": keys[key]["name"] = name - keys[key]["aliases"] = [name] - keys[key]["fingerprints"] = [] - signingkey = True - elif key and field[0] == "sub" and len(field) >= 12: - signingkey = ("s" in field[11]) - elif key and field[0] == "uid": - (name, addr) = email.Utils.parseaddr(field[9]) - if name and name not in keys[key]["aliases"]: - keys[key]["aliases"].append(name) - elif signingkey and field[0] == "fpr": - keys[key]["fingerprints"].append(field[9]) - fpr_lookup[field[9]] = key - - def generate_desired_users(self): - if Options["Generate-Users"]: - format = Options["Generate-Users"] - return self.generate_users_from_keyring(format) - if Options["Import-Ldap-Users"]: - return self.import_users_from_ldap() - return ({}, {}) - - def import_users_from_ldap(self): - LDAPDn = Cnf["Import-LDAP-Fingerprints::LDAPDn"] - LDAPServer = Cnf["Import-LDAP-Fingerprints::LDAPServer"] - l = ldap.open(LDAPServer) - l.simple_bind_s("","") - Attrs = l.search_s(LDAPDn, ldap.SCOPE_ONELEVEL, - "(&(keyfingerprint=*)(gidnumber=%s))" % (Cnf["Import-Users-From-Passwd::ValidGID"]), - ["uid", "keyfingerprint", "cn", "mn", "sn"]) - - ldap_fin_uid_id = {} - - byuid = {} - byname = {} - keys = self.keys - fpr_lookup = self.fpr_lookup - - for i in Attrs: - entry = i[1] - uid = entry["uid"][0] - name = get_ldap_name(entry) - fingerprints = entry["keyFingerPrint"] - id = None - for f in fingerprints: - key = fpr_lookup.get(f, None) - if key not in keys: continue - keys[key]["uid"] = uid - - if id != None: continue - id = daklib.database.get_or_set_uid_id(uid) - byuid[id] = (uid, name) - byname[uid] = (id, name) - - return (byname, byuid) - - def generate_users_from_keyring(self, format): - byuid = {} - byname = {} - keys = self.keys - any_invalid = False - for x in keys.keys(): - if keys[x]["email"] == "invalid-uid": - any_invalid = True - keys[x]["uid"] = format % "invalid-uid" - else: - uid = format % keys[x]["email"] - id = daklib.database.get_or_set_uid_id(uid) - byuid[id] = (uid, keys[x]["name"]) - byname[uid] = (id, keys[x]["name"]) - keys[x]["uid"] = uid - if any_invalid: - uid = format % "invalid-uid" - id = daklib.database.get_or_set_uid_id(uid) - byuid[id] = (uid, "ungeneratable user id") - byname[uid] = (id, "ungeneratable user id") - return (byname, byuid) + gpg_invocation = "gpg --no-default-keyring --keyring %s" +\ + " --with-colons --fingerprint --fingerprint" + keys = {} + fpr_lookup = {} + + def de_escape_gpg_str(self, str): + esclist = re.split(r'(\\x..)', str) + for x in range(1,len(esclist),2): + esclist[x] = "%c" % (int(esclist[x][2:],16)) + return "".join(esclist) + + def __init__(self, keyring): + k = os.popen(self.gpg_invocation % keyring, "r") + keys = self.keys + key = None + fpr_lookup = self.fpr_lookup + signingkey = False + for line in k.xreadlines(): + field = line.split(":") + if field[0] == "pub": + key = field[4] + (name, addr) = email.Utils.parseaddr(field[9]) + name = re.sub(r"\s*[(].*[)]", "", name) + if name == "" or addr == "" or "@" not in addr: + name = field[9] + addr = "invalid-uid" + name = self.de_escape_gpg_str(name) + keys[key] = {"email": addr} + if name != "": keys[key]["name"] = name + keys[key]["aliases"] = [name] + keys[key]["fingerprints"] = [] + signingkey = True + elif key and field[0] == "sub" and len(field) >= 12: + signingkey = ("s" in field[11]) + elif key and field[0] == "uid": + (name, addr) = email.Utils.parseaddr(field[9]) + if name and name not in keys[key]["aliases"]: + keys[key]["aliases"].append(name) + elif signingkey and field[0] == "fpr": + keys[key]["fingerprints"].append(field[9]) + fpr_lookup[field[9]] = key + + def generate_desired_users(self): + if Options["Generate-Users"]: + format = Options["Generate-Users"] + return self.generate_users_from_keyring(format) + if Options["Import-Ldap-Users"]: + return self.import_users_from_ldap() + return ({}, {}) + + def import_users_from_ldap(self): + LDAPDn = Cnf["Import-LDAP-Fingerprints::LDAPDn"] + LDAPServer = Cnf["Import-LDAP-Fingerprints::LDAPServer"] + l = ldap.open(LDAPServer) + l.simple_bind_s("","") + Attrs = l.search_s(LDAPDn, ldap.SCOPE_ONELEVEL, + "(&(keyfingerprint=*)(gidnumber=%s))" % (Cnf["Import-Users-From-Passwd::ValidGID"]), + ["uid", "keyfingerprint", "cn", "mn", "sn"]) + + ldap_fin_uid_id = {} + + byuid = {} + byname = {} + keys = self.keys + fpr_lookup = self.fpr_lookup + + for i in Attrs: + entry = i[1] + uid = entry["uid"][0] + name = get_ldap_name(entry) + fingerprints = entry["keyFingerPrint"] + keyid = None + for f in fingerprints: + key = fpr_lookup.get(f, None) + if key not in keys: continue + keys[key]["uid"] = uid + + if keyid != None: continue + keyid = database.get_or_set_uid_id(uid) + byuid[keyid] = (uid, name) + byname[uid] = (keyid, name) + + return (byname, byuid) + + def generate_users_from_keyring(self, format): + byuid = {} + byname = {} + keys = self.keys + any_invalid = False + for x in keys.keys(): + if keys[x]["email"] == "invalid-uid": + any_invalid = True + keys[x]["uid"] = format % "invalid-uid" + else: + uid = format % keys[x]["email"] + keyid = database.get_or_set_uid_id(uid) + byuid[keyid] = (uid, keys[x]["name"]) + byname[uid] = (keyid, keys[x]["name"]) + keys[x]["uid"] = uid + if any_invalid: + uid = format % "invalid-uid" + keyid = database.get_or_set_uid_id(uid) + byuid[keyid] = (uid, "ungeneratable user id") + byname[uid] = (keyid, "ungeneratable user id") + return (byname, byuid) ################################################################################ @@ -181,11 +181,11 @@ def usage (exit_code=0): def main(): global Cnf, projectB, Options - Cnf = daklib.utils.get_conf() + Cnf = utils.get_conf() Arguments = [('h',"help","Import-Keyring::Options::Help"), - ('L',"import-ldap-users","Import-Keyring::Options::Import-Ldap-Users"), - ('U',"generate-users","Import-Keyring::Options::Generate-Users", "HasArg"), - ] + ('L',"import-ldap-users","Import-Keyring::Options::Import-Ldap-Users"), + ('U',"generate-users","Import-Keyring::Options::Generate-Users", "HasArg"), + ] for i in [ "help", "report-changes", "generate-users", "import-ldap-users" ]: if not Cnf.has_key("Import-Keyring::Options::%s" % (i)): @@ -200,7 +200,7 @@ def main(): usage() if len(keyring_names) != 1: - usage(1) + usage(1) ### Keep track of changes made @@ -209,7 +209,7 @@ def main(): ### Initialise projectB = pg.connect(Cnf["DB::Name"], Cnf["DB::Host"], int(Cnf["DB::Port"])) - daklib.database.init(Cnf, projectB) + database.init(Cnf, projectB) projectB.query("BEGIN WORK") @@ -222,8 +222,13 @@ def main(): keyringname = keyring_names[0] keyring = Keyring(keyringname) - keyring_id = daklib.database.get_or_set_keyring_id( - keyringname.split("/")[-1]) + is_dm = "false" + if Cnf.has_key("Import-Keyring::"+keyringname+"::Debian-Maintainer"): + projectB.query("UPDATE keyrings SET debian_maintainer = '%s' WHERE name = '%s'" % (Cnf["Import-Keyring::"+keyringname+"::Debian-Maintainer"], keyringname.split("/")[-1])) + is_dm = Cnf["Import-Keyring::"+keyringname+"::Debian-Maintainer"] + + keyring_id = database.get_or_set_keyring_id( + keyringname.split("/")[-1]) ### Generate new uid entries if they're needed (from LDAP or the keyring) (desuid_byname, desuid_byid) = keyring.generate_desired_users() @@ -232,14 +237,14 @@ def main(): (db_uid_byname, db_uid_byid) = get_uid_info() ### Update full names of applicable users - for id in desuid_byid.keys(): - uid = (id, desuid_byid[id][0]) - name = desuid_byid[id][1] - oname = db_uid_byid[id][1] - if name and oname != name: - changes.append((uid[1], "Full name: %s\n" % (name))) + for keyid in desuid_byid.keys(): + uid = (keyid, desuid_byid[keyid][0]) + name = desuid_byid[keyid][1] + oname = db_uid_byid[keyid][1] + if name and oname != name: + changes.append((uid[1], "Full name: %s" % (name))) projectB.query("UPDATE uid SET name = '%s' WHERE id = %s" % - (pg.escape_string(name), id)) + (pg.escape_string(name), keyid)) # The fingerprint table (fpr) points to a uid and a keyring. # If the uid is being decided here (ldap/generate) we set it to it. @@ -249,11 +254,11 @@ def main(): fpr = {} for z in keyring.keys.keys(): - id = db_uid_byname.get(keyring.keys[z].get("uid", None), [None])[0] - if id == None: - id = db_fin_info.get(keyring.keys[z]["fingerprints"][0], [None])[0] - for y in keyring.keys[z]["fingerprints"]: - fpr[y] = (id,keyring_id) + keyid = db_uid_byname.get(keyring.keys[z].get("uid", None), [None])[0] + if keyid == None: + keyid = db_fin_info.get(keyring.keys[z]["fingerprints"][0], [None])[0] + for y in keyring.keys[z]["fingerprints"]: + fpr[y] = (keyid,keyring_id) # For any keys that used to be in this keyring, disassociate them. # We don't change the uid, leaving that for historical info; if @@ -261,35 +266,42 @@ def main(): for f,(u,fid,kr) in db_fin_info.iteritems(): if kr != keyring_id: continue - if f in fpr: continue - changes.append((db_uid_byid.get(u, [None])[0], "Removed key: %s\n" % (f))) - projectB.query("UPDATE fingerprint SET keyring = NULL WHERE id = %d" % (fid)) + if f in fpr: continue + changes.append((db_uid_byid.get(u, [None])[0], "Removed key: %s" % (f))) + projectB.query("UPDATE fingerprint SET keyring = NULL WHERE id = %d" % (fid)) # For the keys in this keyring, add/update any fingerprints that've # changed. for f in fpr: newuid = fpr[f][0] - newuiduid = db_uid_byid.get(newuid, [None])[0] - (olduid, oldfid, oldkid) = db_fin_info.get(f, [-1,-1,-1]) - if olduid == None: olduid = -1 - if oldkid == None: oldkid = -1 - if oldfid == -1: - changes.append((newuiduid, "Added key: %s\n" % (f))) + newuiduid = db_uid_byid.get(newuid, [None])[0] + (olduid, oldfid, oldkid) = db_fin_info.get(f, [-1,-1,-1]) + if olduid == None: olduid = -1 + if oldkid == None: oldkid = -1 + if oldfid == -1: + changes.append((newuiduid, "Added key: %s" % (f))) if newuid: - projectB.query("INSERT INTO fingerprint (fingerprint, uid, keyring) VALUES ('%s', %d, %d)" % (f, newuid, keyring_id)) - else: - projectB.query("INSERT INTO fingerprint (fingerprint, keyring) VALUES ('%s', %d)" % (f, keyring_id)) - else: - if newuid and olduid != newuid: - if olduid != -1: - changes.append((newuiduid, "Linked key: %s (formerly belonging to %s)" % (f, db_uid_byid[olduid][0]))) - else: - changes.append((newuiduid, "Linked key: %s (formerly unowned)\n" % (f))) - projectB.query("UPDATE fingerprint SET uid = %d WHERE id = %d" % (newuid, oldfid)) - - if oldkid != keyring_id: - projectB.query("UPDATE fingerprint SET keyring = %d WHERE id = %d" % (keyring_id, oldfid)) + projectB.query("INSERT INTO fingerprint (fingerprint, uid, keyring) VALUES ('%s', %d, %d)" % (f, newuid, keyring_id)) + else: + projectB.query("INSERT INTO fingerprint (fingerprint, keyring) VALUES ('%s', %d)" % (f, keyring_id)) + else: + if newuid and olduid != newuid: + if olduid != -1: + changes.append((newuiduid, "Linked key: %s" % f)) + changes.append((newuiduid, " (formerly belonging to %s)" % (db_uid_byid[olduid][0]))) + else: + changes.append((newuiduid, "Linked key: %s" % f)) + changes.append((newuiduid, " (formerly unowned)")) + projectB.query("UPDATE fingerprint SET uid = %d WHERE id = %d" % (newuid, oldfid)) + + if oldkid != keyring_id: + # Only change the keyring if it won't result in a loss of permissions + q = projectB.query("SELECT debian_maintainer FROM keyrings WHERE id = '%d'" % (keyring_id)) + if is_dm == "false" and q.getresult()[0][0] == 'f': + projectB.query("UPDATE fingerprint SET keyring = %d WHERE id = %d" % (keyring_id, oldfid)) + else: + print "Key %s exists in both DM and DD keyrings. Not demoting." % (f) # All done! @@ -298,12 +310,12 @@ def main(): changesd = {} for (k, v) in changes: if k not in changesd: changesd[k] = "" - changesd[k] += " " + v + changesd[k] += " %s\n" % (v) keys = changesd.keys() keys.sort() for k in keys: - print "%s\n%s" % (k, changesd[k]) + print "%s\n%s\n" % (k, changesd[k]) ################################################################################