From a86d975ac15e074f142c75ba5c74596be92e740d Mon Sep 17 00:00:00 2001 From: jgg <> Date: Wed, 5 Jan 2000 01:50:22 +0000 Subject: [PATCH] more gpg touch ups --- ud-echelon | 93 +++++++++++-------------------------------------- ud-gpgimport | 71 +++++-------------------------------- ud-gpgsigfetch | 33 ++++++------------ userdir_ldap.py | 87 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 121 insertions(+), 163 deletions(-) diff --git a/ud-echelon b/ud-echelon index 6434f0e..2be0112 100755 --- a/ud-echelon +++ b/ud-echelon @@ -7,6 +7,7 @@ from userdir_ldap import *; EX_TEMPFAIL = 75; EX_PERMFAIL = 65; # EX_DATAERR +Debug = ""; # Try to extract a key fingerprint from a PGP siged message def TryGPG(Email): @@ -15,6 +16,7 @@ def TryGPG(Email): if string.find(Msg[0],"-----BEGIN PGP SIGNED MESSAGE-----") == -1: return None; + print Msg[0]; Res = GPGCheckSig(Msg[0]); # Failed to find a matching sig @@ -30,71 +32,6 @@ def TryGPG(Email): return (Attrs[0][1]["uid"][0],"PGP",FormatPGPKey(Res[2][1])); -# Convert the PGP name string to a uid value -def GetUID(l,Name,UnknownMap = {}): - # Crack up the email address into a best guess first/middle/last name - (cn,mn,sn) = NameSplit(re.sub('["]','',Name[0])) - - # Brackets anger the ldap searcher - cn = re.sub('[(")]','?',cn); - sn = re.sub('[(")]','?',sn); - - # First check the unknown map for the email address - if UnknownMap.has_key(Name[1] + '@' + Name[2]): - Stat = "unknown map hit for "+str(Name); - return (UnknownMap[Name[1] + '@' + Name[2]],[Stat]); - - # Then the cruft component (ie there was no email address to match) - if UnknownMap.has_key(Name[2]): - Stat = "unknown map hit for"+str(Name); - return (UnknownMap[Name[2]],[Stat]); - - # Search for a possible first/last name hit - try: - Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"(&(cn=%s)(sn=%s))"%(cn,sn),["uid"]); - except ldap.FILTER_ERROR: - Stat = "Filter failure: (&(cn=%s)(sn=%s))"%(cn,sn); - return (None,[Stat]); - - # Try matching on the email address - if (len(Attrs) != 1): - try: - Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"emailforward=%s"%(Name[2]),["uid"]); - except ldap.FILTER_ERROR: - pass; - - # Hmm, more than one/no return - if (len(Attrs) != 1): - # Key claims a local address - if Name[2] == EmailAppend: - - # Pull out the record for the claimed user - Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"(uid=%s)"%(Name[1]),["uid","sn","cn"]); - - # We require the UID surname to be someplace in the key name, this - # deals with special purpose keys like 'James Troup (Alternate Debian key)' - # Some people put their names backwards on their key too.. check that as well - if len(Attrs) == 1 and \ - (string.find(string.lower(sn),string.lower(Attrs[0][1]["sn"][0])) != -1 or \ - string.find(string.lower(cn),string.lower(Attrs[0][1]["sn"][0])) != -1): - Stat = EmailAppend+" hit for "+str(Name); - return (Name[1],[Stat]); - - # Attempt to give some best guess suggestions for use in editing the - # override file. - Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"(sn~=%s)"%(sn),["uid","sn","cn"]); - - Stat = []; - if len(Attrs) != 0: - Stat = ["None for %s"%(str(Name))]; - for x in Attrs: - Stat.append("But might be: %s %s <%s@debian.org>"%(x[1]["cn"][0],x[1]["sn"][0],x[1]["uid"][0])); - return (None,Stat); - else: - return (Attrs[0][1]["uid"][0],None); - - return (None,None); - # Try to guess the name from the email address def TryMatcher(Email): Sender = Email.getheader("From"); @@ -118,9 +55,13 @@ def TryMatcher(Email): return (UID[0],"FROM",Sender); # Open the log files -MainLog = open(Ech_MainLog,"a+",0); -ErrLog = open(Ech_ErrorLog,"a+",0); - +if Debug == None: + MainLog = open(Ech_MainLog,"a+",0); + ErrLog = open(Ech_ErrorLog,"a+",0); +else: + MainLog = open("/dev/stdout","a+",0); + ErrLog = open("/dev/stdout","a+",0); + # Start of main program ErrMsg = "Indeterminate Error"; ErrType = EX_TEMPFAIL; @@ -138,10 +79,13 @@ try: ErrMsg = "An error occured while performing the LDAP lookup"; global l; l = ldap.open(LDAPServer); - F = open(PassDir+"/pass-"+pwd.getpwuid(posix.getuid())[0],"r"); - AccessPass = string.split(string.strip(F.readline())," "); - l.simple_bind_s("uid="+AccessPass[0]+","+BaseDn,AccessPass[1]); - F.close(); + if Debug == None: + F = open(PassDir+"/pass-"+pwd.getpwuid(posix.getuid())[0],"r"); + AccessPass = string.split(string.strip(F.readline())," "); + l.simple_bind_s("uid="+AccessPass[0]+","+BaseDn,AccessPass[1]); + F.close(); + else: + l.simple_bind_s("",""); # Try to decode ErrType = EX_TEMPFAIL; @@ -162,7 +106,10 @@ try: MainLog.write("%s %s %s\n"%(User[0],User[1],Msg)); Dn = "uid=" + User[0] + "," + BaseDn; Rec = [(ldap.MOD_REPLACE,"activity-%s"%(User[1]),Msg)]; - l.modify_s(Dn,Rec); + if Debug == None: + l.modify_s(Dn,Rec); + else: + print Rec; else: User = ("-","UKN",Email.getheader("From")); Msg = "[%s] \"%s\" \"%s\" \"%s\""%(Now,User[2],List,MsgID); diff --git a/ud-gpgimport b/ud-gpgimport index a0f1764..500f965 100755 --- a/ud-gpgimport +++ b/ud-gpgimport @@ -34,60 +34,6 @@ def LoadOverride(File): Split = re.split("[:\n]",Line); UnknownMap[Split[0]] = string.strip(Split[1]); -# Convert the PGP name string to a uid value -def GetUID(l,Name): - # Crack up the email address into a best guess first/middle/last name - (cn,mn,sn) = NameSplit(re.sub('["]','',Name[0])) - - # Brackets anger the ldap searcher - cn = re.sub('[(")]','?',cn); - sn = re.sub('[(")]','?',sn); - - # First check the unknown map for the email address - if UnknownMap.has_key(Name[1] + '@' + Name[2]): - print "unknown map hit for",Name; - return UnknownMap[Name[1] + '@' + Name[2]]; - - # Then the cruft component (ie there was no email address to match) - if UnknownMap.has_key(Name[2]): - print "unknown map hit for",Name; - return UnknownMap[Name[2]]; - - # Search for a possible first/last name hit - try: - Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"(&(cn=%s)(sn=%s))"%(cn,sn),["uid"]); - except ldap.FILTER_ERROR: - print "Filter failure:","(&(cn=%s)(sn=%s))"%(cn,sn); - return None; - - # Hmm, more than one/no return - if (len(Attrs) != 1): - # Key claims a local address - if Name[2] == EmailAppend: - - # Pull out the record for the claimed user - Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"(uid=%s)"%(Name[1]),["uid","sn","cn"]); - - # We require the UID surname to be someplace in the key name, this - # deals with special purpose keys like 'James Troup (Alternate Debian key)' - # Some people put their names backwards on their key too.. check that as well - if len(Attrs) == 1 and \ - (string.find(string.lower(sn),string.lower(Attrs[0][1]["sn"][0])) != -1 or \ - string.find(string.lower(cn),string.lower(Attrs[0][1]["sn"][0])) != -1): - print EmailAppend,"hit for",Name; - return Name[1]; - - # Attempt to give some best guess suggestions for use in editing the - # override file. - print "None for",Name; - Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"(sn~=%s)"%(sn),["uid","sn","cn"]); - for x in Attrs: - print " But might be:",x[1]["cn"][0],x[1]["sn"][0],"<" + x[1]["uid"][0] + "@debian.org>"; - else: - return Attrs[0][1]["uid"][0]; - - return None; - # Process options AdminUser = pwd.getpwuid(posix.getuid())[0]; (options, arguments) = getopt.getopt(sys.argv[1:], "au:m:n") @@ -188,17 +134,16 @@ while(1): # print "Ignoring keyID",Split2[9],"belonging to",KeyMap[Split2[9]][0]; KeyMap[Split2[9]][1] = 1; continue; - - Match = AddressSplit.match(Split[9]); - if Match == None: - UID = GetUID(l,("","",Split[9])); - else: - UID = GetUID(l,Match.groups()); - - if UID == None: + + UID = GetUID(l,SplitEmail(Split[9]),UnknownMap); + if UID[0] == None: + print "None for",SplitEmail(Split[9]),"'%s'"%(Split[9]); + if UID[1] != None: + for x in UID[1]: print x; print "MISSING 0x" + Split2[9]; continue; + UID = UID[0] Rec = [(ldap.MOD_ADD,"keyfingerprint",Split2[9])]; Dn = "uid=" + UID + "," + BaseDn; print "Adding key 0x"+Split2[9],"to",UID; @@ -227,7 +172,7 @@ print Ignored,"keys already in the directory (ignored)"; # Look for unmatched keys for x in KeyMap.keys(): if KeyMap[x][1] == 0: - print "key 0x",x,"belonging to",KeyMap[x][0],"removed"; + print "key 0x%s belonging to %s removed"%(x,KeyMap[x][0]); if KeyCount.has_key(KeyMap[x][0]) : KeyCount[KeyMap[x][0]] = KeyCount[KeyMap[x][0]] - 1 if KeyCount[KeyMap[x][0]] <= 0: diff --git a/ud-gpgsigfetch b/ud-gpgsigfetch index ed8d43a..592b319 100755 --- a/ud-gpgsigfetch +++ b/ud-gpgsigfetch @@ -1,18 +1,5 @@ #!/usr/bin/env python # -*- mode: python -*- -# This script tries to match key fingerprints from a keyring with user -# name in a directory. When an unassigned key is found a heuristic match -# against the keys given cn/sn and the directory is performed to try to get -# a matching. Generally this works about 90% of the time, matching is fairly -# strict. In the event a non-match a fuzzy sounds-alike search is performed -# and the results printed to aide the user. -# -# GPG is automatically invoked with the correct magic special options, -# pass the names of all the valid key rings on the command line. -# -# The output report will list what actions were taken. Keys that are present -# in the directory but not in the key ring will be removed from the -# directory. import string, re, time, ldap, getopt, sys, pwd, posix; from userdir_gpg import *; @@ -24,10 +11,6 @@ AdminUser = pwd.getpwuid(posix.getuid())[0]; for (switch, val) in options: if (switch == '-o'): Output = val - elif (switch == '-m'): - LoadOverride(val); - elif (switch == '-a'): - NoAct = 0; if len(arguments) == 0: print "Give some keyrings to probe"; @@ -41,11 +24,10 @@ for x in arguments: Args.append("./"+x); else: Args.append(x); +Args.append("--fast-list-mode"); Args.append("--list-sigs"); Args = Args + GPGSearchOptions + [" 2> /dev/null"] -print string.join(Args," ") -#Keys = os.popen(string.join(Args," "),"r"); -Keys = os.popen("cat sigs","r"); +Keys = os.popen(string.join(Args," "),"r"); # Loop over the GPG key file HaveKeys = {}; @@ -78,7 +60,7 @@ OldArgs = Args; Args = Args + GPGSearchOptions + [" 2> /dev/null"] Keys = os.popen(string.join(Args," "),"r"); -print "Reading keys from output"; +print "Reading keys from output ring"; while(1): Line = Keys.readline(); if Line == "": @@ -105,4 +87,11 @@ while (I > 0): OldI = I; I = I - 20; if I < 0: I = 0; - print string.join(Args+KeysToFetch[I:OldI]," ") + print string.join(Args+KeysToFetch[I:OldI]," ") + Fetcher = os.popen(string.join(Args+KeysToFetch[I:OldI]," "),"r"); + while(1): + Line = Fetcher.readline(); + if Line == "": + break; + print Line; + Fetcher.close(); diff --git a/userdir_ldap.py b/userdir_ldap.py index f3f9ba7..0ea96a9 100644 --- a/userdir_ldap.py +++ b/userdir_ldap.py @@ -30,6 +30,8 @@ LastNamesPre = {"van": None, "le": None, "de": None, "di": None}; SSHAuthSplit = re.compile('^(.* )?(\d+) (\d+) (\d+) ?(.+)$'); #'^([^\d](?:[^ "]+(?:".*")?)*)? ?(\d+) (\d+) (\d+) (.+)$'); +AddressSplit = re.compile("(.*).*<([^@]*)@([^>]*)>"); + # Safely get an attribute from a tuple representing a dn and an attribute # list. It returns the first attribute if there are multi. def GetAttr(DnRecord,Attribute,Default = ""): @@ -101,10 +103,9 @@ def NameSplit(Name): break; # Merge any of the middle initials - if len(Words) > 2: - while len(Words[2]) == 2 and Words[2][1] == '.': - Words[1] = Words[1] + Words[2]; - del Words[2]; + while len(Words) > 2 and len(Words[2]) == 2 and Words[2][1] == '.': + Words[1] = Words[1] + Words[2]; + del Words[2]; while len(Words) < 2: Words.append(''); @@ -251,7 +252,83 @@ def SplitEmail(Addr): Res1 = Res1[0]; if Res1[1] == None: return (Res1[0],"",""); + + # If there is no @ then the address was not parsed well. Try the alternate + # Parsing scheme. This is particularly important when scanning PGP keys. Res2 = string.split(Res1[1],"@"); if len(Res2) != 2: - return (Res1[0],"",Res1[1]); + Match = AddressSplit.match(Addr); + if Match == None: + return ("","",Addr); + return Match.groups(); + return (Res1[0],Res2[0],Res2[1]); + +# Convert the PGP name string to a uid value. The return is a tuple of +# (uid,[message strings]). UnknownMpa is a hash from email to uid that +# overrides normal searching. +def GetUID(l,Name,UnknownMap = {}): + # Crack up the email address into a best guess first/middle/last name + (cn,mn,sn) = NameSplit(re.sub('["]','',Name[0])) + + # Brackets anger the ldap searcher + cn = re.sub('[(")]','?',cn); + sn = re.sub('[(")]','?',sn); + + # First check the unknown map for the email address + if UnknownMap.has_key(Name[1] + '@' + Name[2]): + Stat = "unknown map hit for "+str(Name); + return (UnknownMap[Name[1] + '@' + Name[2]],[Stat]); + + # Then the cruft component (ie there was no email address to match) + if UnknownMap.has_key(Name[2]): + Stat = "unknown map hit for"+str(Name); + return (UnknownMap[Name[2]],[Stat]); + + # Search for a possible first/last name hit + try: + Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"(&(cn=%s)(sn=%s))"%(cn,sn),["uid"]); + except ldap.FILTER_ERROR: + Stat = "Filter failure: (&(cn=%s)(sn=%s))"%(cn,sn); + return (None,[Stat]); + + # Try matching on the email address + if (len(Attrs) != 1): + try: + Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"emailforward=%s"%(Name[2]),["uid"]); + except ldap.FILTER_ERROR: + pass; + + # Hmm, more than one/no return + if (len(Attrs) != 1): + # Key claims a local address + if Name[2] == EmailAppend: + + # Pull out the record for the claimed user + Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"(uid=%s)"%(Name[1]),["uid","sn","cn"]); + + # We require the UID surname to be someplace in the key name, this + # deals with special purpose keys like 'James Troup (Alternate Debian key)' + # Some people put their names backwards on their key too.. check that as well + if len(Attrs) == 1 and \ + (string.find(string.lower(sn),string.lower(Attrs[0][1]["sn"][0])) != -1 or \ + string.find(string.lower(cn),string.lower(Attrs[0][1]["sn"][0])) != -1): + Stat = EmailAppend+" hit for "+str(Name); + return (Name[1],[Stat]); + + # Attempt to give some best guess suggestions for use in editing the + # override file. + Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"(sn~=%s)"%(sn),["uid","sn","cn"]); + + Stat = []; + if len(Attrs) != 0: + Stat = ["None for %s"%(str(Name))]; + for x in Attrs: + Stat.append("But might be: %s %s <%s@debian.org>"%(x[1]["cn"][0],x[1]["sn"][0],x[1]["uid"][0])); + return (None,Stat); + else: + return (Attrs[0][1]["uid"][0],None); + + return (None,None); + + -- 2.20.1