Echelon
authorjgg <>
Mon, 3 Jan 2000 08:34:26 +0000 (08:34 +0000)
committerjgg <>
Mon, 3 Jan 2000 08:34:26 +0000 (08:34 +0000)
debian/rules
ud-echelon [new file with mode: 0755]
ud-gpgimport
userdir-ldap.conf
userdir_ldap.py

index d64dad8..ec49962 100755 (executable)
@@ -38,7 +38,7 @@ binary-indep: build
        echo "userdir_gpg" >> $(i)/$(pysite)/userdir_ldap.pth
        install -m 644 userdir_ldap.py userdir_gpg.py \
                $(i)/$(pysite)/userdir_ldap/
        echo "userdir_gpg" >> $(i)/$(pysite)/userdir_ldap.pth
        install -m 644 userdir_ldap.py userdir_gpg.py \
                $(i)/$(pysite)/userdir_ldap/
-       install -m 755 {ud-forwardlist,ud-gpgimport,ud-info,ud-ldapshow,ud-userimport,ud-mailgate,ud-generate,ud-passchk,ud-useradd,ud-replicate,ud-xearth,ud-fingerserv} $(i)/usr/bin/
+       install -m 755 {ud-forwardlist,ud-gpgimport,ud-info,ud-ldapshow,ud-userimport,ud-mailgate,ud-generate,ud-passchk,ud-useradd,ud-replicate,ud-xearth,ud-fingerserv,ud-echelon} $(i)/usr/bin/
        install -m 755 web/*.* $(i)/var/www/userdir-ldap/
        chown www-data.www-data $(i)/var/cache/userdir-ldap/web-cookies/
        chmod u=rwx,g=,o= $(i)/var/cache/userdir-ldap/web-cookies/
        install -m 755 web/*.* $(i)/var/www/userdir-ldap/
        chown www-data.www-data $(i)/var/cache/userdir-ldap/web-cookies/
        chmod u=rwx,g=,o= $(i)/var/cache/userdir-ldap/web-cookies/
diff --git a/ud-echelon b/ud-echelon
new file mode 100755 (executable)
index 0000000..6434f0e
--- /dev/null
@@ -0,0 +1,182 @@
+#!/usr/bin/env python
+# -*- mode: python -*-
+import userdir_gpg, userdir_ldap, sys, traceback, time, ldap, posix;
+import string, pwd
+from userdir_gpg import *;
+from userdir_ldap import *;
+
+EX_TEMPFAIL = 75;
+EX_PERMFAIL = 65;      # EX_DATAERR
+
+# Try to extract a key fingerprint from a PGP siged message
+def TryGPG(Email):
+   # Try to get a pgp text
+   Msg = GetClearSig(Email);
+   if string.find(Msg[0],"-----BEGIN PGP SIGNED MESSAGE-----") == -1:
+      return None;
+      
+   Res = GPGCheckSig(Msg[0]);
+
+   # Failed to find a matching sig
+   if Res[0] != None:
+      return None;
+      
+   # Search for the matching key fingerprint
+   Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"keyfingerprint=" + Res[2][1]);
+   if len(Attrs) == 0:
+      return None;
+   if len(Attrs) != 1:
+      raise Error, "Oddly your key fingerprint is assigned to more than one account.."
+   
+   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");
+   if Sender == None:
+      return None;
+      
+   # Split up the address and invoke the matcher routine
+   UID = GetUID(l,SplitEmail(Sender));
+   
+   if UID[0] == None:
+      if UID[1] == None or len(UID[1]) == 0:
+         return None;
+
+      # Print out an error message
+      S = "%s: %s -> Address matching failed '%s'\n" %(Now,MsgID,Sender);
+      for x in UID[1]:
+         S = S + " " + x + "\n";
+      ErrLog.write(S);
+      return None;
+    
+   return (UID[0],"FROM",Sender);
+   
+# Open the log files
+MainLog = open(Ech_MainLog,"a+",0);
+ErrLog = open(Ech_ErrorLog,"a+",0);
+
+# Start of main program
+ErrMsg = "Indeterminate Error";
+ErrType = EX_TEMPFAIL;
+Now = time.strftime("%a, %d %b %Y %H:%M:%S",time.gmtime(time.time()));
+MsgID = None;
+try:
+   # Get the email 
+   ErrType = EX_PERMFAIL;
+   ErrMsg = "Failed to understand the email or find a signature:";
+   Email = mimetools.Message(sys.stdin,0);
+   MsgID = Email.getheader("Message-ID");
+   
+   # Connect to the ldap server
+   ErrType = EX_TEMPFAIL;
+   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();
+
+   # Try to decode
+   ErrType = EX_TEMPFAIL;
+   ErrMsg = "An error occured while trying GPG decoding";
+   User = TryGPG(Email);
+   if User == None:
+      ErrMsg = "An error occured while trying Matcher decoding";
+      User = TryMatcher(Email);
+
+   # Get any mailing list information   
+   List = Email.getheader("X-Mailing-List");
+   if List == None:
+      List = "-";
+
+   # Tada, write a log message
+   if User != None:
+      Msg = "[%s] \"%s\" \"%s\" \"%s\""%(Now,User[2],List,MsgID);
+      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);
+   else:
+      User = ("-","UKN",Email.getheader("From"));
+      Msg = "[%s] \"%s\" \"%s\" \"%s\""%(Now,User[2],List,MsgID);
+      MainLog.write("%s %s %s\n"%(User[0],User[1],Msg));
+
+except:
+   # Log an exception..
+   S = "%s: %s -> %s\n" %(Now,MsgID,ErrMsg);
+   S = S + "==> %s: %s\n" %(sys.exc_type,sys.exc_value);
+   List = traceback.extract_tb(sys.exc_traceback);
+   if len(List) > 1:
+      for x in List:
+         S = S + "   %s %s:%u: %s\n" %(x[2],x[0],x[1],x[3]);
+   ErrLog.write(S);
+   sys.exit(ErrType);
+   
+sys.exit(0);
index bd9ba9e..a0f1764 100755 (executable)
@@ -23,8 +23,6 @@ from userdir_gpg import *;
 UnknownMap = {};
 NoAct = 1;
 
 UnknownMap = {};
 NoAct = 1;
 
-AddressSplit = re.compile("(.*).*<([^@]*)@([^>]*)>");
-
 # Read the override file into the unknown map. The override file is a list
 # of colon delimited entires mapping PGP email addresess to local users
 def LoadOverride(File):
 # Read the override file into the unknown map. The override file is a list
 # of colon delimited entires mapping PGP email addresess to local users
 def LoadOverride(File):
index b61d1f4..bc3e4c0 100644 (file)
@@ -19,13 +19,16 @@ templatesdir = "/etc/userdir-ldap/templates/";
 replaycachefile = "/var/cache/userdir-ldap/replay";
 #replaycachefile = "/tmp/replay";
 
 replaycachefile = "/var/cache/userdir-ldap/replay";
 #replaycachefile = "/tmp/replay";
 
+# Echelon
+ech_errorlog = "/org/db.debian.org/mail/Log/ech-errors.log"
+ech_mainlog = "/org/db.debian.org/mail/Log/ech.log"
+
 # User properties
 defaultgid = 800;
 
 # For the output generator
 generateconf = "/etc/userdir-ldap/generate.conf"
 generatedir = "/var/cache/userdir-ldap/hosts/";
 # User properties
 defaultgid = 800;
 
 # For the output generator
 generateconf = "/etc/userdir-ldap/generate.conf"
 generatedir = "/var/cache/userdir-ldap/hosts/";
-#generatedir = "/tmp/hosts";
 passdir = "/etc/userdir-ldap/";
 
 # GPG Things
 passdir = "/etc/userdir-ldap/";
 
 # GPG Things
@@ -43,7 +46,7 @@ webloginurl = "login.cgi";
 websearchurl = "search.cgi";
 webupdateurl = "update.cgi";
 
 websearchurl = "search.cgi";
 webupdateurl = "update.cgi";
 
-weblogfile = '/var/log/userldap-web.log';
+weblogfile = "/var/log/userldap-web.log";
 
 # When should authentication tokens expire?
 authexpires = 600;
 
 # When should authentication tokens expire?
 authexpires = 600;
index adcc859..f3f9ba7 100644 (file)
@@ -1,5 +1,5 @@
 # Some routines and configuration that are used by the ldap progams
 # Some routines and configuration that are used by the ldap progams
-import termios, TERMIOS, re, string, imp, ldap, sys, whrandom, crypt;
+import termios, TERMIOS, re, string, imp, ldap, sys, whrandom, crypt, rfc822;
 
 try:
    File = open("/etc/userdir-ldap/userdir-ldap.conf");
 
 try:
    File = open("/etc/userdir-ldap/userdir-ldap.conf");
@@ -8,6 +8,7 @@ except:
 ConfModule = imp.load_source("userdir_config","/etc/userdir-ldap.conf",File);
 File.close();
 
 ConfModule = imp.load_source("userdir_config","/etc/userdir-ldap.conf",File);
 File.close();
 
+# Cheap hack
 BaseDn = ConfModule.basedn;
 BaseDn = ConfModule.basedn;
 LDAPServer = ConfModule.ldaphost;
 BaseDn = ConfModule.basedn;
 BaseDn = ConfModule.basedn;
 LDAPServer = ConfModule.ldaphost;
@@ -18,6 +19,8 @@ GenerateConf = ConfModule.generateconf;
 DefaultGID = ConfModule.defaultgid;
 TemplatesDir = ConfModule.templatesdir;
 PassDir = ConfModule.passdir;
 DefaultGID = ConfModule.defaultgid;
 TemplatesDir = ConfModule.templatesdir;
 PassDir = ConfModule.passdir;
+Ech_ErrorLog = ConfModule.ech_errorlog;
+Ech_MainLog = ConfModule.ech_mainlog;
 
 # This is a list of common last-name prefixes
 LastNamesPre = {"van": None, "le": None, "de": None, "di": None};
 
 # This is a list of common last-name prefixes
 LastNamesPre = {"van": None, "le": None, "de": None, "di": None};
@@ -238,5 +241,17 @@ def FormatPGPKey(Str):
          I = I + 4;
    else:
       Res = Str;
          I = I + 4;
    else:
       Res = Str;
-   return Res;
-  
+   return string.strip(Res);
+
+# Take an email address and split it into 3 parts, (Name,UID,Domain)
+def SplitEmail(Addr):
+   Res1 = rfc822.AddrlistClass(Addr).getaddress();
+   if len(Res1) != 1:
+      return ("","",Addr);
+   Res1 = Res1[0];
+   if Res1[1] == None:
+      return (Res1[0],"","");
+   Res2 = string.split(Res1[1],"@");
+   if len(Res2) != 2:
+      return (Res1[0],"",Res1[1]);
+   return (Res1[0],Res2[0],Res2[1]);