gpg2 output differs from gpg1 - fix GPGSearch
[mirror/userdir-ldap.git] / ud-emailmatcher
1 #!/usr/bin/env python
2 # -*- mode: python -*-
3 # This script tries to match a list of email addresses to the ldap database
4 # uids. It makes use of the PGP key ring to determine matches
5
6 import re, time, ldap, getopt, sys;
7 from userdir_ldap import *;
8 from userdir_gpg import *;
9
10 AddressSplit = re.compile("(.*).*<([^@]*)@([^>]*)>");
11
12 # Import an an forward file
13 def ImportForward(File,EmailMap):
14    F = open(File,"r");
15    while(1):
16       Line = F.readline().strip()
17       if Line == "":
18          break;
19       Split = Line.split(":")
20       if len(Split) != 2:
21          continue;
22    
23       Addr = Split[1].strip()
24       if EmailMap.has_key(Addr) and  EmailMap[Addr] != Split[0]:
25          print "Dup Over Emap",Line,Split
26       else:
27          EmailMap[Addr] = Split[0];
28    F.close();
29
30 # Import an override file
31 def ImportOverride(File,OverMap):
32    F = open(File,"r");
33    while(1):
34       Line = F.readline();
35       if Line == "":
36          break;
37       Line = Line.strip()
38
39       Split = Line.split(":")
40       if len(Split) != 2:
41          continue;
42       OverMap[Split[0]] = Split[1].strip()
43    F.close();
44
45 (options, arguments) = getopt.getopt(sys.argv[1:], "o:f:")
46
47 # Popen GPG with the correct magic special options
48 Args = [GPGPath] + GPGBasicOptions + GPGKeyRings;
49 for x in arguments:
50    Args.append("--keyring");
51    Args.append(x);
52 Args = Args + GPGSearchOptions + [" 2> /dev/null"]
53 Keys = os.popen(" ".join(Args),"r")
54
55 l = connectLDAP()
56
57 # Fetch the key list and map to email address
58 PasswdAttrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"keyfingerprint=*",\
59                 ["uid","keyfingerprint"]);
60 KFMap = {}
61 for x in PasswdAttrs:
62    if x[1].has_key("keyfingerprint") == 0 or x[1].has_key("uid") == 0:
63       continue;
64    for I in x[1]["keyfingerprint"]:
65       KFMap[I] = x[1]["uid"][0];
66    
67 # Loop over the GPG key file mapping addresses to uids
68 Outstanding = 0;
69 Ignored = 0;
70 Emails = [];
71 EmailMap = {};
72 UIDMap = {};
73 UID = None;
74 FingerPrint = None;
75 print "Reading keyrings",
76 sys.stdout.flush();
77 while(1):
78    Line = Keys.readline();
79    if Line == "":
80       break;
81    
82    Split = Line.split(":")
83    if len(Split) >= 8 and Split[0] == "pub":
84       if FingerPrint != None and UID != None:
85          for x in Emails:
86             Match = AddressSplit.match(x);
87             if Match == None:
88               continue;
89             Groups = Match.groups();
90             Email = Groups[1]+'@'+Groups[2];
91             if UIDMap.has_key(Groups[1]):
92                UIDMap[Groups[1]].append(Email);
93             else:
94                UIDMap[Groups[1]] = [Email];
95             if EmailMap.has_key(Email) and EmailMap[Email] != UID:
96                print "Dup Emap",Email
97             else:
98                EmailMap[Email] = UID;
99       Emails = [Split[9]];
100       continue;
101    if len(Split) >= 11 and Split[0] == "fpr":
102       FingerPrint = Split[9];
103       if KFMap.has_key(FingerPrint) == 0:
104          print "Failed",FingerPrint;
105          UID = None;
106          continue;
107       UID = KFMap[FingerPrint];
108    if len(Split) >= 9 and Split[0] == "uid":
109       Emails.append(Split[9]);
110 print;
111
112 # Process the override files
113 for (switch, val) in options:
114    if (switch == '-f'):
115       ImportForward(val,EmailMap);
116       BindUser = val;
117    elif (switch == '-o'):
118       ImportOverride(val,EmailMap);
119
120 # Map the input
121 FinalMap = {};
122 while(1):
123    Line = sys.stdin.readline();
124    if Line == "":
125       break;
126    Line = Line.strip()
127
128    Split = Line.split("@")
129    if len(Split) != 2:
130       continue;
131
132    # The address is in our domain, go directly
133    if Split[1] == EmailAppend:
134       if FinalMap.has_key(Line):
135         print "Dup",Line
136       Split2 = Split[0].split("-")
137       FinalMap[Line] = Split2[0];
138       continue;
139
140    # Exists in the email map..
141    if EmailMap.has_key(Line):
142       if FinalMap.has_key(Line):
143         print "Dup",Line
144       FinalMap[Line] = EmailMap[Line];
145       continue;
146
147    # Try again splitting off common address appendage modes
148    Split2 = Split[0].split("-")
149    Addr = Split2[0]+'@'+Split[1];
150    if EmailMap.has_key(Addr):
151       if FinalMap.has_key(Addr):
152         print "Dup",Addr
153       FinalMap[Line] = EmailMap[Addr];
154       continue;
155
156     # Failed 
157    if UIDMap.has_key(Split[0]):
158       print Line,UIDMap[Split[0]];
159    print Line;
160 print "-----";
161
162 # Generate a reverse map and check for duplicates
163 Back = {};
164 for x in FinalMap.keys():
165    if Back.has_key(FinalMap[x]):
166       print "Dup",x,FinalMap[x],Back[FinalMap[x]];
167    Back[FinalMap[x]] = x;
168    
169 # Print the forward map
170 for x in Back.keys():
171    print "%s: %s" % (x,Back[x]);