Hourly stamp
[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 string, 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 = string.strip(F.readline());
17       if Line == "":
18          break;
19       Split = string.split(Line,":");
20       if len(Split) != 2:
21          continue;
22    
23       Addr = string.strip(Split[1]);
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 = string.strip(Line);
38
39       Split = string.split(Line,":");
40       if len(Split) != 2:
41          continue;
42       OverMap[Split[0]] = string.strip(Split[1]);
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(string.join(Args," "),"r");
54
55 l = ldap.open(LDAPServer);
56 l.simple_bind_s("","");
57
58 # Fetch the key list and map to email address
59 PasswdAttrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"keyfingerprint=*",\
60                 ["uid","keyfingerprint"]);
61 KFMap = {}
62 for x in PasswdAttrs:
63    if x[1].has_key("keyfingerprint") == 0 or x[1].has_key("uid") == 0:
64       continue;
65    for I in x[1]["keyfingerprint"]:
66       KFMap[I] = x[1]["uid"][0];
67    
68 # Loop over the GPG key file mapping addresses to uids
69 Outstanding = 0;
70 Ignored = 0;
71 Emails = [];
72 EmailMap = {};
73 UIDMap = {};
74 UID = None;
75 FingerPrint = None;
76 print "Reading keyrings",
77 sys.stdout.flush();
78 while(1):
79    Line = Keys.readline();
80    if Line == "":
81       break;
82    
83    Split = string.split(Line,":");
84    if len(Split) >= 8 and Split[0] == "pub":
85       if FingerPrint != None and UID != None:
86          for x in Emails:
87             Match = AddressSplit.match(x);
88             if Match == None:
89               continue;
90             Groups = Match.groups();
91             Email = Groups[1]+'@'+Groups[2];
92             if UIDMap.has_key(Groups[1]):
93                UIDMap[Groups[1]].append(Email);
94             else:
95                UIDMap[Groups[1]] = [Email];
96             if EmailMap.has_key(Email) and EmailMap[Email] != UID:
97                print "Dup Emap",Email
98             else:
99                EmailMap[Email] = UID;
100       Emails = [Split[9]];
101       continue;
102    if len(Split) >= 11 and Split[0] == "fpr":
103       FingerPrint = Split[9];
104       if KFMap.has_key(FingerPrint) == 0:
105          print "Failed",FingerPrint;
106          UID = None;
107          continue;
108       UID = KFMap[FingerPrint];
109    if len(Split) >= 9 and Split[0] == "uid":
110       Emails.append(Split[9]);
111 print;
112
113 # Process the override files
114 for (switch, val) in options:
115    if (switch == '-f'):
116       ImportForward(val,EmailMap);
117       BindUser = val;
118    elif (switch == '-o'):
119       ImportOverride(val,EmailMap);
120
121 # Map the input
122 FinalMap = {};
123 while(1):
124    Line = sys.stdin.readline();
125    if Line == "":
126       break;
127    Line = string.strip(Line);
128
129    Split = string.split(Line,"@");
130    if len(Split) != 2:
131       continue;
132
133    # The address is in our domain, go directly
134    if Split[1] == EmailAppend:
135       if FinalMap.has_key(Line):
136         print "Dup",Line
137       Split2 = string.split(Split[0],"-");
138       FinalMap[Line] = Split2[0];
139       continue;
140
141    # Exists in the email map..
142    if EmailMap.has_key(Line):
143       if FinalMap.has_key(Line):
144         print "Dup",Line
145       FinalMap[Line] = EmailMap[Line];
146       continue;
147
148    # Try again splitting off common address appendage modes
149    Split2 = string.split(Split[0],"-");
150    Addr = Split2[0]+'@'+Split[1];
151    if EmailMap.has_key(Addr):
152       if FinalMap.has_key(Addr):
153         print "Dup",Addr
154       FinalMap[Line] = EmailMap[Addr];
155       continue;
156
157     # Failed 
158    if UIDMap.has_key(Split[0]):
159       print Line,UIDMap[Split[0]];
160    print Line;
161 print "-----";
162
163 # Generate a reverse map and check for duplicates
164 Back = {};
165 for x in FinalMap.keys():
166    if Back.has_key(FinalMap[x]):
167       print "Dup",x,FinalMap[x],Back[FinalMap[x]];
168    Back[FinalMap[x]] = x;
169    
170 # Print the forward map
171 for x in Back.keys():
172    print "%s: %s" % (x,Back[x]);