TODO item: do SSL in all ldap connections that authenticate
[mirror/userdir-ldap.git] / ud-echelon
1 #!/usr/bin/env python
2 # -*- mode: python -*-
3 import userdir_gpg, userdir_ldap, sys, traceback, time, ldap, os, getopt;
4 import pwd
5 from userdir_gpg import *;
6 from userdir_ldap import *;
7
8 EX_TEMPFAIL = 75;
9 EX_PERMFAIL = 65;      # EX_DATAERR
10 Debug = None;
11
12 # Try to extract a key fingerprint from a PGP siged message
13 def TryGPG(Email):
14    # Try to get a pgp text
15    try:
16       Msg = GetClearSig(Email);
17    except:
18       # Log an exception.. but continue. This is to deal with 'sort of' 
19       # PGP-MIME things
20       S = "%s: %s -> %s\n" %(Now,MsgID,ErrMsg);
21       S = S + " %s: %s\n" %(sys.exc_type,sys.exc_value);
22       ErrLog.write(S);
23       return None;
24
25    if Msg[0].find("-----BEGIN PGP SIGNED MESSAGE-----") == -1:
26       return None;
27
28    Res = GPGCheckSig(Msg[0]);
29
30    # Failed to find a matching sig
31    if Res[0] != None:
32       S = "%s: %s -> PGP Checking failed '%s': %s %s\n" %(Now,MsgID,Email.getheader("From"),str(Res[0]),str(Res[2]));
33       ErrLog.write(S);
34       return None;
35       
36    # Search for the matching key fingerprint
37    Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"keyFingerPrint=" + Res[2][1]);
38    if len(Attrs) == 0:
39       return None;
40    if len(Attrs) != 1:
41       raise Error, "Oddly your key fingerprint is assigned to more than one account.."
42    
43    return (Attrs[0][1]["uid"][0],"PGP",FormatPGPKey(Res[2][1]));
44
45 # Try to guess the name from the email address
46 def TryMatcher(Email):
47    Sender = Email.getheader("From");
48    if Sender == None:
49       return None;
50       
51    # Split up the address and invoke the matcher routine
52    UID = GetUID(l,SplitEmail(Sender));
53    
54    if UID[0] == None:
55       if UID[1] == None or len(UID[1]) == 0:
56          return None;
57
58       # Print out an error message
59       S = "%s: %s -> Address matching failed '%s'\n" %(Now,MsgID,Sender);
60       for x in UID[1]:
61          S = S + " " + x + "\n";
62       ErrLog.write(S);
63       return None;
64     
65    return (UID[0],"FROM",Sender);
66
67 # Process options
68 (options, arguments) = getopt.getopt(sys.argv[1:], "dr")
69 for (switch, val) in options:
70    if (switch == '-d'):
71       Debug = "";
72    
73 # Open the log files
74 if Debug == None:
75    MainLog = open(Ech_MainLog,"a+",0);
76    ErrLog = open(Ech_ErrorLog,"a+",0);
77 else:
78    MainLog = open("/dev/stdout","a+",0);
79    ErrLog = open("/dev/stdout","a+",0);
80    
81 # Start of main program
82 ErrMsg = "Indeterminate Error";
83 ErrType = EX_TEMPFAIL;
84 Now = time.strftime("%a, %d %b %Y %H:%M:%S",time.gmtime(time.time()));
85 MsgID = None;
86 try:
87    # Get the email 
88    ErrType = EX_PERMFAIL;
89    ErrMsg = "Failed to understand the email or find a signature:";
90    Email = mimetools.Message(sys.stdin,0);
91    MsgID = Email.getheader("Message-ID");
92    
93    # Connect to the ldap server
94    ErrType = EX_TEMPFAIL;
95    ErrMsg = "An error occured while performing the LDAP lookup";
96    global l;
97    l = ldap.open(LDAPServer);
98    if Debug == None:
99       F = open(PassDir+"/pass-"+pwd.getpwuid(os.getuid())[0],"r");
100       AccessPass = F.readline().strip().split(" ")
101       l.simple_bind_s("uid="+AccessPass[0]+","+BaseDn,AccessPass[1]);
102       F.close();
103    else:
104       l.simple_bind_s("","");
105
106    # Try to decode
107    ErrType = EX_TEMPFAIL;
108    ErrMsg = "An error occured while trying GPG decoding";
109    User = TryGPG(Email);
110    if User == None:
111       ErrMsg = "An error occured while trying Matcher decoding";
112       User = TryMatcher(Email);
113
114    # Get any mailing list information   
115    List = Email.getheader("X-Mailing-List");
116    if List == None:
117       List = "-";
118
119    # Tada, write a log message
120    if User != None:
121       Msg = "[%s] \"%s\" \"%s\" \"%s\""%(Now,User[2],List,MsgID);
122       MainLog.write("%s %s %s\n"%(User[0],User[1],Msg));
123       Dn = "uid=" + User[0] + "," + BaseDn;
124       Rec = [(ldap.MOD_REPLACE,"activity-%s"%(User[1]),Msg)];
125       if Debug == None:
126          l.modify_s(Dn,Rec);
127       else:
128          print Rec;
129    else:
130       User = ("-","UKN",Email.getheader("From"));
131       Msg = "[%s] \"%s\" \"%s\" \"%s\""%(Now,User[2],List,MsgID);
132       MainLog.write("%s %s %s\n"%(User[0],User[1],Msg));
133
134 except:
135    # Log an exception..
136    S = "%s: %s -> %s\n" %(Now,MsgID,ErrMsg);
137    S = S + "==> %s: %s\n" %(sys.exc_type,sys.exc_value);
138    List = traceback.extract_tb(sys.exc_traceback);
139    if len(List) > 1:
140       for x in List:
141          S = S + "   %s %s:%u: %s\n" %(x[2],x[0],x[1],x[3]);
142    ErrLog.write(S);
143    sys.exit(ErrType);
144    
145 sys.exit(0);