I have been playing with TMDA for just a little while on a secondary
account, and have found it to be very very useful. Thank you all for
this software.
Attached is a quick patch I created for searching LDAP as part of TMDA.
This is still very very small and just a simple search using LDAP and
if any results are returned it accepts it. I used an LDAP uri to hold the
the information in a single line.
examples:
from-ldap
"ldap://localhost:389/dc=example,dc=com?mail,cn?sub?(|%(keys)s)?bindname=uid=me%2Cou=People%2Cdc=example%2Cdc=com,X-BINDPW=itisme"
accept
from-ldap "ldap://localhost:389/cn=me,ou=abook,dc=example,dc=com??sub?(|%(keys)s)?"
accept
currently the %(keys)s substitution is very limited but can and will be
fixed. :)
I currently have an OID arch and thinking a small schema could be used to
store all of the users rules in LDAP.
-Jeremy
Index: TMDA/FilterParser.py
===================================================================
RCS file: /cvsroot/tmda/tmda/TMDA/FilterParser.py,v
retrieving revision 1.59
diff -u -r1.59 FilterParser.py
--- TMDA/FilterParser.py 11 Jul 2003 23:02:59 -0000 1.59
+++ TMDA/FilterParser.py 19 Aug 2003 01:09:37 -0000
@@ -222,7 +222,7 @@
bol_comment = re.compile(r'\s*#')
most_sources = re.compile(r"""
- ( (?:to|from)-(?:file|cdb|dbm|ezmlm|mailman|mysql|sql)
+ ( (?:to|from)-(?:file|cdb|dbm|ezmlm|mailman|mysql|sql|ldap)
| size | pipe
| (?:to|from) (?!-) )
""", re.VERBOSE | re.IGNORECASE)
@@ -268,6 +268,8 @@
'to-cdb' : ('optional',),
'from-dbm' : ('optional',),
'to-dbm' : ('optional',),
+ 'from-ldap' : ('optional',),
+ 'to-ldap' : ('optional',),
'from-ezmlm' : ('optional',),
'to-ezmlm' : ('optional',),
'from-mailman' : ('attr', 'optional' ),
@@ -720,6 +722,25 @@
source)
+ def __search_ldap(self, uri, keys, actions, source):
+ import ldap
+ import ldapurl
+ found_match = 0
+ LDAPurl = ldapurl.LDAPUrl(uri)
+ conn = ldap.initialize(LDAPurl.initializeUrl())
+ x = ")(mail=".join([ key.lower() for key in keys if key])
+ x = {"keys":"(mail=" + x + ")"}
+ filter = LDAPurl.filterstr % (x)
+ conn.simple_bind_s(LDAPurl.who,LDAPurl.cred)
+ r = conn.search_s(LDAPurl.dn, LDAPurl.scope,
+ filterstr=filter,
+ attrlist=LDAPurl.attrs, attrsonly=1)
+ if r:
+ found_match = 1
+ return found_match
+
+
+
def __search_cdb(self, pathname, keys, actions, source):
"""
Search DJB's constant databases; see <http:/cr.yp.to/cdb.html>.
@@ -947,6 +968,19 @@
found_match = self.__search_cdb(match, keys,
actions, source)
except cdb.error, e:
+ if not args.has_key('optional'):
+ raise MatchError(lineno, str(e))
+ if found_match:
+ break
+ # LDAP Databsse
+ if source in ('from-ldap', 'to-ldap'):
+ import ldap
+ import ldapurl
+ keys += self.__extract_domains(keys)
+ try:
+ found_match = self.__search_ldap(match, keys,
+ actions, source)
+ except (ldap.LDAPError,), e:
if not args.has_key('optional'):
raise MatchError(lineno, str(e))
if found_match: