python-ldap-2.4.10/ 0000755 0000764 0000144 00000000000 11764172736 014640 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Demo/ 0000755 0000764 0000144 00000000000 11764172736 015524 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Demo/sasl_bind.py 0000644 0000764 0000144 00000003630 11243207222 020013 0 ustar michael users 0000000 0000000 # For documentation, see comments in Module/LDAPObject.c and the
# ldap.sasl module documentation.
import ldap,ldap.sasl
ldap.sasl._trace_level=0
ldap.set_option(ldap.OPT_DEBUG_LEVEL,0)
for ldap_uri,sasl_mech,sasl_cb_value_dict in [
(
"ldap://nb2.stroeder.local:1390/",
'CRAM-MD5',
{
ldap.sasl.CB_AUTHNAME :'fred',
ldap.sasl.CB_PASS :'secret',
}
),
(
"ldap://nb2.stroeder.local:1390/",
'PLAIN',
{
ldap.sasl.CB_AUTHNAME :'fred',
ldap.sasl.CB_PASS :'secret',
}
),
(
"ldap://nb2.stroeder.local:1390/",
'LOGIN',
{
ldap.sasl.CB_AUTHNAME :'fred',
ldap.sasl.CB_PASS :'secret',
}
),
(
"ldapi://%2Ftmp%2Fopenldap-socket/",
'EXTERNAL',
{ }
),
(
"ldap://nb2.stroeder.local:1390/",
'GSSAPI',
{ }
),
(
"ldap://nb2.stroeder.local:1390/",
'NTLM',
{
ldap.sasl.CB_AUTHNAME :'fred',
ldap.sasl.CB_PASS :'secret',
}
),
(
"ldap://nb2.stroeder.local:1390/",
'DIGEST-MD5',
{
ldap.sasl.CB_AUTHNAME :'fred',
ldap.sasl.CB_PASS :'secret',
}
),
]:
sasl_auth = ldap.sasl.sasl(sasl_cb_value_dict,sasl_mech)
print 20*'*',sasl_auth.mech,20*'*'
# Open the LDAP connection
l = ldap.initialize(ldap_uri,trace_level=0)
# Set protocol version to LDAPv3 to enable SASL bind!
l.protocol_version = 3
try:
l.sasl_interactive_bind_s("", sasl_auth)
except ldap.LDAPError,e:
print 'Error using SASL mechanism',sasl_auth.mech,str(e)
else:
print 'Sucessfully bound using SASL mechanism:',sasl_auth.mech
try:
print 'Result of Who Am I? ext. op:',repr(l.whoami_s())
except ldap.LDAPError,e:
print 'Error using SASL mechanism',sasl_auth.mech,str(e)
try:
print 'OPT_X_SASL_USERNAME',repr(l.get_option(ldap.OPT_X_SASL_USERNAME))
except AttributeError:
pass
l.unbind()
del l
python-ldap-2.4.10/Demo/schema_tree.py 0000644 0000764 0000144 00000004507 10256025756 020355 0 ustar michael users 0000000 0000000 """
Outputs the object class tree read from LDAPv3 schema
of a given server
Usage: schema_oc_tree.py [--html] [LDAP URL]
"""
import sys,getopt,ldap,ldap.schema
ldap.trace_level = 1
def PrintSchemaTree(schema,se_class,se_tree,se_oid,level):
"""ASCII text output for console"""
se_obj = schema.get_obj(se_class,se_oid)
if se_obj!=None:
print '| '*(level-1)+'+---'*(level>0), \
', '.join(se_obj.names), \
'(%s)' % se_obj.oid
for sub_se_oid in se_tree[se_oid]:
print '| '*(level+1)
PrintSchemaTree(schema,se_class,se_tree,sub_se_oid,level+1)
def HTMLSchemaTree(schema,se_class,se_tree,se_oid,level):
"""HTML output for browser"""
se_obj = schema.get_obj(se_class,se_oid)
if se_obj!=None:
print """
%s (%s)
%s
""" % (', '.join(se_obj.names),se_obj.oid,se_obj.desc)
if se_tree[se_oid]:
print ''
for sub_se_oid in se_tree[se_oid]:
HTMLSchemaTree(schema,se_class,se_tree,sub_se_oid,level+1)
print '
'
print ''
ldap.set_option(ldap.OPT_DEBUG_LEVEL,0)
ldap._trace_level = 0
subschemasubentry_dn,schema = ldap.schema.urlfetch(sys.argv[-1],ldap.trace_level)
if subschemasubentry_dn is None:
print 'No sub schema sub entry found!'
sys.exit(1)
try:
options,args=getopt.getopt(sys.argv[1:],'',['html'])
except getopt.error,e:
print 'Error: %s\nUsage: schema_oc_tree.py [--html] [LDAP URL]'
html_output = options and options[0][0]=='--html'
oc_tree = schema.tree(ldap.schema.ObjectClass)
at_tree = schema.tree(ldap.schema.AttributeType)
#for k,v in oc_tree.items():
# print k,'->',v
#for k,v in at_tree.items():
# print k,'->',v
if html_output:
print """
Object class tree
Object class tree
"""
HTMLSchemaTree(schema,ldap.schema.ObjectClass,oc_tree,'2.5.6.0',0)
print """
Attribute type tree
"""
for a in schema.listall(ldap.schema.AttributeType):
if at_tree[a]:
HTMLSchemaTree(schema,ldap.schema.AttributeType,at_tree,a,0)
print
print """
"""
else:
print '*** Object class tree ***\n'
print
PrintSchemaTree(schema,ldap.schema.ObjectClass,oc_tree,'2.5.6.0',0)
print '\n*** Attribute types tree ***\n'
PrintSchemaTree(schema,ldap.schema.AttributeType,at_tree,'_',0)
python-ldap-2.4.10/Demo/simplebrowse.py 0000644 0000764 0000144 00000006151 07410130511 020566 0 ustar michael users 0000000 0000000 #! python
#
# simple LDAP server browsing example
#
import ldap
import string
from traceback import print_exc
url = "ldap://ldap.openldap.org/"
dn = "dc=openldap,dc=org"
print "Connecting to", url
l = ldap.initialize(url)
l.bind_s("", "", ldap.AUTH_SIMPLE);
lastdn = dn
dnlist = None
while 1:
#-- read a command
try:
cmd = raw_input(dn + "> ")
except EOFError:
print
break
try:
if cmd == "?":
print "cd - change DN to "
print "cd - change DN to number of last 'ls'"
print "cd - - change to previous DN"
print "cd .. - change to one-level higher DN"
print "cd - change to root DN"
print "ls - list children of crrent DN"
print ". - show attributes of current DN"
print "/ - list descendents matching filter "
print "? - show this help"
elif cmd == "ls":
print "Children of", `dn`, ":"
dnlist = []
#
# List the children at one level down from the current dn
# We use the filter 'objectclass=*' to match everything.
# We're not interested in attributes at this stage, so
# we specify [] as the list of attribute names to retreive.
#
for name,attrs in l.search_s(dn, ldap.SCOPE_ONELEVEL,
"objectclass=*", []):
#-- shorten resulting dns for output brevity
if name.startswith(dn+", "):
shortname = "+ "+name[len(dn)+2:]
elif name.endswith(", "+dn):
shortname = name[:-len(dn)-2]+" +"
else:
shortname = name
print " %3d. %s" % (len(dnlist), shortname)
dnlist.append(name)
elif cmd == "cd":
dn = ""
dnlist = None
elif cmd.startswith("cd "):
arg = cmd[3:]
if arg == '-':
lastdn,dn = dn,lastdn
elif arg == '..':
dn = string.join(ldap.explode_dn(dn)[1:], ",")
dn = string.strip(dn)
else:
try:
i = int(arg)
except:
godn = arg
else:
if dnlist is None:
print "do an ls first"
else:
godn = dnlist[i]
lastdn = dn
dn = godn
elif cmd == ".":
#
# Retrieve all the attributes for the current dn.
# We construct a search using SCOPE_BASE (ie just the
# given DN) and again filter with "objectclass=*".
# No attributes are listed, so the default is for
# the client to receive all attributes on the DN.
#
print "Attributes of", `dn`, ":"
for name,attrs in l.search_s(dn, ldap.SCOPE_BASE,
"objectclass=*"):
print " %-24s" % name
for k,vals in attrs.items():
for v in vals:
if len(v) > 200:
v = `v[:200]` + \
("... (%d bytes)" % len(v))
else:
v = `v`
print " %-12s: %s" % (k, v)
elif cmd.startswith("/"):
#
# Search descendent objects to match a given filter.
# We use SCOPE_SUBTREE to indicate descendents, and
# again specify an empty attribute list to indicate
# that we're not interested in them.
#
expr = cmd[1:]
print "Descendents matching filter", `expr`, ":"
for name,attrs in l.search_s(dn, ldap.SCOPE_SUBTREE,
expr, []):
print " %24s", name
else:
print "unknown command - try '?' for help"
except:
print_exc()
python-ldap-2.4.10/Demo/.cvsignore 0000644 0000764 0000144 00000000025 07507672213 017514 0 ustar michael users 0000000 0000000 *.pyc
*.pyo
*.bck
*~
python-ldap-2.4.10/Demo/pyasn1/ 0000755 0000764 0000144 00000000000 11764172736 016737 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Demo/pyasn1/readentrycontrol.py 0000644 0000764 0000144 00000006606 11573756502 022714 0 ustar michael users 0000000 0000000 #!/usr/bin/env python
"""
This sample script demonstrates the use of the pre-read control (see RFC 4527).
Originally contributed by Andreas Hasenack
Requires module pyasn1 (see http://pyasn1.sourceforge.net/)
"""
import pprint,ldap,ldap.modlist
from ldap.controls.readentry import PreReadControl,PostReadControl
uri = "ldap://localhost:2071/"
l = ldap.initialize(uri,trace_level=2)
l.simple_bind_s('uid=diradm,ou=schulung,dc=stroeder,dc=local','testsecret')
print """#---------------------------------------------------------------------------
# Add new entry
#---------------------------------------------------------------------------
"""
new_test_dn = "uid=ablume,ou=Users,ou=schulung,dc=stroeder,dc=local"
new_test_dn2 = "uid=ablume2,ou=Users,ou=schulung,dc=stroeder,dc=local"
new_test_entry = {
'objectClass':['account','posixAccount'],
'uid':['ablume'],
'cn':['Anna Blume'],
'uidNumber':['10000'],
'gidNumber':['10000'],
'homeDirectory':['/home/ablume'],
}
pr = PostReadControl(criticality=True,attrList=['entryUUID','entryCSN'])
msg_id = l.add_ext(
new_test_dn,
ldap.modlist.addModlist(new_test_entry),
serverctrls = [pr]
)
_,_,_,resp_ctrls = l.result3(msg_id)
print "resp_ctrls[0].dn:",resp_ctrls[0].dn
print "resp_ctrls[0].entry:";pprint.pprint(resp_ctrls[0].entry)
print """#---------------------------------------------------------------------------
# Modify entry
#---------------------------------------------------------------------------
"""
pr = PreReadControl(criticality=True,attrList=['uidNumber','gidNumber','entryCSN'])
msg_id = l.modify_ext(
new_test_dn,
[(ldap.MOD_INCREMENT, "uidNumber", "1"),(ldap.MOD_INCREMENT, "gidNumber", "1")],
serverctrls = [pr]
)
_,_,_,resp_ctrls = l.result3(msg_id)
print "resp_ctrls[0].dn:",resp_ctrls[0].dn
print "resp_ctrls[0].entry:";pprint.pprint(resp_ctrls[0].entry)
pr = PostReadControl(criticality=True,attrList=['uidNumber','gidNumber','entryCSN'])
msg_id = l.modify_ext(
new_test_dn,
[(ldap.MOD_INCREMENT, "uidNumber", "1"),(ldap.MOD_INCREMENT, "gidNumber", "1")],
serverctrls = [pr]
)
_,_,_,resp_ctrls = l.result3(msg_id)
print "resp_ctrls[0].dn:",resp_ctrls[0].dn
print "resp_ctrls[0].entry:";pprint.pprint(resp_ctrls[0].entry)
print """#---------------------------------------------------------------------------
# Rename entry
#---------------------------------------------------------------------------
"""
pr = PostReadControl(criticality=True,attrList=['uid'])
msg_id = l.rename(
new_test_dn,
"uid=ablume2",
delold=1,
serverctrls = [pr]
)
_,_,_,resp_ctrls = l.result3(msg_id)
print "resp_ctrls[0].dn:",resp_ctrls[0].dn
print "resp_ctrls[0].entry:";pprint.pprint(resp_ctrls[0].entry)
pr = PreReadControl(criticality=True,attrList=['uid'])
msg_id = l.rename(
new_test_dn2,
"uid=ablume",
delold=1,
serverctrls = [pr]
)
_,_,_,resp_ctrls = l.result3(msg_id)
print "resp_ctrls[0].dn:",resp_ctrls[0].dn
print "resp_ctrls[0].entry:";pprint.pprint(resp_ctrls[0].entry)
print """#---------------------------------------------------------------------------
# Delete entry
#---------------------------------------------------------------------------
"""
pr = PreReadControl(criticality=True,attrList=['*','+'])
msg_id = l.delete_ext(
new_test_dn,
serverctrls = [pr]
)
_,_,_,resp_ctrls = l.result3(msg_id)
print "resp_ctrls[0].dn:",resp_ctrls[0].dn
print "resp_ctrls[0].entry:";pprint.pprint(resp_ctrls[0].entry)
python-ldap-2.4.10/Demo/pyasn1/dds.py 0000644 0000764 0000144 00000002517 11704305353 020053 0 ustar michael users 0000000 0000000 # -*- coding: utf-8 -*-
"""
Demo script for Dynamic Entries (see RFC 2589)
This needs the following software:
Python
pyasn1
pyasn1-modules
python-ldap 2.4+
"""
from ldap.extop.dds import RefreshRequest,RefreshResponse
import sys,ldap,ldapurl,getpass
try:
ldap_url = ldapurl.LDAPUrl(sys.argv[1])
request_ttl = int(sys.argv[2])
except IndexError,ValueError:
print 'Usage: dds.py '
sys.exit(1)
# Set debugging level
#ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
ldapmodule_trace_level = 2
ldapmodule_trace_file = sys.stderr
ldap_conn = ldap.ldapobject.LDAPObject(
ldap_url.initializeUrl(),
trace_level=ldapmodule_trace_level,
trace_file=ldapmodule_trace_file
)
if ldap_url.cred is None:
print 'Password for %s:' % (repr(ldap_url.who))
ldap_url.cred = getpass.getpass()
try:
ldap_conn.simple_bind_s(ldap_url.who or '',ldap_url.cred or '')
except ldap.INVALID_CREDENTIALS,e:
print 'Simple bind failed:',str(e)
sys.exit(1)
else:
extreq = RefreshRequest(entryName=ldap_url.dn,requestTtl=request_ttl)
try:
extop_resp_obj = ldap_conn.extop_s(extreq,extop_resp_class=RefreshResponse)
except ldap.LDAPError,e:
print str(e)
else:
if extop_resp_obj.responseTtl!=request_ttl:
print 'Different response TTL:',extop_resp_obj.responseTtl
else:
print 'Response TTL:',extop_resp_obj.responseTtl
python-ldap-2.4.10/Demo/pyasn1/psearch.py 0000644 0000764 0000144 00000004067 11552002163 020722 0 ustar michael users 0000000 0000000 # -*- coding: utf-8 -*-
"""
Demo script for Persistent Search Control
(see http://tools.ietf.org/html/draft-ietf-ldapext-psearch)
See http://www.python-ldap.org/ for project details.
This needs the following software:
Python
pyasn1
pyasn1-modules
python-ldap 2.4+
"""
import sys,ldap,ldapurl,getpass
from ldap.controls.psearch import PersistentSearchControl,EntryChangeNotificationControl,CHANGE_TYPES_STR
try:
ldap_url = ldapurl.LDAPUrl(sys.argv[1])
except IndexError:
print 'Usage: psearch.py '
sys.exit(1)
# Set debugging level
#ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
ldapmodule_trace_level = 2
ldapmodule_trace_file = sys.stderr
ldap_conn = ldap.ldapobject.LDAPObject(
ldap_url.initializeUrl(),
trace_level=ldapmodule_trace_level,
trace_file=ldapmodule_trace_file
)
if ldap_url.cred is None:
print 'Password for %s:' % (repr(ldap_url.who))
ldap_url.cred = getpass.getpass()
try:
ldap_conn.simple_bind_s(ldap_url.who,ldap_url.cred)
except ldap.INVALID_CREDENTIALS,e:
print 'Simple bind failed:',str(e)
sys.exit(1)
psc = PersistentSearchControl()
msg_id = ldap_conn.search_ext(
ldap_url.dn,
ldap_url.scope,
ldap_url.filterstr,
attrlist = ldap_url.attrs or ['*','+'],
serverctrls=[psc],
)
while True:
try:
res_type,res_data,res_msgid,_,_,_ = ldap_conn.result4(
msg_id,
all=0,
timeout=10.0,
add_ctrls=1,
add_intermediates=1,
resp_ctrl_classes={EntryChangeNotificationControl.controlType:EntryChangeNotificationControl},
)
except ldap.TIMEOUT:
print 'Timeout waiting for results...'
else:
for dn,entry,srv_ctrls in res_data:
ecn_ctrls = [
c
for c in srv_ctrls
if c.controlType == EntryChangeNotificationControl.controlType
]
if ecn_ctrls:
changeType,previousDN,changeNumber = ecn_ctrls[0].changeType,ecn_ctrls[0].previousDN,ecn_ctrls[0].changeNumber
change_type_desc = CHANGE_TYPES_STR[changeType]
print 'changeType: %s (%d), changeNumber: %s, previousDN: %s' % (change_type_desc,changeType,changeNumber,repr(previousDN))
python-ldap-2.4.10/Demo/pyasn1/ppolicy.py 0000644 0000764 0000144 00000002741 11663516773 020775 0 ustar michael users 0000000 0000000 # -*- coding: utf-8 -*-
"""
Demo script for Password Policy Controls
(see http://tools.ietf.org/html/draft-behera-ldap-password-policy)
This needs the following software:
Python
pyasn1
pyasn1-modules
python-ldap 2.4+
"""
import sys,ldap,ldapurl,getpass
from ldap.controls.ppolicy import PasswordPolicyError,PasswordPolicyControl
try:
ldap_url = ldapurl.LDAPUrl(sys.argv[1])
except IndexError,ValueError:
print 'Usage: ppolicy.py '
sys.exit(1)
# Set debugging level
#ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
ldapmodule_trace_level = 2
ldapmodule_trace_file = sys.stderr
ldap_conn = ldap.ldapobject.LDAPObject(
ldap_url.initializeUrl(),
trace_level=ldapmodule_trace_level,
trace_file=ldapmodule_trace_file
)
if ldap_url.cred is None:
print 'Password for %s:' % (repr(ldap_url.who))
ldap_url.cred = getpass.getpass()
try:
msgid = ldap_conn.simple_bind(ldap_url.who,ldap_url.cred,serverctrls=[PasswordPolicyControl()])
res_type,res_data,res_msgid,res_ctrls = ldap_conn.result3(msgid)
except ldap.INVALID_CREDENTIALS,e:
print 'Simple bind failed:',str(e)
sys.exit(1)
else:
if res_ctrls[0].controlType==PasswordPolicyControl.controlType:
ppolicy_ctrl = res_ctrls[0]
print 'PasswordPolicyControl'
print 'error',repr(ppolicy_ctrl.error),(ppolicy_ctrl.error!=None)*repr(PasswordPolicyError(ppolicy_ctrl.error))
print 'timeBeforeExpiration',repr(ppolicy_ctrl.timeBeforeExpiration)
print 'graceAuthNsRemaining',repr(ppolicy_ctrl.graceAuthNsRemaining)
python-ldap-2.4.10/Demo/pyasn1/syncrepl.py 0000644 0000764 0000144 00000013024 11764172557 021151 0 ustar michael users 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
"""
This script implements a syncrepl consumer which syncs data from an OpenLDAP
server to a local (shelve) database.
Notes:
The bound user needs read access to the attributes entryDN and entryCSN.
This needs the following software:
Python
pyasn1 0.1.4+
pyasn1-modules
python-ldap 2.4.10+
"""
# Import the python-ldap modules
import ldap,ldapurl
# Import specific classes from python-ldap
from ldap.ldapobject import ReconnectLDAPObject
from ldap.syncrepl import SyncreplConsumer
# Import modules from Python standard lib
import shelve,signal,time,sys,logging
# Global state
watcher_running = True
ldap_connection = False
class SyncReplConsumer(ReconnectLDAPObject,SyncreplConsumer):
"""
Syncrepl Consumer interface
"""
def __init__(self,db_path,*args,**kwargs):
# Initialise the LDAP Connection first
ldap.ldapobject.ReconnectLDAPObject.__init__(self, *args, **kwargs)
# Now prepare the data store
self.__data = shelve.open(db_path, 'c')
# We need this for later internal use
self.__presentUUIDs = dict()
def __del__(self):
# Close the data store properly to avoid corruption
self.__data.close()
def syncrepl_get_cookie(self):
if 'cookie' in self.__data:
return self.__data['cookie']
def syncrepl_set_cookie(self,cookie):
self.__data['cookie'] = cookie
def syncrepl_entry(self,dn,attributes,uuid):
# First we determine the type of change we have here (and store away the previous data for later if needed)
previous_attributes = dict()
if uuid in self.__data:
change_type = 'modify'
previous_attributes = self.__data[uuid]
else:
change_type = 'add'
# Now we store our knowledge of the existence of this entry (including the DN as an attribute for convenience)
attributes['dn'] = dn
self.__data[uuid] = attributes
# Debugging
print 'Detected', change_type, 'of entry:', dn
# If we have a cookie then this is not our first time being run, so it must be a change
if 'ldap_cookie' in self.__data:
self.perform_application_sync(dn, attributes, previous_attributes)
def syncrepl_delete(self,uuids):
# Make sure we know about the UUID being deleted, just in case...
uuids = [uuid for uuid in uuids if uuid in self.__data]
# Delete all the UUID values we know of
for uuid in uuids:
print 'Detected deletion of entry:', self.__data[uuid]['dn']
del self.__data[uuid]
def syncrepl_present(self,uuids,refreshDeletes=False):
# If we have not been given any UUID values, then we have recieved all the present controls...
if uuids is None:
# We only do things if refreshDeletes is false as the syncrepl extension will call syncrepl_delete instead when it detects a delete notice
if refreshDeletes is False:
deletedEntries = [uuid for uuid in self.__data.keys() if uuid not in self.__presentUUIDs and uuid != 'ldap_cookie']
self.syncrepl_delete( deletedEntries )
# Phase is now completed, reset the list
self.__presentUUIDs = {}
else:
# Note down all the UUIDs we have been sent
for uuid in uuids:
self.__presentUUIDs[uuid] = True
def perform_application_sync(self,dn,attributes,previous_attributes):
print 'Performing application sync for:', dn
return True
# Shutdown handler
def commenceShutdown(signum, stack):
# Declare the needed global variables
global watcher_running, ldap_connection
print 'Shutting down!'
# We are no longer running
watcher_running = False
# Tear down the server connection
if( ldap_connection ):
del ldap_connection
# Shutdown
sys.exit(0)
# Time to actually begin execution
# Install our signal handlers
signal.signal(signal.SIGTERM,commenceShutdown)
signal.signal(signal.SIGINT,commenceShutdown)
try:
ldap_url = ldapurl.LDAPUrl(sys.argv[1])
database_path = sys.argv[2]
except IndexError,e:
print 'Usage: syncrepl-client.py '
sys.exit(1)
except ValueError,e:
print 'Error parsing command-line arguments:',str(e)
sys.exit(1)
while watcher_running:
print 'Connecting to LDAP server now...'
# Prepare the LDAP server connection (triggers the connection as well)
ldap_connection = SyncReplConsumer(database_path,ldap_url.initializeUrl())
# Now we login to the LDAP server
try:
ldap_connection.simple_bind_s(ldap_url.who,ldap_url.cred)
except ldap.INVALID_CREDENTIALS, e:
print 'Login to LDAP server failed: ', str(e)
sys.exit(1)
except ldap.SERVER_DOWN:
print 'LDAP server is down, going to retry.'
time.sleep(5)
continue
# Commence the syncing
print 'Commencing sync process'
ldap_search = ldap_connection.syncrepl_search(
ldap_url.dn or '',
ldap_url.scope or ldap.SCOPE_SUBTREE,
mode = 'refreshAndPersist',
filterstr = ldap_url.filterstr or '(objectClass=*)'
)
try:
while ldap_connection.syncrepl_poll( all = 1, msgid = ldap_search):
pass
except KeyboardInterrupt:
# User asked to exit
commenceShutdown()
pass
except Exception, e:
# Handle any exception
if watcher_running:
print 'Encountered a problem, going to retry. Error:', str(e)
time.sleep(5)
pass
python-ldap-2.4.10/Demo/pyasn1/README 0000644 0000764 0000144 00000000274 11544144266 017613 0 ustar michael users 0000000 0000000 The sample modules/scripts herein require modules pyasn1 and pyasn1-modules.
http://pyasn1.sourceforge.net/
http://pypi.python.org/pypi/pyasn1
http://pypi.python.org/pypi/pyasn1-modules
python-ldap-2.4.10/Demo/pyasn1/sessiontrack.py 0000644 0000764 0000144 00000002517 11604613510 022005 0 ustar michael users 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
"""
demo_track_ldap_session.py
Client-seitige Demo-Implementierung von Session Tracking Control
http://tools.ietf.org/html/draft-wahl-ldap-session-03
"""
__version__ = '0.1'
import sys,getpass,ldap,ldapurl
from ldap.controls.sessiontrack import SessionTrackingControl,SESSION_TRACKING_FORMAT_OID_USERNAME
try:
ldap_url = ldapurl.LDAPUrl(sys.argv[1])
except IndexError,ValueError:
print 'Usage: %s ' % (sys.argv[0])
sys.exit(1)
# Set debugging level
#ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
ldapmodule_trace_level = 2
ldapmodule_trace_file = sys.stderr
ldap_conn = ldap.ldapobject.LDAPObject(
ldap_url.initializeUrl(),
trace_level=ldapmodule_trace_level,
trace_file=ldapmodule_trace_file
)
if ldap_url.who and ldap_url.cred is None:
print 'Password for %s:' % (repr(ldap_url.who))
ldap_url.cred = getpass.getpass()
try:
ldap_conn.simple_bind_s(ldap_url.who or '',ldap_url.cred or '')
except ldap.INVALID_CREDENTIALS,e:
print 'Simple bind failed:',str(e)
sys.exit(1)
st_ctrl = SessionTrackingControl(
'192.0.2.1',
'app.example.com',
SESSION_TRACKING_FORMAT_OID_USERNAME,
'bloggs'
)
ldap_conn.search_ext_s(
ldap_url.dn or '',
ldap_url.scope or ldap.SCOPE_SUBTREE,
ldap_url.filterstr or '(objectClass=*)',
ldap_url.attrs or ['*'],
serverctrls=[st_ctrl]
)
python-ldap-2.4.10/Demo/pickle_ldapobject.py 0000644 0000764 0000144 00000000631 07650130021 021510 0 ustar michael users 0000000 0000000 import os,ldap,pickle
temp_file_name = os.path.join(os.environ.get('TMP','/tmp'),'pickle_ldap-%d' % (os.getpid()))
l1 = ldap.ldapobject.ReconnectLDAPObject('ldap://localhost:1390',trace_level=1)
l1.protocol_version = 3
l1.search_s('',ldap.SCOPE_BASE,'(objectClass=*)')
pickle.dump(l1,open(temp_file_name,'wb'))
l2 = pickle.load(open(temp_file_name,'rb'))
l2.search_s('',ldap.SCOPE_BASE,'(objectClass=*)')
python-ldap-2.4.10/Demo/passwd_ext_op.py 0000644 0000764 0000144 00000001415 10137547500 020742 0 ustar michael users 0000000 0000000 """
Example showing the use of the password extended operation.
"""
import sys,ldap,ldapurl,getpass
# Set debugging level
ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
ldapmodule_trace_level = 2
ldapmodule_trace_file = sys.stderr
lu = ldapurl.LDAPUrl(sys.argv[1])
print 'Old password'
oldpw = getpass.getpass()
print 'New password'
newpw = getpass.getpass()
# Set path name of file containing all CA certificates
# needed to validate server certificates
ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,'/etc/httpd/ssl.crt/myCA-cacerts.pem')
# Create LDAPObject instance
l = ldap.initialize(lu.initializeUrl(),trace_level=ldapmodule_trace_level,trace_file=ldapmodule_trace_file)
l.protocol_version=ldap.VERSION3
l.simple_bind_s(lu.dn,oldpw)
l.passwd(lu.dn,oldpw,newpw)
l.unbind_s()
python-ldap-2.4.10/Demo/schema.py 0000644 0000764 0000144 00000003625 11605554276 017341 0 ustar michael users 0000000 0000000 import sys,ldap,ldap.schema
schema_attrs = ldap.schema.SCHEMA_ATTRS
ldap.set_option(ldap.OPT_DEBUG_LEVEL,0)
ldap._trace_level = 0
subschemasubentry_dn,schema = ldap.schema.urlfetch(sys.argv[-1])
if subschemasubentry_dn is None:
print 'No sub schema sub entry found!'
sys.exit(1)
if schema.non_unique_oids:
print '*** Schema errors ***'
print 'non-unique OIDs:\n','\r\n'.join(schema.non_unique_oids)
print '*** Schema from',repr(subschemasubentry_dn)
# Display schema
for attr_type,schema_class in ldap.schema.SCHEMA_CLASS_MAPPING.items():
print '*'*20,attr_type,'*'*20
for element_id in schema.listall(schema_class):
se_orig = schema.get_obj(schema_class,element_id)
print attr_type,str(se_orig)
print '*** Testing object class inetOrgPerson ***'
drink = schema.get_obj(ldap.schema.AttributeType,'favouriteDrink')
if not drink is None:
print '*** drink ***'
print 'drink.names',repr(drink.names)
print 'drink.collective',repr(drink.collective)
inetOrgPerson = schema.get_obj(ldap.schema.ObjectClass,'inetOrgPerson')
if not inetOrgPerson is None:
print inetOrgPerson.must,inetOrgPerson.may
print '*** person,organizationalPerson,inetOrgPerson ***'
try:
print schema.attribute_types(
['person','organizationalPerson','inetOrgPerson']
)
print schema.attribute_types(
['person','organizationalPerson','inetOrgPerson'],
attr_type_filter = [
('no_user_mod',[0]),
('usage',range(2)),
]
)
except KeyError,e:
print '***KeyError',str(e)
schema.ldap_entry()
print str(schema.get_obj(ldap.schema.MatchingRule,'2.5.13.0'))
print str(schema.get_obj(ldap.schema.MatchingRuleUse,'2.5.13.0'))
print str(schema.get_obj(ldap.schema.AttributeType,'name'))
print str(schema.get_inheritedobj(ldap.schema.AttributeType,'cn',['syntax','equality','substr','ordering']))
must_attr,may_attr = schema.attribute_types(['person','organizationalPerson','inetOrgPerson'],raise_keyerror=0)
python-ldap-2.4.10/Demo/simple.py 0000644 0000764 0000144 00000004506 07426477316 017376 0 ustar michael users 0000000 0000000 import sys,getpass
import ldap
#l = ldap.open("localhost", 31001)
l = ldap.open("marta.it.uq.edu.au")
login_dn = "cn=root,ou=CSEE,o=UQ,c=AU"
login_pw = getpass.getpass("Password for %s: " % login_dn)
l.simple_bind_s(login_dn, login_pw)
#
# create a new sub organisation
#
try:
dn = "ou=CSEE,o=UQ,c=AU"
print "Adding", repr(dn)
l.add_s(dn,
[
("objectclass",["organizationalUnit"]),
("ou", ["CSEE"]),
("description", [
"Department of Computer Science and Electrical Engineering"]),
]
)
except _ldap.LDAPError:
pass
#
# create an entry for me
#
dn = "cn=David Leonard,ou=CSEE,o=UQ,c=AU"
print "Updating", repr(dn)
try:
l.delete_s(dn)
except:
pass
l.add_s(dn,
[
("objectclass", ["organizationalPerson"]),
("sn", ["Leonard"]),
("cn", ["David Leonard"]),
("description", ["Ph.D. student"]),
("display-name", ["David Leonard"]),
#("commonname", ["David Leonard"]),
("mail", ["david.leonard@csee.uq.edu.au"]),
("othermailbox", ["d@openbsd.org"]),
("givenname", ["David"]),
("surname", ["Leonard"]),
("seeAlso", ["http://www.csee.uq.edu.au/~leonard/"]),
("url", ["http://www.csee.uq.edu.au/~leonard/"]),
#("homephone", []),
#("fax", []),
#("otherfacsimiletelephonenumber",[]),
#("officefax", []),
#("mobile", []),
#("otherpager", []),
#("officepager", []),
#("pager", []),
("info", ["info"]),
("title", ["Mr"]),
#("telephonenumber", []),
("l", ["Brisbane"]),
("st", ["Queensland"]),
("c", ["AU"]),
("co", ["co"]),
("o", ["UQ"]),
("ou", ["CSEE"]),
#("homepostaladdress", []),
#("postaladdress", []),
#("streetaddress", []),
#("street", []),
("department", ["CSEE"]),
("comment", ["comment"]),
#("postalcode", []),
("physicaldeliveryofficename", ["Bldg 78, UQ, St Lucia"]),
("preferredDeliveryMethod", ["email"]),
("initials", ["DRL"]),
("conferenceinformation", ["MS-conferenceinformation"]),
#("usercertificate", []),
("labeleduri", ["labeleduri"]),
("manager", ["cn=Jaga Indulska"]),
("reports", ["reports"]),
("jpegPhoto", [open("/www/leonard/leonard.jpg","r").read()]),
("uid", ["leonard"]),
("userPassword", [""])
])
#
# search beneath the CSEE/UQ/AU tree
#
res = l.search_s(
"ou=CSEE, o=UQ, c=AU",
_ldap.SCOPE_SUBTREE,
"objectclass=*",
)
print res
l.unbind()
python-ldap-2.4.10/Demo/ldapcontrols.py 0000644 0000764 0000144 00000001477 10256025543 020577 0 ustar michael users 0000000 0000000 import ldap,ldapurl,pprint
from ldap.controls import LDAPControl,BooleanControl
l = ldap.initialize('ldap://localhost:1390',trace_level=2)
print 60*'#'
pprint.pprint(l.get_option(ldap.OPT_SERVER_CONTROLS))
l.manage_dsa_it(1,1)
pprint.pprint(l.get_option(ldap.OPT_SERVER_CONTROLS))
print 60*'#'
# Search with ManageDsaIT control (which has no value)
pprint.pprint(l.search_ext_s(
'cn=Test-Referral,ou=Testing,dc=stroeder,dc=de',
ldap.SCOPE_BASE,
'(objectClass=*)',
['*','+'],
serverctrls = [ LDAPControl('2.16.840.1.113730.3.4.2',1,None) ],
))
print 60*'#'
# Search with Subentries control (which has boolean value)
pprint.pprint(l.search_ext_s(
'dc=stroeder,dc=de',
ldap.SCOPE_SUBTREE,
'(objectClass=subentry)',
['*','+'],
serverctrls = [ BooleanControl('1.3.6.1.4.1.4203.1.10.1',1,1) ],
))
print 60*'#'
python-ldap-2.4.10/Demo/resiter.py 0000644 0000764 0000144 00000001301 10333634551 017533 0 ustar michael users 0000000 0000000 """
Demo for using ldap.resiter.ResultProcessor
written by Michael Stroeder
See http://python-ldap.sourceforge.net for details.
\$Id: resiter.py,v 1.1 2005/11/07 11:24:25 stroeder Exp $
Python compability note:
Requires Python 2.3+
"""
import ldap,ldap.resiter
class LDAPObject(ldap.ldapobject.LDAPObject,ldap.resiter.ResultProcessor):
pass
l = LDAPObject('ldap://localhost:1390',trace_level=1)
l.protocol_version = 3
msgid = l.search('dc=stroeder,dc=de',ldap.SCOPE_SUBTREE,'(cn=m*)')
result_iter = l.allresults(msgid)
for result_type,result_list,result_msgid,result_serverctrls in result_iter:
print result_type,result_list,result_msgid,result_serverctrls
l.unbind_s()
python-ldap-2.4.10/Demo/matchedvalues.py 0000644 0000764 0000144 00000003554 10655566727 020737 0 ustar michael users 0000000 0000000 #!/usr/bin/env python
#
# demo for matched values control (RFC 3876)
#
# suppose the uid=jsmith LDAP entry has two mail attributes:
#
# dn: uid=jsmith,ou=People,dc=example,dc=com
# (...)
# mail: jsmith@example.com
# mail: jsmith@example.org
#
# Let's say you want to fetch only the example.org email. Without MV,
# you would first fetch all mail attributes and then filter them further
# on the client. With the MV control, the result can be given to the
# client already filtered.
#
# Sample output:
# $ ./matchedvalues.py
# LDAP filter used: (&(objectClass=inetOrgPerson)(mail=*@example.org))
# Requesting 'mail' attribute back
#
# No matched values control:
# dn: uid=jsmith,ou=People,dc=example,dc=com
# mail: jsmith@example.org
# mail: john@example.com
#
# Matched values control: (mail=*@example.org)
# dn: uid=jsmith,ou=People,dc=example,dc=com
# mail: jsmith@example.org
import ldap
from ldap.controls import MatchedValuesControl
def print_result(search_result):
for n in range(len(search_result)):
print "dn: %s" % search_result[n][0]
for attr in search_result[n][1].keys():
for i in range(len(search_result[n][1][attr])):
print "%s: %s" % (attr, search_result[n][1][attr][i])
print
uri = "ldap://ldap.example.com"
base = "dc=example,dc=com"
scope = ldap.SCOPE_SUBTREE
filter = "(&(objectClass=inetOrgPerson)(mail=*@example.org))"
control_filter = "(mail=*@example.org)"
ld = ldap.initialize(uri)
mv = MatchedValuesControl(criticality=True, controlValue=control_filter)
res = ld.search_ext_s(base, scope, filter, attrlist = ['mail'])
print "LDAP filter used: %s" % filter
print "Requesting 'mail' attribute back"
print
print "No matched values control:"
print_result(res)
res = ld.search_ext_s(base, scope, filter, attrlist = ['mail'], serverctrls = [mv])
print "Matched values control: %s" % control_filter
print_result(res)
python-ldap-2.4.10/Demo/initialize.py 0000644 0000764 0000144 00000005456 11764172557 020252 0 ustar michael users 0000000 0000000 """
Various examples how to connect to a LDAP host with the new
factory function ldap.initialize() introduced in OpenLDAP 2 API.
Assuming you have LDAP servers running on
ldap://localhost:1390 (LDAP with StartTLS)
ldaps://localhost:1391 (LDAP over SSL)
ldapi://%2ftmp%2fopenldap2 (domain socket /tmp/openldap2)
"""
import sys,os,ldap
# Switch off processing .ldaprc or ldap.conf
os.environ['LDAPNOINIT']='1'
# Set debugging level
#ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
ldapmodule_trace_level = 1
ldapmodule_trace_file = sys.stderr
ldap._trace_level = ldapmodule_trace_level
# Complete path name of the file containing all trusted CA certs
CACERTDIR='/etc/ssl/certs'
print """##################################################################
# LDAPv3 connection with StartTLS ext. op.
##################################################################
"""
# Create LDAPObject instance
l = ldap.initialize('ldap://localhost:1390',trace_level=ldapmodule_trace_level,trace_file=ldapmodule_trace_file)
# Set LDAP protocol version used
l.protocol_version=ldap.VERSION3
# Force cert validation
l.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_DEMAND)
# Set path name of file containing all trusted CA certificates
l.set_option(ldap.OPT_X_TLS_CACERTDIR,CACERTDIR)
# Force libldap to create a new SSL context (must be last TLS option!)
l.set_option(ldap.OPT_X_TLS_NEWCTX,0)
# Now try StartTLS extended operation
l.start_tls_s()
# Try an explicit anon bind to provoke failure
l.simple_bind_s('','')
# Close connection
l.unbind_s()
print """##################################################################
# LDAPv3 connection over SSL
##################################################################
"""
# Create LDAPObject instance
l = ldap.initialize('ldaps://localhost:1391',trace_level=ldapmodule_trace_level,trace_file=ldapmodule_trace_file)
# Set LDAP protocol version used
l.protocol_version=ldap.VERSION3
# Force cert validation
l.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_DEMAND)
# Set path name of file containing all trusted CA certificates
l.set_option(ldap.OPT_X_TLS_CACERTDIR,CACERTDIR)
# Force libldap to create a new SSL context (must be last TLS option!)
l.set_option(ldap.OPT_X_TLS_NEWCTX,0)
# Try an explicit anon bind to provoke failure
l.simple_bind_s('','')
# Close connection
l.unbind_s()
print """##################################################################
# LDAPv3 connection over Unix domain socket
##################################################################
"""
# Create LDAPObject instance
l = ldap.initialize('ldapi://%2ftmp%2fopenldap-socket',trace_level=ldapmodule_trace_level,trace_file=ldapmodule_trace_file)
# Set LDAP protocol version used
l.protocol_version=ldap.VERSION3
# Try an explicit anon bind to provoke failure
l.simple_bind_s('','')
# Close connection
l.unbind_s()
python-ldap-2.4.10/Demo/rename.py 0000644 0000764 0000144 00000002031 07426477316 017343 0 ustar michael users 0000000 0000000 import ldap
from getpass import getpass
# Create LDAPObject instance
l = ldap.initialize('ldap://localhost:1389',trace_level=1)
print 'Password:'
cred = getpass()
try:
# Set LDAP protocol version used
l.set_option(ldap.OPT_PROTOCOL_VERSION,3)
# Try a bind to provoke failure if protocol version is not supported
l.bind_s('cn=root,dc=stroeder,dc=com',cred,ldap.AUTH_SIMPLE)
print 'Using rename_s():'
l.rename_s(
'uid=fred,ou=Unstructured testing tree,dc=stroeder,dc=com',
'cn=Fred Feuerstein',
'dc=stroeder,dc=com',
0
)
l.rename_s(
'cn=Fred Feuerstein,dc=stroeder,dc=com',
'uid=fred',
'ou=Unstructured testing tree,dc=stroeder,dc=com',
0
)
m = l.rename(
'uid=fred,ou=Unstructured testing tree,dc=stroeder,dc=com',
'cn=Fred Feuerstein',
'dc=stroeder,dc=com',
0
)
r = l.result(m,1)
m = l.rename(
'cn=Fred Feuerstein,dc=stroeder,dc=com',
'uid=fred',
'ou=Unstructured testing tree,dc=stroeder,dc=com',
0
)
r = l.result(m,1)
finally:
l.unbind_s()
python-ldap-2.4.10/Demo/reconnect.py 0000644 0000764 0000144 00000001031 07524237466 020052 0 ustar michael users 0000000 0000000 import sys,time,ldap,ldap.ldapobject,ldapurl
from ldap.ldapobject import *
ldap_url = ldapurl.LDAPUrl(sys.argv[1])
ldap_url.applyDefaults({
'who':'',
'cred':'',
'filterstr':'(objectClass=*)',
'scope':ldap.SCOPE_BASE
})
ldap.trace_level=1
l = ldap.ldapobject.ReconnectLDAPObject(
ldap_url.initializeUrl(),trace_level=ldap.trace_level
)
l.protocol_version = ldap.VERSION3
l.simple_bind_s(ldap_url.who,ldap_url.cred)
while 1:
l.search_s(ldap_url.dn,ldap_url.scope,ldap_url.filterstr,ldap_url.attrs)
sys.stdin.readline()
python-ldap-2.4.10/Demo/page_control.py 0000644 0000764 0000144 00000003312 11545152005 020531 0 ustar michael users 0000000 0000000 url = "ldap://localhost:1390/"
base = "dc=stroeder,dc=de"
search_flt = r'(objectClass=*)'
page_size = 10
import ldap,pprint
from ldap.controls import SimplePagedResultsControl
searchreq_attrlist=['cn','entryDN','entryUUID','mail','objectClass']
#ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
ldap.set_option(ldap.OPT_REFERRALS, 0)
l = ldap.initialize(url,trace_level=1)
l.protocol_version = 3
l.simple_bind_s("", "")
req_ctrl = SimplePagedResultsControl(True,size=page_size,cookie='')
known_ldap_resp_ctrls = {
SimplePagedResultsControl.controlType:SimplePagedResultsControl,
}
# Send search request
msgid = l.search_ext(
base,
ldap.SCOPE_SUBTREE,
search_flt,
attrlist=searchreq_attrlist,
serverctrls=[req_ctrl]
)
pages = 0
while True:
pages += 1
print "Getting page %d" % (pages)
rtype, rdata, rmsgid, serverctrls = l.result3(msgid,resp_ctrl_classes=known_ldap_resp_ctrls)
print '%d results' % len(rdata)
print 'serverctrls=',pprint.pprint(serverctrls)
# pprint.pprint(rdata)
pctrls = [
c
for c in serverctrls
if c.controlType == SimplePagedResultsControl.controlType
]
if pctrls:
print 'pctrls[0].size',repr(pctrls[0].size)
print 'pctrls[0].cookie',repr(pctrls[0].cookie)
if pctrls[0].cookie:
# Copy cookie from response control to request control
req_ctrl.cookie = pctrls[0].cookie
msgid = l.search_ext(
base,
ldap.SCOPE_SUBTREE,
search_flt,
attrlist=searchreq_attrlist,
serverctrls=[req_ctrl]
)
else:
break
else:
print "Warning: Server ignores RFC 2696 control."
break
l.unbind_s()
python-ldap-2.4.10/Demo/ms_ad_bind.py 0000644 0000764 0000144 00000002043 11004050475 020132 0 ustar michael users 0000000 0000000 # How to bind to MS AD with python-ldap and various methods
import ldap,ldap.sasl
ldap_uri = "ldap://dc1.example.com"
dn = "CN=Anna Blume,CN=Users,DC=addomain,DC=example,DC=com"
sAMAccountName = "ABlume"
userPrincipalName = "ablume@addomain.example.com"
password = 'testsecret'
trace_level = 2
l = ldap.initialize(ldap_uri,trace_level=trace_level)
# Normal LDAPv3 compliant simple bind
l.simple_bind_s(dn,password)
# This is AD-specific and not LDAPv3 compliant
l.simple_bind_s(userPrincipalName,password)
# This is AD-specific and not LDAPv3 compliant
l.simple_bind_s(userPrincipalName,password)
# SASL bind with mech DIGEST-MD5 with sAMAccountName as SASL user name
sasl_auth = ldap.sasl.sasl(
{
ldap.sasl.CB_AUTHNAME:sAMAccountName,
ldap.sasl.CB_PASS :password,
},
'DIGEST-MD5'
)
l.sasl_interactive_bind_s("", sasl_auth)
# SASL bind with mech GSSAPI
# with the help of Kerberos V TGT obtained before with command
# kinit ablume@ADDOMAIN.EXAMPLE.COM
sasl_auth = ldap.sasl.sasl({},'GSSAPI')
l.sasl_interactive_bind_s("", sasl_auth)
python-ldap-2.4.10/Demo/paged_search_ext_s.py 0000644 0000764 0000144 00000005714 11704305351 021675 0 ustar michael users 0000000 0000000 url = "ldap://localhost:1390/"
base = "dc=stroeder,dc=de"
search_flt = r'(objectClass=*)'
searchreq_attrlist=['cn','entryDN','entryUUID','mail','objectClass']
from ldap.ldapobject import ReconnectLDAPObject
import ldap,pprint
from ldap.controls import SimplePagedResultsControl
class PagedResultsSearchObject:
page_size = 50
def paged_search_ext_s(self,base,scope,filterstr='(objectClass=*)',attrlist=None,attrsonly=0,serverctrls=None,clientctrls=None,timeout=-1,sizelimit=0):
"""
Behaves exactly like LDAPObject.search_ext_s() but internally uses the
simple paged results control to retrieve search results in chunks.
This is non-sense for really large results sets which you would like
to process one-by-one
"""
while True: # loop for reconnecting if necessary
req_ctrl = SimplePagedResultsControl(True,size=self.page_size,cookie='')
try:
# Send first search request
msgid = self.search_ext(
base,
scope,
filterstr=filterstr,
attrlist=attrlist,
attrsonly=attrsonly,
serverctrls=(serverctrls or [])+[req_ctrl],
clientctrls=clientctrls,
timeout=timeout,
sizelimit=sizelimit
)
result_pages = 0
all_results = []
while True:
rtype, rdata, rmsgid, rctrls = self.result3(msgid)
all_results.extend(rdata)
result_pages += 1
# Extract the simple paged results response control
pctrls = [
c
for c in rctrls
if c.controlType == SimplePagedResultsControl.controlType
]
if pctrls:
if pctrls[0].cookie:
# Copy cookie from response control to request control
req_ctrl.cookie = pctrls[0].cookie
msgid = self.search_ext(
base,
scope,
filterstr=filterstr,
attrlist=attrlist,
attrsonly=attrsonly,
serverctrls=(serverctrls or [])+[req_ctrl],
clientctrls=clientctrls,
timeout=timeout,
sizelimit=sizelimit
)
else:
break # no more pages available
except ldap.SERVER_DOWN,e:
try:
self.reconnect(self._uri)
except AttributeError:
raise e
else:
return result_pages,all_results
class MyLDAPObject(ReconnectLDAPObject,PagedResultsSearchObject):
pass
#ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
ldap.set_option(ldap.OPT_REFERRALS, 0)
l = MyLDAPObject(url,trace_level=2,retry_max=100,retry_delay=2)
l.protocol_version = 3
l.simple_bind_s("", "")
l.page_size=10
# Send search request
result_pages,all_results = l.paged_search_ext_s(
base,
ldap.SCOPE_SUBTREE,
search_flt,
attrlist=searchreq_attrlist,
serverctrls=None
)
l.unbind_s()
print 'Received %d results in %d pages.' % (len(all_results),result_pages)
python-ldap-2.4.10/Demo/options.py 0000644 0000764 0000144 00000001641 07635354564 017576 0 ustar michael users 0000000 0000000
import ldap
host="localhost:1390"
print "API info:",ldap.get_option(ldap.OPT_API_INFO)
print "debug level:",ldap.get_option(ldap.OPT_DEBUG_LEVEL)
#print "Setting debug level to 255..."
#ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
#print "debug level:",ldap.get_option(ldap.OPT_DEBUG_LEVEL)
print "default size limit:",ldap.get_option(ldap.OPT_SIZELIMIT)
print "Setting default size limit to 10..."
ldap.set_option(ldap.OPT_SIZELIMIT,10)
print "default size limit:",ldap.get_option(ldap.OPT_SIZELIMIT)
print "Creating connection to",host,"..."
l=ldap.init(host)
print "size limit:",l.get_option(ldap.OPT_SIZELIMIT)
print "Setting connection size limit to 20..."
l.set_option(ldap.OPT_SIZELIMIT,20)
print "size limit:",l.get_option(ldap.OPT_SIZELIMIT)
#print "Setting time limit to 60 secs..."
l.set_option(ldap.OPT_TIMELIMIT,60)
#print "time limit:",l.get_option(ldap.OPT_TIMELIMIT)
print "Binding..."
l.simple_bind_s("","")
python-ldap-2.4.10/Demo/Lib/ 0000755 0000764 0000144 00000000000 11764172736 016232 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Demo/Lib/.cvsignore 0000644 0000764 0000144 00000000025 07507672213 020222 0 ustar michael users 0000000 0000000 *.pyc
*.pyo
*.bck
*~
python-ldap-2.4.10/Demo/Lib/ldap/ 0000755 0000764 0000144 00000000000 11764172736 017152 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Demo/Lib/ldap/.cvsignore 0000644 0000764 0000144 00000000025 07507672213 021142 0 ustar michael users 0000000 0000000 *.pyc
*.pyo
*.bck
*~
python-ldap-2.4.10/Demo/Lib/ldap/async/ 0000755 0000764 0000144 00000000000 11764172736 020267 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Demo/Lib/ldap/async/sizelimit.py 0000644 0000764 0000144 00000002040 10411503653 022626 0 ustar michael users 0000000 0000000 """
ldifwriter - using ldap.async module for retrieving partial results
in a list even though the exception ldap.SIZELIMIT_EXCEEDED
was raised.output of LDIF stream
Written by Michael Stroeder
$Id: sizelimit.py,v 1.4 2006/03/26 12:23:07 stroeder Exp $
This example translates the naming context of data read from
input, sanitizes some attributes, maps/removes object classes,
maps/removes attributes., etc. It's far from being complete though.
Python compability note:
Tested on Python 2.0+, should run on Python 1.5.x.
"""
import sys,ldap,ldap.async
s = ldap.async.List(
ldap.initialize('ldap://localhost:1390'),
)
s.startSearch(
'dc=stroeder,dc=de',
ldap.SCOPE_SUBTREE,
'(objectClass=*)',
)
try:
partial = s.processResults()
except ldap.SIZELIMIT_EXCEEDED:
sys.stderr.write('Warning: Server-side size limit exceeded.\n')
else:
if partial:
sys.stderr.write('Warning: Only partial results received.\n')
sys.stderr.write(
'%d results received.\n' % (
len(s.allResults)
)
)
python-ldap-2.4.10/Demo/Lib/ldap/async/.cvsignore 0000644 0000764 0000144 00000000025 07520013005 022236 0 ustar michael users 0000000 0000000 *.pyc
*.pyo
*.bck
*~
python-ldap-2.4.10/Demo/Lib/ldap/async/deltree.py 0000644 0000764 0000144 00000005111 11235000725 022240 0 ustar michael users 0000000 0000000 import ldap,ldap.async
class DeleteLeafs(ldap.async.AsyncSearchHandler):
"""
Class for deleting entries which are results of a search.
DNs of Non-leaf entries are collected in DeleteLeafs.nonLeafEntries.
"""
_entryResultTypes = ldap.async._entryResultTypes
def __init__(self,l):
ldap.async.AsyncSearchHandler.__init__(self,l)
self.nonLeafEntries = []
self.deletedEntries = 0
def startSearch(self,searchRoot,searchScope):
if not searchScope in [ldap.SCOPE_ONELEVEL,ldap.SCOPE_SUBTREE]:
raise ValueError, "Parameter searchScope must be either ldap.SCOPE_ONELEVEL or ldap.SCOPE_SUBTREE."
self.nonLeafEntries = []
self.deletedEntries = 0
ldap.async.AsyncSearchHandler.startSearch(
self,
searchRoot,
searchScope,
filterStr='(objectClass=*)',
attrList=['hasSubordinates','numSubordinates'],
attrsOnly=0,
)
def _processSingleResult(self,resultType,resultItem):
if self._entryResultTypes.has_key(resultType):
# Don't process search references
dn,entry = resultItem
hasSubordinates = entry.get(
'hasSubordinates',
entry.get('hassubordinates',['FALSE']
)
)[0]
numSubordinates = entry.get(
'numSubordinates',
entry.get('numsubordinates',['0'])
)[0]
if hasSubordinates=='TRUE' or int(numSubordinates):
self.nonLeafEntries.append(dn)
else:
try:
self._l.delete_s(dn)
except ldap.NOT_ALLOWED_ON_NONLEAF,e:
self.nonLeafEntries.append(dn)
else:
self.deletedEntries = self.deletedEntries+1
def DelTree(l,dn,scope=ldap.SCOPE_ONELEVEL):
"""
Recursively delete entries below or including entry with name dn.
"""
leafs_deleter = DeleteLeafs(l)
leafs_deleter.startSearch(dn,scope)
leafs_deleter.processResults()
deleted_entries = leafs_deleter.deletedEntries
non_leaf_entries = leafs_deleter.nonLeafEntries[:]
while non_leaf_entries:
dn = non_leaf_entries.pop()
print deleted_entries,len(non_leaf_entries),dn
leafs_deleter.startSearch(dn,ldap.SCOPE_SUBTREE)
leafs_deleter.processResults()
deleted_entries = deleted_entries+leafs_deleter.deletedEntries
non_leaf_entries.extend(leafs_deleter.nonLeafEntries)
return # DelTree()
# Create LDAPObject instance
l = ldap.initialize('ldap://localhost:1390')
# Try a bind to provoke failure if protocol version is not supported
l.simple_bind_s('cn=Directory Manager,dc=IMC,dc=org','controller')
# Delete all entries *below* the entry dc=Delete,dc=IMC,dc=org
DelTree(l,'dc=Delete,dc=IMC,dc=org',ldap.SCOPE_ONELEVEL)
python-ldap-2.4.10/Demo/Lib/ldap/async/ldifwriter.py 0000644 0000764 0000144 00000001761 10411503653 023001 0 ustar michael users 0000000 0000000 """
ldifwriter - using ldap.async module for output of LDIF stream
of LDAP search results
Written by Michael Stroeder
$Id: ldifwriter.py,v 1.4 2006/03/26 12:23:07 stroeder Exp $
This example translates the naming context of data read from
input, sanitizes some attributes, maps/removes object classes,
maps/removes attributes., etc. It's far from being complete though.
Python compability note:
Tested on Python 2.0+, should run on Python 1.5.x.
"""
import sys,ldap,ldap.async
s = ldap.async.LDIFWriter(
ldap.initialize('ldap://localhost:1390'),
sys.stdout
)
s.startSearch(
'dc=stroeder,dc=de',
ldap.SCOPE_SUBTREE,
'(objectClass=*)',
)
try:
partial = s.processResults()
except ldap.SIZELIMIT_EXCEEDED:
sys.stderr.write('Warning: Server-side size limit exceeded.\n')
else:
if partial:
sys.stderr.write('Warning: Only partial results received.\n')
sys.stderr.write(
'%d results received.\n' % (
s.endResultBreak-s.beginResultsDropped
)
)
python-ldap-2.4.10/Demo/Lib/ldif/ 0000755 0000764 0000144 00000000000 11764172736 017150 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Demo/Lib/ldif/.cvsignore 0000644 0000764 0000144 00000000025 07507672213 021140 0 ustar michael users 0000000 0000000 *.pyc
*.pyo
*.bck
*~
python-ldap-2.4.10/Demo/Lib/ldif/ldifcopy.py 0000644 0000764 0000144 00000001242 07405752201 021316 0 ustar michael users 0000000 0000000 """
ldifcopy - reads LDIF from stdin, retrieve values by URL and
write resulting LDIF to stdout
Written by Michael Stroeder
$Id: ldifcopy.py,v 1.2 2001/12/12 22:04:49 stroeder Exp $
This example translates the naming context of data read from
input, sanitizes some attributes, maps/removes object classes,
maps/removes attributes., etc. It's far from being complete though.
Python compability note:
Tested on Python 2.0+, should run on Python 1.5.x.
"""
import sys,ldif
infile = sys.stdin
outfile = sys.stdout
ldif_collector = ldif.LDIFCopy(
infile,
outfile,
process_url_schemes=['file','ftp','http']
)
ldif_collector.parse()
python-ldap-2.4.10/Demo/Lib/ldapurl/ 0000755 0000764 0000144 00000000000 11764172736 017675 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Demo/Lib/ldapurl/urlsearch.py 0000644 0000764 0000144 00000001442 07617316074 022235 0 ustar michael users 0000000 0000000 """
Do a search with the LDAP URL specified at command-line.
No output of LDAP data is produced except trace output.
"""
import sys,getpass,ldap,ldapurl
try:
ldapUrl = ldapurl.LDAPUrl(ldapUrl=sys.argv[1])
except IndexError:
print 'Usage: %s [LDAP URL]' % (sys.argv[0])
sys.exit(1)
for a in [
'urlscheme','hostport','dn','attrs','scope',
'filterstr','extensions','who','cred'
]:
print a,repr(getattr(ldapUrl,a))
l = ldap.initialize(ldapUrl.initializeUrl(),trace_level=1)
if ldapUrl.who!=None:
if ldapUrl.cred!=None:
cred=ldapUrl.cred
else:
print 'Enter password for simple bind with',repr(ldapUrl.who)
cred=getpass.getpass()
l.simple_bind_s(ldapUrl.who,cred)
res = l.search_s(ldapUrl.dn,ldapUrl.scope,ldapUrl.filterstr,ldapUrl.attrs)
print len(res),'search results'
python-ldap-2.4.10/Demo/Lib/ldapurl/.cvsignore 0000644 0000764 0000144 00000000025 07617316730 021666 0 ustar michael users 0000000 0000000 *.pyc
*.pyo
*.bck
*~
python-ldap-2.4.10/Modules/ 0000755 0000764 0000144 00000000000 11764172736 016250 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Modules/LDAPObject.h 0000644 0000764 0000144 00000003121 11172071675 020256 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: LDAPObject.h,v 1.10 2009/04/17 12:19:09 stroeder Exp $ */
#ifndef __h_LDAPObject
#define __h_LDAPObject
#include "common.h"
#include "lber.h"
#include "ldap.h"
#if LDAP_API_VERSION < 2000
#error Current python-ldap requires OpenLDAP 2.x
#endif
#if PYTHON_API_VERSION < 1007
typedef PyObject* _threadstate;
#else
typedef PyThreadState* _threadstate;
#endif
typedef struct {
PyObject_HEAD
LDAP* ldap;
_threadstate _save; /* for thread saving on referrals */
int valid;
} LDAPObject;
extern PyTypeObject LDAP_Type;
#define LDAPObject_Check(v) ((v)->ob_type == &LDAP_Type)
extern LDAPObject *newLDAPObject( LDAP* );
/* macros to allow thread saving in the context of an LDAP connection */
#define LDAP_BEGIN_ALLOW_THREADS( l ) \
{ \
LDAPObject *lo = (l); \
if (lo->_save != NULL) \
Py_FatalError( "saving thread twice?" ); \
lo->_save = PyEval_SaveThread(); \
}
#define LDAP_END_ALLOW_THREADS( l ) \
{ \
LDAPObject *lo = (l); \
_threadstate _save = lo->_save; \
lo->_save = NULL; \
PyEval_RestoreThread( _save ); \
}
#endif /* __h_LDAPObject */
python-ldap-2.4.10/Modules/ldapcontrol.c 0000644 0000764 0000144 00000020567 11660514462 020736 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: ldapcontrol.c,v 1.20 2011/10/26 18:38:06 stroeder Exp $ */
#include "common.h"
#include "LDAPObject.h"
#include "ldapcontrol.h"
#include "berval.h"
#include "errors.h"
#include "lber.h"
/* Prints to stdout the contents of an array of LDAPControl objects */
/* XXX: This is a debugging tool, and the printf generates some warnings
* about pointer types. I left it here in case something breaks and we
* need to inspect an LDAPControl structure.
static void
LDAPControl_DumpList( LDAPControl** lcs ) {
LDAPControl** lcp;
LDAPControl* lc;
for ( lcp = lcs; *lcp; lcp++ ) {
lc = *lcp;
printf("OID: %s\nCriticality: %d\nBER length: %d\nBER value: %x\n",
lc->ldctl_oid, lc->ldctl_iscritical, lc->ldctl_value.bv_len,
lc->ldctl_value.bv_val);
}
} */
/* Free a single LDAPControl object created by Tuple_to_LDAPControl */
static void
LDAPControl_DEL( LDAPControl* lc )
{
if (lc == NULL)
return;
if (lc->ldctl_oid)
PyMem_DEL(lc->ldctl_oid);
PyMem_DEL(lc);
}
/* Free an array of LDAPControl objects created by LDAPControls_from_object */
void
LDAPControl_List_DEL( LDAPControl** lcs )
{
LDAPControl** lcp;
if (lcs == NULL)
return;
for ( lcp = lcs; *lcp; lcp++ )
LDAPControl_DEL( *lcp );
PyMem_DEL( lcs );
}
/* Takes a tuple of the form:
* (OID: string, Criticality: int/boolean, Value: string/None)
* and converts it into an LDAPControl structure.
*
* The Value string should represent an ASN.1 encoded structure.
*/
static LDAPControl*
Tuple_to_LDAPControl( PyObject* tup )
{
char *oid;
char iscritical;
struct berval berbytes;
PyObject *bytes;
LDAPControl *lc = NULL;
Py_ssize_t len;
if (!PyTuple_Check(tup)) {
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
"expected a tuple", tup));
return NULL;
}
if (!PyArg_ParseTuple( tup, "sbO", &oid, &iscritical, &bytes ))
return NULL;
lc = PyMem_NEW(LDAPControl, 1);
if (lc == NULL) {
PyErr_NoMemory();
return NULL;
}
lc->ldctl_iscritical = iscritical;
len = strlen(oid);
lc->ldctl_oid = PyMem_NEW(char, len + 1);
if (lc->ldctl_oid == NULL) {
PyErr_NoMemory();
LDAPControl_DEL(lc);
return NULL;
}
memcpy(lc->ldctl_oid, oid, len + 1);
/* The berval can either be None or a String */
if (PyNone_Check(bytes)) {
berbytes.bv_len = 0;
berbytes.bv_val = NULL;
}
else if (PyString_Check(bytes)) {
berbytes.bv_len = PyString_Size(bytes);
berbytes.bv_val = PyString_AsString(bytes);
}
else {
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
"expected a string", bytes));
LDAPControl_DEL(lc);
return NULL;
}
lc->ldctl_value = berbytes;
return lc;
}
/* Convert a list of tuples (of a format acceptable to the Tuple_to_LDAPControl
* function) into an array of LDAPControl objects. */
int
LDAPControls_from_object(PyObject* list, LDAPControl ***controls_ret)
{
Py_ssize_t len, i;
LDAPControl** ldcs;
LDAPControl* ldc;
PyObject* item;
if (!PySequence_Check(list)) {
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
"expected a list", list));
return 0;
}
len = PySequence_Length(list);
ldcs = PyMem_NEW(LDAPControl*, len + 1);
if (ldcs == NULL) {
PyErr_NoMemory();
return 0;
}
for (i = 0; i < len; i++) {
item = PySequence_GetItem(list, i);
if (item == NULL) {
PyMem_DEL(ldcs);
return 0;
}
ldc = Tuple_to_LDAPControl(item);
if (ldc == NULL) {
Py_DECREF(item);
PyMem_DEL(ldcs);
return 0;
}
ldcs[i] = ldc;
Py_DECREF(item);
}
ldcs[len] = NULL;
*controls_ret = ldcs;
return 1;
}
PyObject*
LDAPControls_to_List(LDAPControl **ldcs)
{
PyObject *res = 0, *pyctrl;
LDAPControl **tmp = ldcs;
Py_ssize_t num_ctrls = 0, i;
if (tmp)
while (*tmp++) num_ctrls++;
if (!(res = PyList_New(num_ctrls)))
goto endlbl;
for (i = 0; i < num_ctrls; i++) {
if (!(pyctrl = Py_BuildValue("sbO&", ldcs[i]->ldctl_oid,
ldcs[i]->ldctl_iscritical,
LDAPberval_to_object,
&ldcs[i]->ldctl_value))) {
goto endlbl;
}
PyList_SET_ITEM(res, i, pyctrl);
}
Py_INCREF(res);
endlbl:
Py_XDECREF(res);
return res;
}
/* --------------- en-/decoders ------------- */
/* Matched Values, aka, Values Return Filter */
static PyObject*
encode_rfc3876(PyObject *self, PyObject *args)
{
PyObject *res = 0;
int err;
BerElement *vrber = 0;
char *vrFilter;
struct berval *ctrl_val;
if (!PyArg_ParseTuple(args, "s:encode_valuesreturnfilter_control", &vrFilter)) {
goto endlbl;
}
if (!(vrber = ber_alloc_t(LBER_USE_DER))) {
LDAPerr(LDAP_NO_MEMORY);
goto endlbl;
}
err = ldap_put_vrFilter(vrber, vrFilter);
if (err == -1) {
LDAPerr(LDAP_FILTER_ERROR);
goto endlbl;
}
err = ber_flatten(vrber, &ctrl_val);
if (err == -1) {
LDAPerr(LDAP_NO_MEMORY);
goto endlbl;
}
res = LDAPberval_to_object(ctrl_val);
endlbl:
if (vrber)
ber_free(vrber, 1);
return res;
}
static PyObject*
encode_rfc2696(PyObject *self, PyObject *args)
{
PyObject *res = 0;
BerElement *ber = 0;
struct berval cookie, *ctrl_val;
Py_ssize_t cookie_len;
unsigned long size;
ber_tag_t tag;
if (!PyArg_ParseTuple(args, "is#:encode_page_control", &size,
&cookie.bv_val, &cookie_len)) {
goto endlbl;
}
cookie.bv_len = (ber_len_t) cookie_len;
if (!(ber = ber_alloc_t(LBER_USE_DER))) {
LDAPerr(LDAP_NO_MEMORY);
goto endlbl;
}
tag = ber_printf(ber, "{i", size);
if (tag == LBER_ERROR) {
LDAPerr(LDAP_ENCODING_ERROR);
goto endlbl;
}
if (!cookie.bv_len)
tag = ber_printf(ber, "o", "", 0);
else
tag = ber_printf(ber, "O", &cookie);
if (tag == LBER_ERROR) {
LDAPerr(LDAP_ENCODING_ERROR);
goto endlbl;
}
tag = ber_printf(ber, /*{ */ "N}");
if (tag == LBER_ERROR) {
LDAPerr(LDAP_ENCODING_ERROR);
goto endlbl;
}
if (-1 == ber_flatten(ber, &ctrl_val)) {
LDAPerr(LDAP_NO_MEMORY);
goto endlbl;
}
res = LDAPberval_to_object(ctrl_val);
endlbl:
if (ber)
ber_free(ber, 1);
return res;
}
static PyObject*
decode_rfc2696(PyObject *self, PyObject *args)
{
PyObject *res = 0;
BerElement *ber = 0;
struct berval ldctl_value;
ber_tag_t tag;
struct berval *cookiep;
unsigned long count;
Py_ssize_t ldctl_value_len;
if (!PyArg_ParseTuple(args, "s#:decode_page_control",
&ldctl_value.bv_val, &ldctl_value_len)) {
goto endlbl;
}
ldctl_value.bv_len = (ber_len_t) ldctl_value_len;
if (!(ber = ber_init(&ldctl_value))) {
LDAPerr(LDAP_NO_MEMORY);
goto endlbl;
}
tag = ber_scanf(ber, "{iO", &count, &cookiep);
if (tag == LBER_ERROR) {
LDAPerr(LDAP_DECODING_ERROR);
goto endlbl;
}
res = Py_BuildValue("(lO&)", count, LDAPberval_to_object, cookiep);
endlbl:
if (ber)
ber_free(ber, 1);
return res;
}
static PyObject*
encode_assertion_control(PyObject *self, PyObject *args)
{
int err;
PyObject *res = 0;
char *assertion_filterstr;
struct berval ctrl_val;
LDAP *ld = NULL;
if (!PyArg_ParseTuple(args, "s:encode_assertion_control",
&assertion_filterstr)) {
goto endlbl;
}
err = ldap_create(&ld);
if (err != LDAP_SUCCESS)
return LDAPerror(ld, "ldap_create");
err = ldap_create_assertion_control_value(ld,assertion_filterstr,&ctrl_val);
if (err != LDAP_SUCCESS)
return LDAPerror(ld, "ldap_create_assertion_control_value");
res = LDAPberval_to_object(&ctrl_val);
endlbl:
return res;
}
static PyMethodDef methods[] = {
{"encode_page_control", encode_rfc2696, METH_VARARGS },
{"decode_page_control", decode_rfc2696, METH_VARARGS },
{"encode_valuesreturnfilter_control", encode_rfc3876, METH_VARARGS },
{"encode_assertion_control", encode_assertion_control, METH_VARARGS },
{ NULL, NULL }
};
void
LDAPinit_control(PyObject *d)
{
LDAPadd_methods(d, methods);
}
python-ldap-2.4.10/Modules/ldapmodule.c 0000644 0000764 0000144 00000001714 11172071675 020536 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: ldapmodule.c,v 1.9 2009/04/17 12:19:09 stroeder Exp $ */
#include "common.h"
#include "version.h"
#include "constants.h"
#include "errors.h"
#include "functions.h"
#include "schema.h"
#include "ldapcontrol.h"
#include "LDAPObject.h"
DL_EXPORT(void) init_ldap(void);
/* dummy module methods */
static PyMethodDef methods[] = {
{ NULL, NULL }
};
/* module initialisation */
DL_EXPORT(void)
init_ldap()
{
PyObject *m, *d;
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
LDAP_Type.ob_type = &PyType_Type;
#endif
/* Create the module and add the functions */
m = Py_InitModule("_ldap", methods);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
LDAPinit_version(d);
LDAPinit_constants(d);
LDAPinit_errors(d);
LDAPinit_functions(d);
LDAPinit_schema(d);
LDAPinit_control(d);
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module _ldap");
}
python-ldap-2.4.10/Modules/common.c 0000644 0000764 0000144 00000000764 11172071675 017704 0 ustar michael users 0000000 0000000 /* Miscellaneous common routines
* See http://www.python-ldap.org/ for details.
* $Id: common.c,v 1.3 2009/04/17 12:19:09 stroeder Exp $ */
#include "common.h"
/* dynamically add the methods into the module dictionary d */
void
LDAPadd_methods( PyObject* d, PyMethodDef* methods )
{
PyMethodDef *meth;
for( meth = methods; meth->ml_meth; meth++ ) {
PyObject *f = PyCFunction_New( meth, NULL );
PyDict_SetItemString( d, meth->ml_name, f );
Py_DECREF(f);
}
}
python-ldap-2.4.10/Modules/.cvsignore 0000644 0000764 0000144 00000000011 07507671633 020240 0 ustar michael users 0000000 0000000 *.bck
*~
python-ldap-2.4.10/Modules/ldapcontrol.h 0000644 0000764 0000144 00000000650 11235744576 020743 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: ldapcontrol.h,v 1.6 2009/08/04 05:39:10 leonard Exp $ */
#ifndef __h_ldapcontrol
#define __h_ldapcontrol
#include "common.h"
#include "ldap.h"
void LDAPinit_control(PyObject *d);
void LDAPControl_List_DEL( LDAPControl** );
int LDAPControls_from_object(PyObject *, LDAPControl ***);
PyObject* LDAPControls_to_List(LDAPControl **ldcs);
#endif /* __h_ldapcontrol */
python-ldap-2.4.10/Modules/version.c 0000644 0000764 0000144 00000000661 11172071675 020075 0 ustar michael users 0000000 0000000 /* Set release version
* See http://www.python-ldap.org/ for details.
* $Id: version.c,v 1.4 2009/04/17 12:19:09 stroeder Exp $ */
#include "common.h"
#define _STR(x) #x
#define STR(x) _STR(x)
static char version_str[] = STR(LDAPMODULE_VERSION);
void
LDAPinit_version( PyObject* d )
{
PyObject *version;
version = PyString_FromString(version_str);
PyDict_SetItemString( d, "__version__", version );
Py_DECREF(version);
}
python-ldap-2.4.10/Modules/schema.c 0000644 0000764 0000144 00000020276 11172071675 017654 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: schema.c,v 1.8 2009/04/17 12:19:09 stroeder Exp $ */
#include "common.h"
#include "schema.h"
#include "ldap_schema.h"
/*
This utility function takes a null delimited C array of (null
delimited) C strings, creates its python equivalent and returns a
new reference to it. If the array is empty or the pointer to it is
NULL, an empty python array is returned.
*/
PyObject* c_string_array_to_python(char **string_array)
{
Py_ssize_t count = 0;
char **s;
PyObject *py_list;
if (string_array) {
for (s=string_array; *s != 0; s++) count++;
py_list = PyList_New(count);
count = 0;
for (s=string_array; *s != 0; s++){
PyList_SetItem(py_list, count, PyString_FromString(*s));
count++;
}
} else py_list=PyList_New(0);
return py_list;
}
/*
This function returns a list of tuples. The first entry of each
tuple is a string (lsei_name), and the second is a lists built from
lsei_values.
Probably the C data structure is modeled along the lines of a
mapping "lsei_name -> (list of lsei_values)". However, there seems
to be no guarantee that a lsei_name is unique, so I dare not use a
python mapping for this beast...
*/
PyObject* schema_extension_to_python(LDAPSchemaExtensionItem **extensions)
{
Py_ssize_t count = 0;
LDAPSchemaExtensionItem **e;
PyObject *py_list, *item_tuple;
if (extensions) {
for (e = extensions; *e !=0; e++) count++;
py_list = PyList_New(count);
count = 0;
for (e = extensions; *e !=0; e++) {
item_tuple = PyTuple_New(2);
PyTuple_SetItem(item_tuple, 0,
PyString_FromString((*e)->lsei_name));
PyTuple_SetItem(item_tuple, 1,
c_string_array_to_python((*e)->lsei_values));
PyList_SetItem(py_list, count, item_tuple);
count++;
}
}
else py_list=PyList_New(0);
return py_list;
}
/*
The following four functions do the boring job: they take a python
string, feed it into the respective parser functions provided by
openldap, and build a python list from the data structure returned
by the C function.
*/
static char doc_ldap_str2objectclass[] =
"";
static PyObject*
l_ldap_str2objectclass(PyObject* self, PyObject *args)
{
int ret=0, flag = LDAP_SCHEMA_ALLOW_NONE;
char *oc_string;
const char *errp;
LDAPObjectClass *o;
PyObject *oc_names, *oc_sup_oids, *oc_at_oids_must,
*oc_at_oids_may, *py_ret;
if (!PyArg_ParseTuple(args, "si", &oc_string, &flag))
return NULL;
o = ldap_str2objectclass( oc_string, &ret, &errp, flag);
if (ret) {
py_ret = PyInt_FromLong(ret);
return py_ret;
}
oc_sup_oids = c_string_array_to_python(o->oc_sup_oids);
oc_names = c_string_array_to_python(o->oc_names);
oc_at_oids_must = c_string_array_to_python(o->oc_at_oids_must);
oc_at_oids_may = c_string_array_to_python(o->oc_at_oids_may);
py_ret = PyList_New(9);
PyList_SetItem(py_ret, 0, PyString_FromString(o->oc_oid));
PyList_SetItem(py_ret, 1, oc_names);
if (o->oc_desc) {
PyList_SetItem(py_ret, 2, PyString_FromString(o->oc_desc));
} else {
PyList_SetItem(py_ret, 2, PyString_FromString(""));
}
PyList_SetItem(py_ret, 3, PyInt_FromLong(o->oc_obsolete));
PyList_SetItem(py_ret, 4, oc_sup_oids);
PyList_SetItem(py_ret, 5, PyInt_FromLong(o->oc_kind));
PyList_SetItem(py_ret, 6, oc_at_oids_must);
PyList_SetItem(py_ret, 7, oc_at_oids_may);
PyList_SetItem(py_ret, 8,
schema_extension_to_python(o->oc_extensions));
ldap_objectclass_free(o);
return py_ret;
}
static char doc_ldap_str2attributetype[] =
"";
static PyObject*
l_ldap_str2attributetype(PyObject* self, PyObject *args)
{
int ret=0, flag = LDAP_SCHEMA_ALLOW_NONE;
char *at_string;
const char *errp;
LDAPAttributeType *a;
PyObject *py_ret;
PyObject *at_names;
if (!PyArg_ParseTuple(args, "si", &at_string,&flag))
return NULL;
a = ldap_str2attributetype( at_string, &ret, &errp, flag);
if (ret) {
py_ret = PyInt_FromLong(ret);
return py_ret;
}
py_ret = PyList_New(15);
PyList_SetItem(py_ret, 0, PyString_FromString(a->at_oid));
at_names = c_string_array_to_python(a->at_names);
PyList_SetItem(py_ret, 1, at_names);
if (a->at_desc) {
PyList_SetItem(py_ret, 2, PyString_FromString(a->at_desc));
} else {
PyList_SetItem(py_ret, 2, PyString_FromString(""));
}
PyList_SetItem(py_ret, 3, PyInt_FromLong(a->at_obsolete));
if (a->at_sup_oid) {
PyList_SetItem(py_ret, 4, PyString_FromString(a->at_sup_oid));
} else {
PyList_SetItem(py_ret, 4, PyString_FromString(""));
}
if (a->at_equality_oid) {
PyList_SetItem(py_ret, 5, PyString_FromString(a->at_equality_oid));
} else {
PyList_SetItem(py_ret, 5, PyString_FromString(""));
}
if (a->at_ordering_oid) {
PyList_SetItem(py_ret, 6, PyString_FromString(a->at_ordering_oid));
} else {
PyList_SetItem(py_ret, 6, PyString_FromString(""));
}
if (a->at_substr_oid) {
PyList_SetItem(py_ret, 7, PyString_FromString(a->at_substr_oid));
} else {
PyList_SetItem(py_ret, 7, PyString_FromString(""));
}
if (a->at_syntax_oid) {
PyList_SetItem(py_ret, 8, PyString_FromString(a->at_syntax_oid));
} else {
PyList_SetItem(py_ret, 8, PyString_FromString(""));
}
PyList_SetItem(py_ret, 9, PyInt_FromLong(a->at_syntax_len));
PyList_SetItem(py_ret,10, PyInt_FromLong(a->at_single_value));
PyList_SetItem(py_ret,11, PyInt_FromLong(a->at_collective));
PyList_SetItem(py_ret,12, PyInt_FromLong(a->at_no_user_mod));
PyList_SetItem(py_ret,13, PyInt_FromLong(a->at_usage));
PyList_SetItem(py_ret, 14,
schema_extension_to_python(a->at_extensions));
ldap_attributetype_free(a);
return py_ret;
}
static char doc_ldap_str2syntax[] =
"";
static PyObject*
l_ldap_str2syntax(PyObject* self, PyObject *args)
{
LDAPSyntax *s;
int ret=0, flag = LDAP_SCHEMA_ALLOW_NONE;
const char *errp;
char *syn_string;
PyObject *py_ret, *syn_names;
if (!PyArg_ParseTuple(args, "si", &syn_string,&flag))
return NULL;
s = ldap_str2syntax(syn_string, &ret, &errp, flag);
if (ret) {
py_ret = PyInt_FromLong(ret);
return py_ret;
}
py_ret = PyList_New(4);
PyList_SetItem(py_ret, 0, PyString_FromString(s->syn_oid));
syn_names = c_string_array_to_python(s->syn_names);
PyList_SetItem(py_ret, 1, syn_names);
if (s->syn_desc) {
PyList_SetItem(py_ret, 2, PyString_FromString(s->syn_desc));
} else {
PyList_SetItem(py_ret, 2, PyString_FromString(""));
}
PyList_SetItem(py_ret, 3,
schema_extension_to_python(s->syn_extensions));
ldap_syntax_free(s);
return py_ret;
}
static char doc_ldap_str2matchingrule[] =
"";
static PyObject*
l_ldap_str2matchingrule(PyObject* self, PyObject *args)
{
LDAPMatchingRule *m;
int ret=0, flag = LDAP_SCHEMA_ALLOW_NONE;
const char *errp;
char *mr_string;
PyObject *py_ret, *mr_names;
if (!PyArg_ParseTuple(args, "si", &mr_string,&flag))
return NULL;
m = ldap_str2matchingrule(mr_string, &ret, &errp, flag);
if (ret) {
py_ret = PyInt_FromLong(ret);
return py_ret;
}
py_ret = PyList_New(6);
PyList_SetItem(py_ret, 0, PyString_FromString(m->mr_oid));
mr_names = c_string_array_to_python(m->mr_names);
PyList_SetItem(py_ret, 1, mr_names);
if (m->mr_desc) {
PyList_SetItem(py_ret, 2, PyString_FromString(m->mr_desc));
} else {
PyList_SetItem(py_ret, 2, PyString_FromString(""));
}
PyList_SetItem(py_ret, 3, PyInt_FromLong(m->mr_obsolete));
if (m->mr_syntax_oid) {
PyList_SetItem(py_ret, 4, PyString_FromString(m->mr_syntax_oid));
} else {
PyList_SetItem(py_ret, 4, PyString_FromString(""));
}
PyList_SetItem(py_ret, 5,
schema_extension_to_python(m->mr_extensions));
ldap_matchingrule_free(m);
return py_ret;
}
/* methods */
static PyMethodDef methods[] = {
{ "str2objectclass", (PyCFunction)l_ldap_str2objectclass, METH_VARARGS,
doc_ldap_str2objectclass },
{ "str2attributetype", (PyCFunction)l_ldap_str2attributetype,
METH_VARARGS, doc_ldap_str2attributetype },
{ "str2syntax", (PyCFunction)l_ldap_str2syntax,
METH_VARARGS, doc_ldap_str2syntax },
{ "str2matchingrule", (PyCFunction)l_ldap_str2matchingrule,
METH_VARARGS, doc_ldap_str2matchingrule },
{ NULL, NULL }
};
void
LDAPinit_schema( PyObject* d ) {
LDAPadd_methods( d, methods );
}
python-ldap-2.4.10/Modules/schema.h 0000644 0000764 0000144 00000000363 11172071675 017654 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: schema.h,v 1.5 2009/04/17 12:19:09 stroeder Exp $ */
#ifndef __h_schema_
#define __h_schema_
#include "common.h"
extern void LDAPinit_schema( PyObject* );
#endif /* __h_schema_ */
python-ldap-2.4.10/Modules/constants.c 0000644 0000764 0000144 00000022076 11660514462 020426 0 ustar michael users 0000000 0000000 /* constants defined for LDAP
* See http://www.python-ldap.org/ for details.
* $Id: constants.c,v 1.55 2011/10/14 11:47:08 stroeder Exp $ */
#include "common.h"
#include "constants.h"
#include "lber.h"
#include "ldap.h"
static PyObject* reverse;
static PyObject* forward;
/* convert an result integer into a Python string */
PyObject*
LDAPconstant( int val ) {
PyObject *i = PyInt_FromLong( val );
PyObject *s = PyObject_GetItem( reverse, i );
if (s == NULL) {
PyErr_Clear();
return i;
}
Py_DECREF(i);
return s;
}
/* initialise the module constants */
void
LDAPinit_constants( PyObject* d )
{
PyObject *zero, *author,*obj;
reverse = PyDict_New();
forward = PyDict_New();
PyDict_SetItemString( d, "_reverse", reverse );
PyDict_SetItemString( d, "_forward", forward );
#define add_int(d, name) \
{ \
PyObject *i = PyInt_FromLong(LDAP_##name); \
PyDict_SetItemString( d, #name, i ); \
Py_DECREF(i); \
}
/* simple constants */
add_int(d,API_VERSION);
add_int(d,VENDOR_VERSION);
add_int(d,PORT);
add_int(d,VERSION1);
add_int(d,VERSION2);
add_int(d,VERSION3);
add_int(d,VERSION_MIN);
add_int(d,VERSION);
add_int(d,VERSION_MAX);
add_int(d,TAG_MESSAGE);
add_int(d,TAG_MSGID);
add_int(d,REQ_BIND);
add_int(d,REQ_UNBIND);
add_int(d,REQ_SEARCH);
add_int(d,REQ_MODIFY);
add_int(d,REQ_ADD);
add_int(d,REQ_DELETE);
add_int(d,REQ_MODRDN);
add_int(d,REQ_COMPARE);
add_int(d,REQ_ABANDON);
add_int(d,TAG_LDAPDN);
add_int(d,TAG_LDAPCRED);
add_int(d,TAG_CONTROLS);
add_int(d,TAG_REFERRAL);
add_int(d,REQ_EXTENDED);
#if LDAP_API_VERSION >= 2004
add_int(d,TAG_NEWSUPERIOR);
add_int(d,TAG_EXOP_REQ_OID);
add_int(d,TAG_EXOP_REQ_VALUE);
add_int(d,TAG_EXOP_RES_OID);
add_int(d,TAG_EXOP_RES_VALUE);
#ifdef HAVE_SASL
add_int(d,TAG_SASL_RES_CREDS);
#endif
#endif
add_int(d,SASL_AUTOMATIC);
add_int(d,SASL_INTERACTIVE);
add_int(d,SASL_QUIET);
/* reversibles */
zero = PyInt_FromLong( 0 );
PyDict_SetItem( reverse, zero, Py_None );
Py_DECREF( zero );
add_int(d,RES_BIND);
add_int(d,RES_SEARCH_ENTRY);
add_int(d,RES_SEARCH_RESULT);
add_int(d,RES_MODIFY);
add_int(d,RES_ADD);
add_int(d,RES_DELETE);
add_int(d,RES_MODRDN);
add_int(d,RES_COMPARE);
add_int(d,RES_ANY);
add_int(d,RES_SEARCH_REFERENCE);
add_int(d,RES_EXTENDED);
add_int(d,RES_UNSOLICITED);
add_int(d,RES_INTERMEDIATE);
/* non-reversibles */
add_int(d,AUTH_NONE);
add_int(d,AUTH_SIMPLE);
add_int(d,SCOPE_BASE);
add_int(d,SCOPE_ONELEVEL);
add_int(d,SCOPE_SUBTREE);
add_int(d,MOD_ADD);
add_int(d,MOD_DELETE);
add_int(d,MOD_REPLACE);
add_int(d,MOD_INCREMENT);
add_int(d,MOD_BVALUES);
add_int(d,MSG_ONE);
add_int(d,MSG_ALL);
add_int(d,MSG_RECEIVED);
/* (errors.c contains the error constants) */
add_int(d,DEREF_NEVER);
add_int(d,DEREF_SEARCHING);
add_int(d,DEREF_FINDING);
add_int(d,DEREF_ALWAYS);
add_int(d,NO_LIMIT);
add_int(d,OPT_API_INFO);
add_int(d,OPT_DEREF);
add_int(d,OPT_SIZELIMIT);
add_int(d,OPT_TIMELIMIT);
#ifdef LDAP_OPT_REFERRALS
add_int(d,OPT_REFERRALS);
#endif
add_int(d,OPT_ERROR_NUMBER);
add_int(d,OPT_RESTART);
add_int(d,OPT_PROTOCOL_VERSION);
add_int(d,OPT_SERVER_CONTROLS);
add_int(d,OPT_CLIENT_CONTROLS);
add_int(d,OPT_API_FEATURE_INFO);
add_int(d,OPT_HOST_NAME);
add_int(d,OPT_DIAGNOSTIC_MESSAGE);
add_int(d,OPT_ERROR_STRING);
add_int(d,OPT_MATCHED_DN);
add_int(d,OPT_DEBUG_LEVEL);
add_int(d,OPT_TIMEOUT);
add_int(d,OPT_REFHOPLIMIT);
add_int(d,OPT_NETWORK_TIMEOUT);
add_int(d,OPT_URI);
#ifdef LDAP_OPT_DEFBASE
add_int(d,OPT_DEFBASE);
#endif
#ifdef HAVE_TLS
add_int(d,OPT_X_TLS);
#ifdef LDAP_OPT_X_TLS_NEWCTX
add_int(d,OPT_X_TLS_CTX);
#endif
add_int(d,OPT_X_TLS_CACERTFILE);
add_int(d,OPT_X_TLS_CACERTDIR);
add_int(d,OPT_X_TLS_CERTFILE);
add_int(d,OPT_X_TLS_KEYFILE);
add_int(d,OPT_X_TLS_REQUIRE_CERT);
add_int(d,OPT_X_TLS_CIPHER_SUITE);
add_int(d,OPT_X_TLS_RANDOM_FILE);
add_int(d,OPT_X_TLS_DHFILE);
add_int(d,OPT_X_TLS_NEVER);
add_int(d,OPT_X_TLS_HARD);
add_int(d,OPT_X_TLS_DEMAND);
add_int(d,OPT_X_TLS_ALLOW);
add_int(d,OPT_X_TLS_TRY);
#ifdef LDAP_OPT_X_TLS_CRLCHECK
/* only available if OpenSSL supports it => might cause backward compability problems */
add_int(d,OPT_X_TLS_CRLCHECK);
#ifdef LDAP_OPT_X_TLS_CRLFILE
add_int(d,OPT_X_TLS_CRLFILE);
#endif
add_int(d,OPT_X_TLS_CRL_NONE);
add_int(d,OPT_X_TLS_CRL_PEER);
add_int(d,OPT_X_TLS_CRL_ALL);
#endif
#ifdef LDAP_OPT_X_TLS_NEWCTX
add_int(d,OPT_X_TLS_NEWCTX);
#endif
#ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
add_int(d,OPT_X_TLS_PROTOCOL_MIN);
#endif
#ifdef LDAP_OPT_X_TLS_PACKAGE
add_int(d,OPT_X_TLS_PACKAGE);
#endif
#endif
add_int(d,OPT_X_SASL_MECH);
add_int(d,OPT_X_SASL_REALM);
add_int(d,OPT_X_SASL_AUTHCID);
add_int(d,OPT_X_SASL_AUTHZID);
add_int(d,OPT_X_SASL_SSF);
add_int(d,OPT_X_SASL_SSF_EXTERNAL);
add_int(d,OPT_X_SASL_SECPROPS);
add_int(d,OPT_X_SASL_SSF_MIN);
add_int(d,OPT_X_SASL_SSF_MAX);
#ifdef LDAP_OPT_X_SASL_NOCANON
add_int(d,OPT_X_SASL_NOCANON);
#endif
#ifdef LDAP_OPT_X_SASL_USERNAME
add_int(d,OPT_X_SASL_USERNAME);
#endif
#ifdef LDAP_OPT_CONNECT_ASYNC
add_int(d,OPT_CONNECT_ASYNC);
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_IDLE
add_int(d,OPT_X_KEEPALIVE_IDLE);
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_PROBES
add_int(d,OPT_X_KEEPALIVE_PROBES);
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
add_int(d,OPT_X_KEEPALIVE_INTERVAL);
#endif
add_int(d,DN_FORMAT_LDAP);
add_int(d,DN_FORMAT_LDAPV3);
add_int(d,DN_FORMAT_LDAPV2);
add_int(d,DN_FORMAT_DCE);
add_int(d,DN_FORMAT_UFN);
add_int(d,DN_FORMAT_AD_CANONICAL);
/* add_int(d,DN_FORMAT_LBER); */ /* "for testing only" */
add_int(d,DN_FORMAT_MASK);
add_int(d,DN_PRETTY);
add_int(d,DN_SKIP);
add_int(d,DN_P_NOLEADTRAILSPACES);
add_int(d,DN_P_NOSPACEAFTERRDN);
add_int(d,DN_PEDANTIC);
add_int(d,AVA_NULL);
add_int(d,AVA_STRING);
add_int(d,AVA_BINARY);
add_int(d,AVA_NONPRINTABLE);
/*add_int(d,OPT_ON);*/
obj = PyInt_FromLong(1);
PyDict_SetItemString( d, "OPT_ON", obj );
Py_DECREF(obj);
/*add_int(d,OPT_OFF);*/
obj = PyInt_FromLong(0);
PyDict_SetItemString( d, "OPT_OFF", obj );
Py_DECREF(obj);
add_int(d,OPT_SUCCESS);
/* XXX - these belong in errors.c */
add_int(d,URL_ERR_BADSCOPE);
add_int(d,URL_ERR_MEM);
/* author */
author = PyString_FromString("python-ldap Project");
PyDict_SetItemString(d, "__author__", author);
Py_DECREF(author);
/* add_int(d,LIBLDAP_R); */
#ifdef HAVE_LIBLDAP_R
obj = PyInt_FromLong(1);
#else
obj = PyInt_FromLong(0);
#endif
PyDict_SetItemString( d, "LIBLDAP_R", obj );
Py_DECREF(obj);
/* add_int(d,SASL); */
#ifdef HAVE_SASL
obj = PyInt_FromLong(1);
#else
obj = PyInt_FromLong(0);
#endif
PyDict_SetItemString( d, "SASL_AVAIL", obj );
Py_DECREF(obj);
/* add_int(d,TLS); */
#ifdef HAVE_TLS
obj = PyInt_FromLong(1);
#else
obj = PyInt_FromLong(0);
#endif
PyDict_SetItemString( d, "TLS_AVAIL", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_MANAGEDSAIT);
PyDict_SetItemString( d, "CONTROL_MANAGEDSAIT", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_PROXY_AUTHZ);
PyDict_SetItemString( d, "CONTROL_PROXY_AUTHZ", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_SUBENTRIES);
PyDict_SetItemString( d, "CONTROL_SUBENTRIES", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_VALUESRETURNFILTER);
PyDict_SetItemString( d, "CONTROL_VALUESRETURNFILTER", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_ASSERT);
PyDict_SetItemString( d, "CONTROL_ASSERT", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_PRE_READ);
PyDict_SetItemString( d, "CONTROL_PRE_READ", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_POST_READ);
PyDict_SetItemString( d, "CONTROL_POST_READ", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_SORTREQUEST);
PyDict_SetItemString( d, "CONTROL_SORTREQUEST", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_SORTRESPONSE);
PyDict_SetItemString( d, "CONTROL_SORTRESPONSE", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_PAGEDRESULTS);
PyDict_SetItemString( d, "CONTROL_PAGEDRESULTS", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_SYNC);
PyDict_SetItemString( d, "CONTROL_SYNC", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_SYNC_STATE);
PyDict_SetItemString( d, "CONTROL_SYNC_STATE", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_SYNC_DONE);
PyDict_SetItemString( d, "CONTROL_SYNC_DONE", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_SYNC_INFO);
PyDict_SetItemString( d, "SYNC_INFO", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_PASSWORDPOLICYREQUEST);
PyDict_SetItemString( d, "CONTROL_PASSWORDPOLICYREQUEST", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_PASSWORDPOLICYRESPONSE);
PyDict_SetItemString( d, "CONTROL_PASSWORDPOLICYRESPONSE", obj );
Py_DECREF(obj);
obj = PyString_FromString(LDAP_CONTROL_RELAX);
PyDict_SetItemString( d, "CONTROL_RELAX", obj );
Py_DECREF(obj);
}
python-ldap-2.4.10/Modules/functions.h 0000644 0000764 0000144 00000000477 11172071675 020432 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: functions.h,v 1.4 2009/04/17 12:19:09 stroeder Exp $ */
#ifndef __h_functions_
#define __h_functions_
/* $Id: functions.h,v 1.4 2009/04/17 12:19:09 stroeder Exp $ */
#include "common.h"
extern void LDAPinit_functions( PyObject* );
#endif /* __h_functions_ */
python-ldap-2.4.10/Modules/common.h 0000644 0000764 0000144 00000001432 11172071675 017702 0 ustar michael users 0000000 0000000 /* common utility macros
* See http://www.python-ldap.org/ for details.
* $Id: common.h,v 1.8 2009/04/17 12:19:09 stroeder Exp $ */
#ifndef __h_common
#define __h_common
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#if defined(MS_WINDOWS)
#include
#else /* unix */
#include
#include
#include
#endif
/* Backwards compability with Python prior 2.5 */
#if PY_VERSION_HEX < 0x02050000
typedef int Py_ssize_t;
#define PY_SSIZE_T_MAX INT_MAX
#define PY_SSIZE_T_MIN INT_MIN
#endif
#include
#define streq( a, b ) \
( (*(a)==*(b)) && 0==strcmp(a,b) )
void LDAPadd_methods( PyObject*d, PyMethodDef*methods );
#define PyNone_Check(o) ((o) == Py_None)
#endif /* __h_common_ */
python-ldap-2.4.10/Modules/message.h 0000644 0000764 0000144 00000000527 11530551500 020026 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: message.h,v 1.6 2011/02/21 21:04:00 stroeder Exp $ */
#ifndef __h_message
#define __h_message
#include "common.h"
#include "lber.h"
#include "ldap.h"
extern PyObject* LDAPmessage_to_python( LDAP*ld, LDAPMessage*m, int add_ctrls, int add_intermediates );
#endif /* __h_message_ */
python-ldap-2.4.10/Modules/berval.h 0000644 0000764 0000144 00000000655 11242133473 017664 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: berval.h,v 1.1 2009/08/17 01:49:47 leonard Exp $ */
#ifndef __h_berval
#define __h_berval
#include "common.h"
#include "lber.h"
int LDAPberval_from_object(PyObject *obj, struct berval *bv);
int LDAPberval_from_object_check(PyObject *obj);
void LDAPberval_release(struct berval *bv);
PyObject *LDAPberval_to_object(const struct berval *bv);
#endif /* __h_berval_ */
python-ldap-2.4.10/Modules/errors.h 0000644 0000764 0000144 00000000607 11172071675 017731 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: errors.h,v 1.6 2009/04/17 12:19:09 stroeder Exp $ */
#ifndef __h_errors_
#define __h_errors_
#include "common.h"
#include "lber.h"
#include "ldap.h"
extern PyObject* LDAPexception_class;
extern PyObject* LDAPerror( LDAP*, char*msg );
extern void LDAPinit_errors( PyObject* );
PyObject* LDAPerr(int errnum);
#endif /* __h_errors */
python-ldap-2.4.10/Modules/version.h 0000644 0000764 0000144 00000000416 11172071675 020100 0 ustar michael users 0000000 0000000 /* Set release version
* See http://www.python-ldap.org/ for details.
* $Id: version.h,v 1.4 2009/04/17 12:19:09 stroeder Exp $ */
#ifndef __h_version_
#define __h_version_
#include "common.h"
extern void LDAPinit_version( PyObject* d );
#endif /* __h_version_ */
python-ldap-2.4.10/Modules/LDAPObject.c 0000644 0000764 0000144 00000115042 11550563067 020260 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: LDAPObject.c,v 1.90 2011/04/11 11:29:59 stroeder Exp $ */
#include "common.h"
#include "patchlevel.h"
#include
#include
#include "errors.h"
#include "constants.h"
#include "LDAPObject.h"
#include "ldapcontrol.h"
#include "message.h"
#include "berval.h"
#include "options.h"
#ifdef HAVE_SASL
#include
#endif
static void free_attrs(char***);
/* constructor */
LDAPObject*
newLDAPObject( LDAP* l )
{
LDAPObject* self = (LDAPObject*) PyObject_NEW(LDAPObject, &LDAP_Type);
if (self == NULL)
return NULL;
self->ldap = l;
self->_save = NULL;
self->valid = 1;
return self;
}
/* destructor */
static void
dealloc( LDAPObject* self )
{
if (self->ldap) {
if (self->valid) {
LDAP_BEGIN_ALLOW_THREADS( self );
ldap_unbind_ext( self->ldap, NULL, NULL );
LDAP_END_ALLOW_THREADS( self );
self->valid = 0;
}
self->ldap = NULL;
}
PyObject_DEL(self);
}
/*------------------------------------------------------------
* utility functions
*/
/*
* check to see if the LDAPObject is valid,
* ie has been opened, and not closed. An exception is set if not valid.
*/
static int
not_valid( LDAPObject* l ) {
if (l->valid) {
return 0;
} else {
PyErr_SetString( LDAPexception_class, "LDAP connection invalid" );
return 1;
}
}
/* free a LDAPMod (complete or partially) allocated in Tuple_to_LDAPMod() */
static void
LDAPMod_DEL( LDAPMod* lm )
{
Py_ssize_t i;
if (lm->mod_type)
PyMem_DEL(lm->mod_type);
if (lm->mod_bvalues) {
for (i = 0; lm->mod_bvalues[i]; i++) {
PyMem_DEL(lm->mod_bvalues[i]);
}
PyMem_DEL(lm->mod_bvalues);
}
PyMem_DEL(lm);
}
/*
* convert a tuple of the form (int,str,[str,...])
* or (str, [str,...]) if no_op is true, into an LDAPMod structure.
* See ldap_modify(3) for details.
*
* NOTE: the resulting LDAPMod structure has pointers directly into
* the Python string storage, so LDAPMod structures MUST have a
* shorter lifetime than the tuple passed in.
*/
/* XXX - there is no way to pass complex-structured BER objects in here! */
static LDAPMod*
Tuple_to_LDAPMod( PyObject* tup, int no_op )
{
int op;
char *type;
PyObject *list, *item;
LDAPMod *lm = NULL;
Py_ssize_t i, len, nstrs;
if (!PyTuple_Check(tup)) {
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
"expected a tuple", tup));
return NULL;
}
if (no_op) {
if (!PyArg_ParseTuple( tup, "sO", &type, &list ))
return NULL;
op = 0;
} else {
if (!PyArg_ParseTuple( tup, "isO", &op, &type, &list ))
return NULL;
}
lm = PyMem_NEW(LDAPMod, 1);
if (lm == NULL)
goto nomem;
lm->mod_op = op | LDAP_MOD_BVALUES;
lm->mod_bvalues = NULL;
len = strlen(type);
lm->mod_type = PyMem_NEW(char, len + 1);
if (lm->mod_type == NULL)
goto nomem;
memcpy(lm->mod_type, type, len + 1);
if (list == Py_None) {
/* None indicates a NULL mod_bvals */
} else if (PyString_Check(list)) {
/* Single string is a singleton list */
lm->mod_bvalues = PyMem_NEW(struct berval *, 2);
if (lm->mod_bvalues == NULL)
goto nomem;
lm->mod_bvalues[0] = PyMem_NEW(struct berval, 1);
if (lm->mod_bvalues[0] == NULL)
goto nomem;
lm->mod_bvalues[1] = NULL;
lm->mod_bvalues[0]->bv_len = PyString_Size(list);
lm->mod_bvalues[0]->bv_val = PyString_AsString(list);
} else if (PySequence_Check(list)) {
nstrs = PySequence_Length(list);
lm->mod_bvalues = PyMem_NEW(struct berval *, nstrs + 1);
if (lm->mod_bvalues == NULL)
goto nomem;
for (i = 0; i < nstrs; i++) {
lm->mod_bvalues[i] = PyMem_NEW(struct berval, 1);
if (lm->mod_bvalues[i] == NULL)
goto nomem;
lm->mod_bvalues[i+1] = NULL;
item = PySequence_GetItem(list, i);
if (item == NULL)
goto error;
if (!PyString_Check(item)) {
PyErr_SetObject( PyExc_TypeError, Py_BuildValue( "sO",
"expected a string in the list", item));
Py_DECREF(item);
goto error;
}
lm->mod_bvalues[i]->bv_len = PyString_Size(item);
lm->mod_bvalues[i]->bv_val = PyString_AsString(item);
Py_DECREF(item);
}
if (nstrs == 0)
lm->mod_bvalues[0] = NULL;
}
return lm;
nomem:
PyErr_NoMemory();
error:
if (lm)
LDAPMod_DEL(lm);
return NULL;
}
/* free the structure allocated in List_to_LDAPMods() */
static void
LDAPMods_DEL( LDAPMod** lms ) {
LDAPMod** lmp;
for ( lmp = lms; *lmp; lmp++ )
LDAPMod_DEL( *lmp );
PyMem_DEL(lms);
}
/*
* convert a list of tuples into a LDAPMod*[] array structure
* NOTE: list of tuples must live longer than the LDAPMods
*/
static LDAPMod**
List_to_LDAPMods( PyObject *list, int no_op ) {
Py_ssize_t i, len;
LDAPMod** lms;
PyObject *item;
if (!PySequence_Check(list)) {
PyErr_SetObject( PyExc_TypeError, Py_BuildValue("sO",
"expected list of tuples", list ));
return NULL;
}
len = PySequence_Length(list);
if (len < 0) {
PyErr_SetObject( PyExc_TypeError, Py_BuildValue("sO",
"expected list of tuples", list ));
return NULL;
}
lms = PyMem_NEW(LDAPMod *, len + 1);
if (lms == NULL)
goto nomem;
for (i = 0; i < len; i++) {
lms[i] = NULL;
item = PySequence_GetItem(list, i);
if (item == NULL)
goto error;
lms[i] = Tuple_to_LDAPMod(item, no_op);
Py_DECREF(item);
if (lms[i] == NULL)
goto error;
}
lms[len] = NULL;
return lms;
nomem:
PyErr_NoMemory();
error:
if (lms)
LDAPMods_DEL(lms);
return NULL;
}
/*
* convert a python list of strings into an attr list (char*[]).
* returns 1 if successful, 0 if not (with exception set)
* XXX the strings should live longer than the resulting attrs pointer.
*/
int
attrs_from_List( PyObject *attrlist, char***attrsp ) {
char **attrs = NULL;
Py_ssize_t i, len;
PyObject *item;
if (attrlist == Py_None) {
/* None means a NULL attrlist */
} else if (PyString_Check(attrlist)) {
/* caught by John Benninghoff */
PyErr_SetObject( PyExc_TypeError, Py_BuildValue("sO",
"expected *list* of strings, not a string", attrlist ));
goto error;
} else if (PySequence_Check(attrlist)) {
len = PySequence_Length(attrlist);
attrs = PyMem_NEW(char *, len + 1);
if (attrs == NULL)
goto nomem;
for (i = 0; i < len; i++) {
attrs[i] = NULL;
item = PySequence_GetItem(attrlist, i);
if (item == NULL)
goto error;
if (!PyString_Check(item)) {
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
"expected string in list", item));
Py_DECREF(item);
goto error;
}
attrs[i] = PyString_AsString(item);
Py_DECREF(item);
}
attrs[len] = NULL;
} else {
PyErr_SetObject( PyExc_TypeError, Py_BuildValue("sO",
"expected list of strings or None", attrlist ));
goto error;
}
*attrsp = attrs;
return 1;
nomem:
PyErr_NoMemory();
error:
free_attrs(&attrs);
return 0;
}
/* free memory allocated from above routine */
static void
free_attrs( char*** attrsp ) {
char **attrs = *attrsp;
if (attrs != NULL) {
PyMem_DEL(attrs);
*attrsp = NULL;
}
}
/*------------------------------------------------------------
* methods
*/
/* ldap_unbind_ext */
static PyObject*
l_ldap_unbind_ext( LDAPObject* self, PyObject* args )
{
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
int ldaperror;
if (!PyArg_ParseTuple( args, "|OO", &serverctrls, &clientctrls)) return NULL;
if (not_valid(self)) return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_unbind_ext( self->ldap, server_ldcs, client_ldcs );
LDAP_END_ALLOW_THREADS( self );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_unbind_ext" );
self->valid = 0;
Py_INCREF(Py_None);
return Py_None;
}
/* ldap_abandon_ext */
static PyObject*
l_ldap_abandon_ext( LDAPObject* self, PyObject* args )
{
int msgid;
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
int ldaperror;
if (!PyArg_ParseTuple( args, "i|OO", &msgid, &serverctrls, &clientctrls)) return NULL;
if (not_valid(self)) return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_abandon_ext( self->ldap, msgid, server_ldcs, client_ldcs );
LDAP_END_ALLOW_THREADS( self );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_abandon_ext" );
Py_INCREF(Py_None);
return Py_None;
}
/* ldap_add_ext */
static PyObject *
l_ldap_add_ext( LDAPObject* self, PyObject *args )
{
char *dn;
PyObject *modlist;
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
int msgid;
int ldaperror;
LDAPMod **mods;
if (!PyArg_ParseTuple( args, "sO|OO", &dn, &modlist, &serverctrls, &clientctrls )) return NULL;
if (not_valid(self)) return NULL;
mods = List_to_LDAPMods( modlist, 1 );
if (mods == NULL)
return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_add_ext( self->ldap, dn, mods, server_ldcs, client_ldcs, &msgid);
LDAP_END_ALLOW_THREADS( self );
LDAPMods_DEL( mods );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_add_ext" );
return PyInt_FromLong(msgid);
}
/* ldap_simple_bind */
static PyObject*
l_ldap_simple_bind( LDAPObject* self, PyObject* args )
{
char *who;
int msgid;
int ldaperror;
Py_ssize_t cred_len;
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
struct berval cred;
if (!PyArg_ParseTuple( args, "ss#|OO", &who, &cred.bv_val, &cred_len, &serverctrls, &clientctrls )) return NULL;
cred.bv_len = (ber_len_t) cred_len;
if (not_valid(self)) return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_sasl_bind( self->ldap, who, LDAP_SASL_SIMPLE, &cred, server_ldcs, client_ldcs, &msgid);
LDAP_END_ALLOW_THREADS( self );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_simple_bind" );
return PyInt_FromLong( msgid );
}
#ifdef HAVE_SASL
/* The following functions implement SASL binds. A new method
sasl_interactive_bind_s(bind_dn, sasl_mechanism) has been introduced.
* The bind_dn argument will be passed to the c library; however,
normally it is not needed and should be an empty string.
* The sasl_mechanism argument is an instance of a class that
implements a callback interface. For convenience, it should be
derived from the sasl class (which lives in the ldap.sasl module).
See the module documentation for more information.
Check your /usr/lib/sasl/ directory for locally installed SASL
auth modules ("mechanisms"), or try
ldapsearch -b "" -s base -LLL -x supportedSASLMechanisms
(perhaps with an additional -h and -p argument for ldap host and
port). The latter will show you which SASL mechanisms are known
to the LDAP server. If you do not want to set up Kerberos, you
can still use SASL binds. Your authentication data should then be
stored in /etc/sasldb (see saslpasswd(8)). If the LDAP server
does not find the sasldb, it wont allow for DIGEST-MD5 and
CRAM-MD5. One important thing to get started with sasldb: you
should first add a dummy user (saslpasswd -c dummy), and this
will give you some strange error messages. Then delete the dummy
user (saslpasswd -d dummy), and now you can start adding users to
your sasldb (again, use the -c switch). Strange, eh?
* The sasl_mechanism object must implement a method, which will be
called by the sasl lib several times. The prototype of the
callback looks like this: callback(id, challenge, prompt,
defresult) has to return a string (or maybe None). The id
argument specifies, which information should be passed back to
the SASL lib (see SASL_CB_xxx in sasl.h)
A nice "Howto get LDAPv3 up and running with Kerberos and SSL" can
be found at http://www.bayour.com/LDAPv3-HOWTO.html. Instead of
MIT Kerberos, I used Heimdal for my tests (since it is included
with SuSE Linux).
Todo:
* Find a better interface than the python callback. This is
really ugly. Perhaps one could make use of a sasl class, like
in the perl ldap module.
* Thread safety?
* Memory Management?
* Write more docs
* ...
*/
static int interaction ( unsigned flags,
sasl_interact_t *interact,
PyObject* SASLObject )
{
/* const char *dflt = interact->defresult; */
PyObject *result;
char *c_result;
result = PyObject_CallMethod(SASLObject,
"callback",
"isss",
interact->id, /* see sasl.h */
interact->challenge,
interact->prompt,
interact->defresult);
if (result == NULL)
/*searching for a better error code */
return LDAP_OPERATIONS_ERROR;
c_result = PyString_AsString(result); /*xxx Error checking?? */
/* according to the sasl docs, we should malloc() the returned
string only for calls where interact->id == SASL_CB_PASS, so we
probably leak a few bytes per ldap bind. However, if I restrict
the strdup() to this case, I get segfaults. Should probably be
fixed sometimes.
*/
interact->result = strdup( c_result );
if (interact->result == NULL)
return LDAP_OPERATIONS_ERROR;
interact->len = strlen(c_result);
/* We _should_ overwrite the python string buffer for security
reasons, however we may not (api/stringObjects.html). Any ideas?
*/
Py_DECREF(result); /*not needed any longer */
result = NULL;
return LDAP_SUCCESS;
}
/*
This function will be called by ldap_sasl_interactive_bind(). The
"*in" is an array of sasl_interact_t's (see sasl.h for a
reference). The last interact in the array has an interact->id of
SASL_CB_LIST_END.
*/
int py_ldap_sasl_interaction( LDAP *ld,
unsigned flags,
void *defaults,
void *in )
{
/* These are just typecasts */
sasl_interact_t *interact = (sasl_interact_t *) in;
PyObject *SASLObject = (PyObject *) defaults;
/* Loop over the array of sasl_interact_t structs */
while( interact->id != SASL_CB_LIST_END ) {
int rc = 0;
rc = interaction( flags, interact, SASLObject );
if( rc ) return rc;
interact++;
}
return LDAP_SUCCESS;
}
static PyObject*
l_ldap_sasl_interactive_bind_s( LDAPObject* self, PyObject* args )
{
char *c_mechanism;
char *who;
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
PyObject *SASLObject = NULL;
PyObject *mechanism = NULL;
int msgid;
static unsigned sasl_flags = LDAP_SASL_QUIET;
/*
* In Python 2.3+, a "I" format argument indicates that we're either converting
* the Python object into a long or an unsigned int. In versions prior to that,
* it will always convert to a long. Since the sasl_flags variable is an
* unsigned int, we need to use the "I" flag if we're running Python 2.3+ and a
* "i" otherwise.
*/
#if (PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION < 3)
if (!PyArg_ParseTuple(args, "sOOOi", &who, &SASLObject, &serverctrls, &clientctrls, &sasl_flags ))
#else
if (!PyArg_ParseTuple(args, "sOOOI", &who, &SASLObject, &serverctrls, &clientctrls, &sasl_flags ))
#endif
return NULL;
if (not_valid(self)) return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
/* now we extract the sasl mechanism from the SASL Object */
mechanism = PyObject_GetAttrString(SASLObject, "mech");
if (mechanism == NULL) return NULL;
c_mechanism = PyString_AsString(mechanism);
Py_DECREF(mechanism);
mechanism = NULL;
/* Don't know if it is the "intended use" of the defaults
parameter of ldap_sasl_interactive_bind_s when we pass the
Python object SASLObject, but passing it through some
static variable would destroy thread safety, IMHO.
*/
msgid = ldap_sasl_interactive_bind_s(self->ldap,
who,
c_mechanism,
(LDAPControl**) server_ldcs,
(LDAPControl**) client_ldcs,
sasl_flags,
py_ldap_sasl_interaction,
SASLObject);
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if (msgid != LDAP_SUCCESS)
return LDAPerror( self->ldap, "ldap_sasl_interactive_bind_s" );
return PyInt_FromLong( msgid );
}
#endif
#ifdef LDAP_API_FEATURE_CANCEL
/* ldap_cancel */
static PyObject*
l_ldap_cancel( LDAPObject* self, PyObject* args )
{
int msgid;
int cancelid;
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
int ldaperror;
if (!PyArg_ParseTuple( args, "i|OO", &cancelid, &serverctrls, &clientctrls)) return NULL;
if (not_valid(self)) return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_cancel( self->ldap, cancelid, server_ldcs, client_ldcs, &msgid );
LDAP_END_ALLOW_THREADS( self );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_cancel" );
return PyInt_FromLong( msgid );
}
#endif
/* ldap_compare_ext */
static PyObject *
l_ldap_compare_ext( LDAPObject* self, PyObject *args )
{
char *dn, *attr;
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
int msgid;
int ldaperror;
Py_ssize_t value_len;
struct berval value;
if (!PyArg_ParseTuple( args, "sss#|OO", &dn, &attr, &value.bv_val, &value_len, &serverctrls, &clientctrls )) return NULL;
value.bv_len = (ber_len_t) value_len;
if (not_valid(self)) return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_compare_ext( self->ldap, dn, attr, &value, server_ldcs, client_ldcs, &msgid );
LDAP_END_ALLOW_THREADS( self );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_compare_ext" );
return PyInt_FromLong( msgid );
}
/* ldap_delete_ext */
static PyObject *
l_ldap_delete_ext( LDAPObject* self, PyObject *args )
{
char *dn;
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
int msgid;
int ldaperror;
if (!PyArg_ParseTuple( args, "s|OO", &dn, &serverctrls, &clientctrls )) return NULL;
if (not_valid(self)) return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_delete_ext( self->ldap, dn, server_ldcs, client_ldcs, &msgid );
LDAP_END_ALLOW_THREADS( self );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_delete_ext" );
return PyInt_FromLong(msgid);
}
/* ldap_modify_ext */
static PyObject *
l_ldap_modify_ext( LDAPObject* self, PyObject *args )
{
char *dn;
PyObject *modlist;
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
int msgid;
int ldaperror;
LDAPMod **mods;
if (!PyArg_ParseTuple( args, "sO|OO", &dn, &modlist, &serverctrls, &clientctrls )) return NULL;
if (not_valid(self)) return NULL;
mods = List_to_LDAPMods( modlist, 0 );
if (mods == NULL)
return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_modify_ext( self->ldap, dn, mods, server_ldcs, client_ldcs, &msgid );
LDAP_END_ALLOW_THREADS( self );
LDAPMods_DEL( mods );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_modify_ext" );
return PyInt_FromLong( msgid );
}
/* ldap_rename */
static PyObject *
l_ldap_rename( LDAPObject* self, PyObject *args )
{
char *dn, *newrdn;
char *newSuperior = NULL;
int delold = 1;
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
int msgid;
int ldaperror;
if (!PyArg_ParseTuple( args, "ss|ziOO", &dn, &newrdn, &newSuperior, &delold, &serverctrls, &clientctrls ))
return NULL;
if (not_valid(self)) return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_rename( self->ldap, dn, newrdn, newSuperior, delold, server_ldcs, client_ldcs, &msgid );
LDAP_END_ALLOW_THREADS( self );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_rename" );
return PyInt_FromLong( msgid );
}
/* ldap_result4 */
static PyObject *
l_ldap_result4( LDAPObject* self, PyObject *args )
{
int msgid = LDAP_RES_ANY;
int all = 1;
double timeout = -1.0;
int add_ctrls = 0;
int add_intermediates = 0;
int add_extop = 0;
struct timeval tv;
struct timeval* tvp;
int res_type;
LDAPMessage *msg = NULL;
PyObject *result_str, *retval, *pmsg, *pyctrls = 0;
int res_msgid = 0;
char *retoid = 0;
PyObject *valuestr = 0;
if (!PyArg_ParseTuple( args, "|iidiii", &msgid, &all, &timeout, &add_ctrls, &add_intermediates, &add_extop ))
return NULL;
if (not_valid(self)) return NULL;
if (timeout >= 0) {
tvp = &tv;
set_timeval_from_double( tvp, timeout );
} else {
tvp = NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
res_type = ldap_result( self->ldap, msgid, all, tvp, &msg );
LDAP_END_ALLOW_THREADS( self );
if (res_type < 0) /* LDAP or system error */
return LDAPerror( self->ldap, "ldap_result4" );
if (res_type == 0) {
/* Polls return (None, None, None, None); timeouts raise an exception */
if (timeout == 0) {
if (add_extop) {
return Py_BuildValue("(OOOOOO)", Py_None, Py_None, Py_None, Py_None, Py_None, Py_None);
} else {
return Py_BuildValue("(OOOO)", Py_None, Py_None, Py_None, Py_None);
}
}
else
return LDAPerr(LDAP_TIMEOUT);
}
if (msg)
res_msgid = ldap_msgid(msg);
int result = LDAP_SUCCESS;
char **refs = NULL;
LDAPControl **serverctrls = 0;
LDAP_BEGIN_ALLOW_THREADS( self );
if (res_type == LDAP_RES_SEARCH_ENTRY) {
/* LDAPmessage_to_python will parse entries and read the controls for each entry */
} else if (res_type == LDAP_RES_SEARCH_REFERENCE) {
/* LDAPmessage_to_python will parse refs and read the controls for each res */
} else if (res_type == LDAP_RES_INTERMEDIATE) {
/* LDAPmessage_to_python will parse intermediates and controls */
} else {
int rc;
if (res_type == LDAP_RES_EXTENDED) {
struct berval *retdata = 0;
rc = ldap_parse_extended_result( self->ldap, msg, &retoid, &retdata, 0 );
/* handle error rc!=0 here? */
if (rc == LDAP_SUCCESS) {
valuestr = LDAPberval_to_object(retdata);
}
ber_bvfree( retdata );
}
rc = ldap_parse_result( self->ldap, msg, &result, NULL, NULL, &refs,
&serverctrls, 0 );
}
LDAP_END_ALLOW_THREADS( self );
if (result != LDAP_SUCCESS) { /* result error */
char *e, err[1024];
if (result == LDAP_REFERRAL && refs && refs[0]) {
snprintf(err, sizeof(err), "Referral:\n%s", refs[0]);
e = err;
} else
e = "ldap_parse_result";
ldap_msgfree(msg);
return LDAPerror( self->ldap, e );
}
if (!(pyctrls = LDAPControls_to_List(serverctrls))) {
int err = LDAP_NO_MEMORY;
ldap_set_option(self->ldap, LDAP_OPT_ERROR_NUMBER, &err);
ldap_msgfree(msg);
return LDAPerror(self->ldap, "LDAPControls_to_List");
}
ldap_controls_free(serverctrls);
pmsg = LDAPmessage_to_python( self->ldap, msg, add_ctrls, add_intermediates );
result_str = LDAPconstant( res_type );
if (pmsg == NULL) {
retval = NULL;
} else {
/* s handles NULL, but O does not */
if (add_extop) {
retval = Py_BuildValue("(OOiOsO)", result_str, pmsg, res_msgid,
pyctrls, retoid, valuestr ? valuestr : Py_None);
} else {
retval = Py_BuildValue("(OOiO)", result_str, pmsg, res_msgid, pyctrls);
}
if (pmsg != Py_None) {
Py_DECREF(pmsg);
}
}
if (valuestr) {
Py_DECREF(valuestr);
}
Py_XDECREF(pyctrls);
Py_DECREF(result_str);
return retval;
}
/* ldap_search_ext */
static PyObject*
l_ldap_search_ext( LDAPObject* self, PyObject* args )
{
char *base;
int scope;
char *filter;
PyObject *attrlist = Py_None;
char **attrs;
int attrsonly = 0;
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
double timeout = -1.0;
struct timeval tv;
struct timeval* tvp;
int sizelimit = 0;
int msgid;
int ldaperror;
if (!PyArg_ParseTuple( args, "sis|OiOOdi",
&base, &scope, &filter, &attrlist, &attrsonly,
&serverctrls, &clientctrls, &timeout, &sizelimit )) return NULL;
if (not_valid(self)) return NULL;
if (!attrs_from_List( attrlist, &attrs ))
return NULL;
if (timeout >= 0) {
tvp = &tv;
set_timeval_from_double( tvp, timeout );
} else {
tvp = NULL;
}
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_search_ext( self->ldap, base, scope, filter, attrs, attrsonly,
server_ldcs, client_ldcs, tvp, sizelimit, &msgid );
LDAP_END_ALLOW_THREADS( self );
free_attrs( &attrs );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_search_ext" );
return PyInt_FromLong( msgid );
}
/* ldap_whoami_s (available since OpenLDAP 2.1.13) */
static PyObject*
l_ldap_whoami_s( LDAPObject* self, PyObject* args )
{
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
struct berval *bvalue = NULL;
PyObject *result;
int ldaperror;
if (!PyArg_ParseTuple( args, "|OO", &serverctrls, &clientctrls)) return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_whoami_s( self->ldap, &bvalue, server_ldcs, client_ldcs );
LDAP_END_ALLOW_THREADS( self );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_whoami_s" );
result = LDAPberval_to_object(bvalue);
return result;
}
#ifdef HAVE_TLS
/* ldap_start_tls_s */
static PyObject*
l_ldap_start_tls_s( LDAPObject* self, PyObject* args )
{
int result;
if (!PyArg_ParseTuple( args, "" )) return NULL;
if (not_valid(self)) return NULL;
result = ldap_start_tls_s( self->ldap, NULL, NULL );
if ( result != LDAP_SUCCESS ){
ldap_set_option(self->ldap, LDAP_OPT_ERROR_NUMBER, &result);
return LDAPerror( self->ldap, "ldap_start_tls_s" );
}
Py_INCREF(Py_None);
return Py_None;
}
#endif
/* ldap_set_option */
static PyObject*
l_ldap_set_option(PyObject* self, PyObject *args)
{
PyObject *value;
int option;
if (!PyArg_ParseTuple(args, "iO:set_option", &option, &value))
return NULL;
if (LDAP_set_option((LDAPObject *)self, option, value) == -1)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
/* ldap_get_option */
static PyObject*
l_ldap_get_option(PyObject* self, PyObject *args)
{
int option;
if (!PyArg_ParseTuple(args, "i:get_option", &option))
return NULL;
return LDAP_get_option((LDAPObject *)self, option);
}
/* ldap_passwd */
static PyObject *
l_ldap_passwd( LDAPObject* self, PyObject *args )
{
struct berval user;
Py_ssize_t user_len;
struct berval oldpw;
Py_ssize_t oldpw_len;
struct berval newpw;
Py_ssize_t newpw_len;
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
int msgid;
int ldaperror;
if (!PyArg_ParseTuple( args, "z#z#z#|OO", &user.bv_val, &user_len, &oldpw.bv_val, &oldpw_len, &newpw.bv_val, &newpw_len, &serverctrls, &clientctrls ))
return NULL;
user.bv_len = (ber_len_t) user_len;
oldpw.bv_len = (ber_len_t) oldpw_len;
newpw.bv_len = (ber_len_t) newpw_len;
if (not_valid(self)) return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_passwd( self->ldap,
user.bv_val != NULL ? &user : NULL,
oldpw.bv_val != NULL ? &oldpw : NULL,
newpw.bv_val != NULL ? &newpw : NULL,
server_ldcs,
client_ldcs,
&msgid );
LDAP_END_ALLOW_THREADS( self );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_passwd" );
return PyInt_FromLong( msgid );
}
/* ldap_extended_operation */
static PyObject *
l_ldap_extended_operation( LDAPObject* self, PyObject *args )
{
char *reqoid = NULL;
struct berval reqvalue = {0, NULL};
PyObject *serverctrls = Py_None;
PyObject *clientctrls = Py_None;
LDAPControl** server_ldcs = NULL;
LDAPControl** client_ldcs = NULL;
int msgid;
int ldaperror;
if (!PyArg_ParseTuple( args, "sz#|OO", &reqoid, &reqvalue.bv_val, &reqvalue.bv_len, &serverctrls, &clientctrls ))
return NULL;
if (not_valid(self)) return NULL;
if (!PyNone_Check(serverctrls)) {
if (!LDAPControls_from_object(serverctrls, &server_ldcs))
return NULL;
}
if (!PyNone_Check(clientctrls)) {
if (!LDAPControls_from_object(clientctrls, &client_ldcs))
return NULL;
}
LDAP_BEGIN_ALLOW_THREADS( self );
ldaperror = ldap_extended_operation( self->ldap, reqoid,
reqvalue.bv_val != NULL ? &reqvalue : NULL,
server_ldcs,
client_ldcs,
&msgid );
LDAP_END_ALLOW_THREADS( self );
LDAPControl_List_DEL( server_ldcs );
LDAPControl_List_DEL( client_ldcs );
if ( ldaperror!=LDAP_SUCCESS )
return LDAPerror( self->ldap, "ldap_extended_operation" );
return PyInt_FromLong( msgid );
}
/* methods */
static PyMethodDef methods[] = {
{"unbind_ext", (PyCFunction)l_ldap_unbind_ext, METH_VARARGS },
{"abandon_ext", (PyCFunction)l_ldap_abandon_ext, METH_VARARGS },
{"add_ext", (PyCFunction)l_ldap_add_ext, METH_VARARGS },
{"simple_bind", (PyCFunction)l_ldap_simple_bind, METH_VARARGS },
#ifdef HAVE_SASL
{"sasl_interactive_bind_s", (PyCFunction)l_ldap_sasl_interactive_bind_s, METH_VARARGS },
#endif
{"compare_ext", (PyCFunction)l_ldap_compare_ext, METH_VARARGS },
{"delete_ext", (PyCFunction)l_ldap_delete_ext, METH_VARARGS },
{"modify_ext", (PyCFunction)l_ldap_modify_ext, METH_VARARGS },
{"rename", (PyCFunction)l_ldap_rename, METH_VARARGS },
{"result4", (PyCFunction)l_ldap_result4, METH_VARARGS },
{"search_ext", (PyCFunction)l_ldap_search_ext, METH_VARARGS },
#ifdef HAVE_TLS
{"start_tls_s", (PyCFunction)l_ldap_start_tls_s, METH_VARARGS },
#endif
{"whoami_s", (PyCFunction)l_ldap_whoami_s, METH_VARARGS },
{"passwd", (PyCFunction)l_ldap_passwd, METH_VARARGS },
{"set_option", (PyCFunction)l_ldap_set_option, METH_VARARGS },
{"get_option", (PyCFunction)l_ldap_get_option, METH_VARARGS },
#ifdef LDAP_API_FEATURE_CANCEL
{"cancel", (PyCFunction)l_ldap_cancel, METH_VARARGS },
#endif
{"extop", (PyCFunction)l_ldap_extended_operation, METH_VARARGS },
{ NULL, NULL }
};
/* get attribute */
static PyObject*
getattr(LDAPObject* self, char* name)
{
return Py_FindMethod(methods, (PyObject*)self, name);
}
/* set attribute */
static int
setattr(LDAPObject* self, char* name, PyObject* value)
{
PyErr_SetString(PyExc_AttributeError, name);
return -1;
}
/* type entry */
PyTypeObject LDAP_Type = {
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
/* see http://www.python.org/doc/FAQ.html#3.24 */
PyObject_HEAD_INIT(NULL)
#else /* ! MS_WINDOWS */
PyObject_HEAD_INIT(&PyType_Type)
#endif /* MS_WINDOWS */
0, /*ob_size*/
"LDAP", /*tp_name*/
sizeof(LDAPObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)getattr, /*tp_getattr*/
(setattrfunc)setattr, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
};
python-ldap-2.4.10/Modules/options.c 0000644 0000764 0000144 00000024312 11574511341 020075 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: options.c,v 1.39 2011/06/10 21:55:45 stroeder Exp $ */
#include "common.h"
#include "errors.h"
#include "LDAPObject.h"
#include "ldapcontrol.h"
#include "options.h"
void
set_timeval_from_double( struct timeval *tv, double d ) {
tv->tv_usec = (long) ( fmod(d, 1.0) * 1000000.0 );
tv->tv_sec = (long) floor(d);
}
/**
* Converts a return code from ldap_set_option() or ldap_get_option()
* into a python error, and returns NULL.
*/
static PyObject *
option_error(int res, const char *fn)
{
if (res == LDAP_OPT_ERROR)
PyErr_SetString(PyExc_ValueError, "option error");
else if (res == LDAP_PARAM_ERROR)
PyErr_SetString(PyExc_ValueError, "parameter error");
else if (res == LDAP_NO_MEMORY)
PyErr_NoMemory();
else
PyErr_Format(PyExc_SystemError, "error %d from %s", res, fn);
return NULL;
}
/**
* Sets an LDAP option.
* Returns 0 on failure, 1 on success
*/
int
LDAP_set_option(LDAPObject *self, int option, PyObject *value)
{
int res;
int intval;
double doubleval;
char *strval;
struct timeval tv;
void *ptr;
LDAP *ld;
LDAPControl **controls = NULL;
ld = self ? self->ldap : NULL;
switch(option) {
case LDAP_OPT_API_INFO:
case LDAP_OPT_API_FEATURE_INFO:
#ifdef HAVE_SASL
case LDAP_OPT_X_SASL_SSF:
#endif
/* Read-only options */
PyErr_SetString(PyExc_ValueError, "read-only option");
return 0;
case LDAP_OPT_REFERRALS:
case LDAP_OPT_RESTART:
#ifdef LDAP_OPT_X_SASL_NOCANON
case LDAP_OPT_X_SASL_NOCANON:
#endif
#ifdef LDAP_OPT_CONNECT_ASYNC
case LDAP_OPT_CONNECT_ASYNC:
#endif
/* Truth-value options */
ptr = PyObject_IsTrue(value) ? LDAP_OPT_ON : LDAP_OPT_OFF;
break;
case LDAP_OPT_DEREF:
case LDAP_OPT_SIZELIMIT:
case LDAP_OPT_TIMELIMIT:
case LDAP_OPT_PROTOCOL_VERSION:
case LDAP_OPT_ERROR_NUMBER:
case LDAP_OPT_DEBUG_LEVEL:
#ifdef HAVE_TLS
case LDAP_OPT_X_TLS:
case LDAP_OPT_X_TLS_REQUIRE_CERT:
#ifdef LDAP_OPT_X_TLS_CRLCHECK
case LDAP_OPT_X_TLS_CRLCHECK:
#endif
#ifdef LDAP_OPT_X_TLS_NEWCTX
case LDAP_OPT_X_TLS_NEWCTX:
#endif
#ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
case LDAP_OPT_X_TLS_PROTOCOL_MIN:
#endif
#endif
#ifdef HAVE_SASL
case LDAP_OPT_X_SASL_SSF_MIN:
case LDAP_OPT_X_SASL_SSF_MAX:
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_IDLE
case LDAP_OPT_X_KEEPALIVE_IDLE:
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_PROBES
case LDAP_OPT_X_KEEPALIVE_PROBES:
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
case LDAP_OPT_X_KEEPALIVE_INTERVAL:
#endif
/* integer value options */
if (!PyArg_Parse(value, "i:set_option", &intval))
return 0;
ptr = &intval;
break;
case LDAP_OPT_HOST_NAME:
case LDAP_OPT_URI:
#ifdef LDAP_OPT_DEFBASE
case LDAP_OPT_DEFBASE:
#endif
case LDAP_OPT_ERROR_STRING:
case LDAP_OPT_MATCHED_DN:
#ifdef HAVE_TLS
case LDAP_OPT_X_TLS_CACERTFILE:
case LDAP_OPT_X_TLS_CACERTDIR:
case LDAP_OPT_X_TLS_CERTFILE:
case LDAP_OPT_X_TLS_KEYFILE:
case LDAP_OPT_X_TLS_CIPHER_SUITE:
case LDAP_OPT_X_TLS_RANDOM_FILE:
case LDAP_OPT_X_TLS_DHFILE:
#ifdef LDAP_OPT_X_TLS_CRLFILE
case LDAP_OPT_X_TLS_CRLFILE:
#endif
#endif
#ifdef HAVE_SASL
case LDAP_OPT_X_SASL_SECPROPS:
#endif
/* String valued options */
if (!PyArg_Parse(value, "s:set_option", &strval))
return 0;
ptr = strval;
break;
case LDAP_OPT_TIMEOUT:
case LDAP_OPT_NETWORK_TIMEOUT:
/* Float valued timeval options */
if (!PyArg_Parse(value, "d:set_option", &doubleval))
return 0;
if (doubleval >= 0) {
set_timeval_from_double( &tv, doubleval );
ptr = &tv;
} else {
ptr = NULL;
}
break;
case LDAP_OPT_SERVER_CONTROLS:
case LDAP_OPT_CLIENT_CONTROLS:
if (!LDAPControls_from_object(value, &controls))
return 0;
ptr = controls;
break;
default:
PyErr_Format(PyExc_ValueError, "unknown option %d", option);
return 0;
}
if (self) LDAP_BEGIN_ALLOW_THREADS(self);
res = ldap_set_option(ld, option, ptr);
if (self) LDAP_END_ALLOW_THREADS(self);
if ((option == LDAP_OPT_SERVER_CONTROLS) || (option == LDAP_OPT_CLIENT_CONTROLS))
LDAPControl_List_DEL(controls);
if (res != LDAP_OPT_SUCCESS) {
option_error(res, "ldap_set_option");
return 0;
}
return 1;
}
PyObject *
LDAP_get_option(LDAPObject *self, int option)
{
int res;
int intval;
struct timeval *tv;
LDAPAPIInfo apiinfo;
LDAPControl **lcs;
LDAPControl *lc;
char *strval;
PyObject *extensions, *v, *tup;
Py_ssize_t i, num_extensions, num_controls;
LDAP *ld;
ld = self ? self->ldap : NULL;
switch(option) {
case LDAP_OPT_API_INFO:
apiinfo.ldapai_info_version = LDAP_API_INFO_VERSION;
if (self) LDAP_BEGIN_ALLOW_THREADS(self);
res = ldap_get_option( ld, option, &apiinfo );
if (self) LDAP_END_ALLOW_THREADS(self);
if (res != LDAP_OPT_SUCCESS)
return option_error(res, "ldap_get_option");
/* put the extensions into tuple form */
num_extensions = 0;
while (apiinfo.ldapai_extensions[num_extensions])
num_extensions++;
extensions = PyTuple_New(num_extensions);
for (i = 0; i < num_extensions; i++)
PyTuple_SET_ITEM(extensions, i,
PyString_FromString(apiinfo.ldapai_extensions[i]));
/* return api info as a dictionary */
v = Py_BuildValue("{s:i, s:i, s:i, s:s, s:i, s:O}",
"info_version", apiinfo.ldapai_info_version,
"api_version", apiinfo.ldapai_api_version,
"protocol_version", apiinfo.ldapai_protocol_version,
"vendor_name", apiinfo.ldapai_vendor_name,
"vendor_version", apiinfo.ldapai_vendor_version,
"extensions", extensions);
if (apiinfo.ldapai_vendor_name)
ldap_memfree(apiinfo.ldapai_vendor_name);
for (i = 0; i < num_extensions; i++)
ldap_memfree(apiinfo.ldapai_extensions[i]);
ldap_memfree(apiinfo.ldapai_extensions);
Py_DECREF(extensions);
return v;
#ifdef HAVE_SASL
case LDAP_OPT_X_SASL_SSF:
#endif
case LDAP_OPT_REFERRALS:
case LDAP_OPT_RESTART:
case LDAP_OPT_DEREF:
case LDAP_OPT_SIZELIMIT:
case LDAP_OPT_TIMELIMIT:
case LDAP_OPT_PROTOCOL_VERSION:
case LDAP_OPT_ERROR_NUMBER:
case LDAP_OPT_DEBUG_LEVEL:
#ifdef HAVE_TLS
case LDAP_OPT_X_TLS:
case LDAP_OPT_X_TLS_REQUIRE_CERT:
#ifdef LDAP_OPT_X_TLS_CRLCHECK
case LDAP_OPT_X_TLS_CRLCHECK:
#endif
#ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
case LDAP_OPT_X_TLS_PROTOCOL_MIN:
#endif
#endif
#ifdef HAVE_SASL
case LDAP_OPT_X_SASL_SSF_MIN:
case LDAP_OPT_X_SASL_SSF_MAX:
#endif
#ifdef LDAP_OPT_X_SASL_NOCANON
case LDAP_OPT_X_SASL_NOCANON:
#endif
#ifdef LDAP_OPT_CONNECT_ASYNC
case LDAP_OPT_CONNECT_ASYNC:
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_IDLE
case LDAP_OPT_X_KEEPALIVE_IDLE:
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_PROBES
case LDAP_OPT_X_KEEPALIVE_PROBES:
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
case LDAP_OPT_X_KEEPALIVE_INTERVAL:
#endif
/* Integer-valued options */
if (self) LDAP_BEGIN_ALLOW_THREADS(self);
res = ldap_get_option(ld, option, &intval);
if (self) LDAP_END_ALLOW_THREADS(self);
if (res != LDAP_OPT_SUCCESS)
return option_error(res, "ldap_get_option");
return PyInt_FromLong(intval);
case LDAP_OPT_HOST_NAME:
case LDAP_OPT_URI:
#ifdef LDAP_OPT_DEFBASE
case LDAP_OPT_DEFBASE:
#endif
case LDAP_OPT_ERROR_STRING:
case LDAP_OPT_MATCHED_DN:
#ifdef HAVE_TLS
case LDAP_OPT_X_TLS_CACERTFILE:
case LDAP_OPT_X_TLS_CACERTDIR:
case LDAP_OPT_X_TLS_CERTFILE:
case LDAP_OPT_X_TLS_KEYFILE:
case LDAP_OPT_X_TLS_CIPHER_SUITE:
case LDAP_OPT_X_TLS_RANDOM_FILE:
case LDAP_OPT_X_TLS_DHFILE:
#ifdef LDAP_OPT_X_TLS_CRLFILE
case LDAP_OPT_X_TLS_CRLFILE:
#endif
#ifdef LDAP_OPT_X_TLS_PACKAGE
case LDAP_OPT_X_TLS_PACKAGE:
#endif
#endif
#ifdef HAVE_SASL
case LDAP_OPT_X_SASL_SECPROPS:
case LDAP_OPT_X_SASL_MECH:
case LDAP_OPT_X_SASL_REALM:
case LDAP_OPT_X_SASL_AUTHCID:
case LDAP_OPT_X_SASL_AUTHZID:
#ifdef LDAP_OPT_X_SASL_USERNAME
case LDAP_OPT_X_SASL_USERNAME:
#endif
#endif
/* String-valued options */
if (self) LDAP_BEGIN_ALLOW_THREADS(self);
res = ldap_get_option(ld, option, &strval);
if (self) LDAP_END_ALLOW_THREADS(self);
if (res != LDAP_OPT_SUCCESS)
return option_error(res, "ldap_get_option");
if (strval == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
v = PyString_FromString(strval);
ldap_memfree(strval);
return v;
case LDAP_OPT_TIMEOUT:
case LDAP_OPT_NETWORK_TIMEOUT:
/* Double-valued timeval options */
if (self) LDAP_BEGIN_ALLOW_THREADS(self);
res = ldap_get_option(ld, option, &tv);
if (self) LDAP_END_ALLOW_THREADS(self);
if (res != LDAP_OPT_SUCCESS)
return option_error(res, "ldap_get_option");
if (tv == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
v = PyFloat_FromDouble(
(double) tv->tv_sec + ( (double) tv->tv_usec / 1000000.0 )
);
ldap_memfree(tv);
return v;
case LDAP_OPT_SERVER_CONTROLS:
case LDAP_OPT_CLIENT_CONTROLS:
if (self) LDAP_BEGIN_ALLOW_THREADS(self);
res = ldap_get_option(ld, option, &lcs);
if (self) LDAP_END_ALLOW_THREADS(self);
if (res != LDAP_OPT_SUCCESS)
return option_error(res, "ldap_get_option");
if (lcs == NULL)
return PyList_New(0);
/* Get the number of controls */
num_controls = 0;
while (lcs[num_controls])
num_controls++;
/* We'll build a list of controls, with each control a tuple */
v = PyList_New(num_controls);
for (i = 0; i < num_controls; i++) {
lc = lcs[i];
tup = Py_BuildValue("(sbs)",
lc->ldctl_oid,
lc->ldctl_iscritical,
lc->ldctl_value.bv_val);
PyList_SET_ITEM(v, i, tup);
}
ldap_controls_free(lcs);
return v;
default:
PyErr_Format(PyExc_ValueError, "unknown option %d", option);
return NULL;
}
}
python-ldap-2.4.10/Modules/errors.c 0000644 0000764 0000144 00000013263 11704305353 017720 0 ustar michael users 0000000 0000000 /*
* errors that arise from ldap use
* Most errors become their own exception
* See http://www.python-ldap.org/ for details.
* $Id: errors.c,v 1.23 2012/01/11 10:04:48 stroeder Exp $ */
#include "common.h"
#include "errors.h"
/* the base exception class */
PyObject*
LDAPexception_class;
/* list of error objects */
#define LDAP_ERROR_MIN LDAP_REFERRAL_LIMIT_EXCEEDED
#ifdef LDAP_PROXIED_AUTHORIZATION_DENIED
#define LDAP_ERROR_MAX LDAP_PROXIED_AUTHORIZATION_DENIED
#else
#ifdef LDAP_ASSERTION_FAILED
#define LDAP_ERROR_MAX LDAP_ASSERTION_FAILED
#else
#define LDAP_ERROR_MAX LDAP_OTHER
#endif
#endif
#define LDAP_ERROR_OFFSET -LDAP_ERROR_MIN
static PyObject* errobjects[ LDAP_ERROR_MAX-LDAP_ERROR_MIN+1 ];
/* Convert a bare LDAP error number into an exception */
PyObject*
LDAPerr(int errnum)
{
if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX)
PyErr_SetNone(errobjects[errnum+LDAP_ERROR_OFFSET]);
else
PyErr_SetObject(LDAPexception_class,
Py_BuildValue("{s:i}", "errnum", errnum));
return NULL;
}
/* Convert an LDAP error into an informative python exception */
PyObject*
LDAPerror( LDAP *l, char *msg )
{
if (l == NULL) {
PyErr_SetFromErrno( LDAPexception_class );
return NULL;
}
else {
int errnum, opt_errnum;
PyObject *errobj;
PyObject *info;
PyObject *str;
char *matched, *error;
opt_errnum = ldap_get_option(l, LDAP_OPT_ERROR_NUMBER, &errnum);
if (opt_errnum != LDAP_OPT_SUCCESS)
errnum = opt_errnum;
if (errnum == LDAP_NO_MEMORY)
return PyErr_NoMemory();
if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX)
errobj = errobjects[errnum+LDAP_ERROR_OFFSET];
else
errobj = LDAPexception_class;
info = PyDict_New();
if (info == NULL)
return NULL;
str = PyString_FromString(ldap_err2string(errnum));
if (str)
PyDict_SetItemString( info, "desc", str );
Py_XDECREF(str);
if (ldap_get_option(l, LDAP_OPT_MATCHED_DN, &matched) >= 0
&& matched != NULL) {
if (*matched != '\0') {
str = PyString_FromString(matched);
if (str)
PyDict_SetItemString( info, "matched", str );
Py_XDECREF(str);
}
ldap_memfree(matched);
}
if (errnum == LDAP_REFERRAL) {
str = PyString_FromString(msg);
if (str)
PyDict_SetItemString( info, "info", str );
Py_XDECREF(str);
} else if (ldap_get_option(l, LDAP_OPT_ERROR_STRING, &error) >= 0
&& error != NULL) {
if (error != '\0') {
str = PyString_FromString(error);
if (str)
PyDict_SetItemString( info, "info", str );
Py_XDECREF(str);
}
ldap_memfree(error);
}
PyErr_SetObject( errobj, info );
Py_DECREF(info);
return NULL;
}
}
/* initialisation */
void
LDAPinit_errors( PyObject*d ) {
/* create the base exception class */
LDAPexception_class = PyErr_NewException("ldap.LDAPError",
NULL,
NULL);
PyDict_SetItemString( d, "LDAPError", LDAPexception_class );
/* XXX - backward compatibility with pre-1.8 */
PyDict_SetItemString( d, "error", LDAPexception_class );
/* create each LDAP error object */
# define seterrobj2(n,o) \
PyDict_SetItemString( d, #n, (errobjects[LDAP_##n+LDAP_ERROR_OFFSET] = o) )
# define seterrobj(n) { \
PyObject *e = PyErr_NewException("ldap." #n, \
LDAPexception_class, NULL); \
seterrobj2(n, e); \
Py_INCREF(e); \
}
seterrobj(ADMINLIMIT_EXCEEDED);
seterrobj(AFFECTS_MULTIPLE_DSAS);
seterrobj(ALIAS_DEREF_PROBLEM);
seterrobj(ALIAS_PROBLEM);
seterrobj(ALREADY_EXISTS);
seterrobj(AUTH_UNKNOWN);
seterrobj(BUSY);
seterrobj(CLIENT_LOOP);
seterrobj(COMPARE_FALSE);
seterrobj(COMPARE_TRUE);
seterrobj(CONFIDENTIALITY_REQUIRED);
seterrobj(CONNECT_ERROR);
seterrobj(CONSTRAINT_VIOLATION);
seterrobj(CONTROL_NOT_FOUND);
seterrobj(DECODING_ERROR);
seterrobj(ENCODING_ERROR);
seterrobj(FILTER_ERROR);
seterrobj(INAPPROPRIATE_AUTH);
seterrobj(INAPPROPRIATE_MATCHING);
seterrobj(INSUFFICIENT_ACCESS);
seterrobj(INVALID_CREDENTIALS);
seterrobj(INVALID_DN_SYNTAX);
seterrobj(INVALID_SYNTAX);
seterrobj(IS_LEAF);
seterrobj(LOCAL_ERROR);
seterrobj(LOOP_DETECT);
seterrobj(MORE_RESULTS_TO_RETURN);
seterrobj(NAMING_VIOLATION);
seterrobj(NO_OBJECT_CLASS_MODS);
seterrobj(NOT_ALLOWED_ON_NONLEAF);
seterrobj(NOT_ALLOWED_ON_RDN);
seterrobj(NOT_SUPPORTED);
seterrobj(NO_MEMORY);
seterrobj(NO_OBJECT_CLASS_MODS);
seterrobj(NO_RESULTS_RETURNED);
seterrobj(NO_SUCH_ATTRIBUTE);
seterrobj(NO_SUCH_OBJECT);
seterrobj(OBJECT_CLASS_VIOLATION);
seterrobj(OPERATIONS_ERROR);
seterrobj(OTHER);
seterrobj(PARAM_ERROR);
seterrobj(PARTIAL_RESULTS);
seterrobj(PROTOCOL_ERROR);
seterrobj(REFERRAL);
seterrobj(REFERRAL_LIMIT_EXCEEDED);
seterrobj(RESULTS_TOO_LARGE);
seterrobj(SASL_BIND_IN_PROGRESS);
seterrobj(SERVER_DOWN);
seterrobj(SIZELIMIT_EXCEEDED);
seterrobj(STRONG_AUTH_NOT_SUPPORTED);
seterrobj(STRONG_AUTH_REQUIRED);
seterrobj(SUCCESS);
seterrobj(TIMELIMIT_EXCEEDED);
seterrobj(TIMEOUT);
seterrobj(TYPE_OR_VALUE_EXISTS);
seterrobj(UNAVAILABLE);
seterrobj(UNAVAILABLE_CRITICAL_EXTENSION);
seterrobj(UNDEFINED_TYPE);
seterrobj(UNWILLING_TO_PERFORM);
seterrobj(USER_CANCELLED);
#ifdef LDAP_API_FEATURE_CANCEL
seterrobj(CANCELLED);
seterrobj(NO_SUCH_OPERATION);
seterrobj(TOO_LATE);
seterrobj(CANNOT_CANCEL);
#endif
#ifdef LDAP_ASSERTION_FAILED
seterrobj(ASSERTION_FAILED);
#endif
#ifdef LDAP_PROXIED_AUTHORIZATION_DENIED
seterrobj(PROXIED_AUTHORIZATION_DENIED);
#endif
}
python-ldap-2.4.10/Modules/options.h 0000644 0000764 0000144 00000000531 11172071675 020104 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: options.h,v 1.4 2009/04/17 12:19:09 stroeder Exp $ */
int LDAP_optionval_by_name(const char *name);
int LDAP_set_option(LDAPObject *self, int option, PyObject *value);
PyObject *LDAP_get_option(LDAPObject *self, int option);
void set_timeval_from_double( struct timeval *tv, double d );
python-ldap-2.4.10/Modules/message.c 0000644 0000764 0000144 00000015365 11660514462 020041 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: message.c,v 1.19 2011/10/26 18:38:06 stroeder Exp $ */
#include "common.h"
#include "message.h"
#include "berval.h"
#include "errors.h"
#include "ldapcontrol.h"
#include "constants.h"
/*
* Converts an LDAP message into a Python structure.
*
* On success, returns a list of dictionaries.
* On failure, returns NULL, and sets an error.
*
* The message m is always freed, regardless of return value.
*
* If add_ctrls is non-zero, per-entry/referral/partial/intermediate
* controls will be added as a third item to each entry tuple
*
* If add_intermediates is non-zero, intermediate/partial results will
* be returned
*/
PyObject *
LDAPmessage_to_python(LDAP *ld, LDAPMessage *m, int add_ctrls, int add_intermediates)
{
/* we convert an LDAP message into a python structure.
* It is always a list of dictionaries.
* We always free m.
*/
PyObject *result, *pyctrls = 0;
LDAPMessage* entry;
LDAPControl **serverctrls = 0;
int rc;
result = PyList_New(0);
if (result == NULL) {
ldap_msgfree( m );
return NULL;
}
for(entry = ldap_first_entry(ld,m);
entry != NULL;
entry = ldap_next_entry(ld,entry))
{
char *dn;
char *attr;
BerElement *ber = NULL;
PyObject* entrytuple;
PyObject* attrdict;
dn = ldap_get_dn( ld, entry );
if (dn == NULL) {
Py_DECREF(result);
ldap_msgfree( m );
return LDAPerror( ld, "ldap_get_dn" );
}
attrdict = PyDict_New();
if (attrdict == NULL) {
Py_DECREF(result);
ldap_msgfree( m );
ldap_memfree(dn);
return NULL;
}
rc = ldap_get_entry_controls( ld, entry, &serverctrls );
if (rc) {
Py_DECREF(result);
ldap_msgfree( m );
ldap_memfree(dn);
return LDAPerror( ld, "ldap_get_entry_controls" );
}
/* convert serverctrls to list of tuples */
if ( ! ( pyctrls = LDAPControls_to_List( serverctrls ) ) ) {
int err = LDAP_NO_MEMORY;
ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
Py_DECREF(result);
ldap_msgfree( m );
ldap_memfree(dn);
ldap_controls_free(serverctrls);
return LDAPerror( ld, "LDAPControls_to_List" );
}
ldap_controls_free(serverctrls);
/* Fill attrdict with lists */
for( attr = ldap_first_attribute( ld, entry, &ber );
attr != NULL;
attr = ldap_next_attribute( ld, entry, ber )
) {
PyObject* valuelist;
struct berval ** bvals =
ldap_get_values_len( ld, entry, attr );
/* Find which list to append to */
if ( PyMapping_HasKeyString( attrdict, attr ) ) {
valuelist = PyMapping_GetItemString( attrdict, attr );
} else {
valuelist = PyList_New(0);
if (valuelist != NULL && PyMapping_SetItemString(attrdict,
attr, valuelist) == -1) {
Py_DECREF(valuelist);
valuelist = NULL; /* catch error later */
}
}
if (valuelist == NULL) {
Py_DECREF(attrdict);
Py_DECREF(result);
if (ber != NULL)
ber_free(ber, 0);
ldap_msgfree( m );
ldap_memfree(attr);
ldap_memfree(dn);
Py_XDECREF(pyctrls);
return NULL;
}
if (bvals != NULL) {
Py_ssize_t i;
for (i=0; bvals[i]; i++) {
PyObject *valuestr;
valuestr = LDAPberval_to_object(bvals[i]);
if (PyList_Append( valuelist, valuestr ) == -1) {
Py_DECREF(attrdict);
Py_DECREF(result);
Py_DECREF(valuestr);
Py_DECREF(valuelist);
if (ber != NULL)
ber_free(ber, 0);
ldap_msgfree( m );
ldap_memfree(attr);
ldap_memfree(dn);
Py_XDECREF(pyctrls);
return NULL;
}
Py_DECREF(valuestr);
}
ldap_value_free_len(bvals);
}
Py_DECREF( valuelist );
ldap_memfree(attr);
}
if (add_ctrls) {
entrytuple = Py_BuildValue("(sOO)", dn, attrdict, pyctrls);
} else {
entrytuple = Py_BuildValue("(sO)", dn, attrdict);
}
ldap_memfree(dn);
Py_DECREF(attrdict);
Py_XDECREF(pyctrls);
PyList_Append(result, entrytuple);
Py_DECREF(entrytuple);
if (ber != NULL)
ber_free(ber, 0);
}
for(entry = ldap_first_reference(ld,m);
entry != NULL;
entry = ldap_next_reference(ld,entry))
{
char **refs = NULL;
PyObject* entrytuple;
PyObject* reflist = PyList_New(0);
if (reflist == NULL) {
Py_DECREF(result);
ldap_msgfree( m );
return NULL;
}
if (ldap_parse_reference(ld, entry, &refs, &serverctrls, 0) != LDAP_SUCCESS) {
Py_DECREF(reflist);
Py_DECREF(result);
ldap_msgfree( m );
return LDAPerror( ld, "ldap_parse_reference" );
}
/* convert serverctrls to list of tuples */
if ( ! ( pyctrls = LDAPControls_to_List( serverctrls ) ) ) {
int err = LDAP_NO_MEMORY;
ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
Py_DECREF(reflist);
Py_DECREF(result);
ldap_msgfree( m );
ldap_controls_free(serverctrls);
return LDAPerror( ld, "LDAPControls_to_List" );
}
ldap_controls_free(serverctrls);
if (refs) {
Py_ssize_t i;
for (i=0; refs[i] != NULL; i++) {
PyObject *refstr = PyString_FromString(refs[i]);
PyList_Append(reflist, refstr);
Py_DECREF(refstr);
}
ber_memvfree( (void **) refs );
}
if (add_ctrls) {
entrytuple = Py_BuildValue("(sOO)", NULL, reflist, pyctrls);
} else {
entrytuple = Py_BuildValue("(sO)", NULL, reflist);
}
Py_DECREF(reflist);
Py_XDECREF(pyctrls);
PyList_Append(result, entrytuple);
Py_DECREF(entrytuple);
}
if (add_intermediates) {
for(entry = ldap_first_message(ld,m);
entry != NULL;
entry = ldap_next_message(ld,entry))
{
/* list of tuples */
/* each tuple is OID, Berval, controllist */
if ( LDAP_RES_INTERMEDIATE == ldap_msgtype( entry ) ) {
PyObject* valtuple;
PyObject *valuestr;
char *retoid = 0;
struct berval *retdata = 0;
if (ldap_parse_intermediate( ld, entry, &retoid, &retdata, &serverctrls, 0 ) != LDAP_SUCCESS) {
Py_DECREF(result);
ldap_msgfree( m );
return LDAPerror( ld, "ldap_parse_intermediate" );
}
/* convert serverctrls to list of tuples */
if ( ! ( pyctrls = LDAPControls_to_List( serverctrls ) ) ) {
int err = LDAP_NO_MEMORY;
ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
Py_DECREF(result);
ldap_msgfree( m );
ldap_controls_free(serverctrls);
ldap_memfree( retoid );
ber_bvfree( retdata );
return LDAPerror( ld, "LDAPControls_to_List" );
}
ldap_controls_free(serverctrls);
valuestr = LDAPberval_to_object(retdata);
ber_bvfree( retdata );
valtuple = Py_BuildValue("(sOO)", retoid,
valuestr ? valuestr : Py_None,
pyctrls);
ldap_memfree( retoid );
Py_DECREF(valuestr);
Py_XDECREF(pyctrls);
PyList_Append(result, valtuple);
Py_DECREF(valtuple);
}
}
}
ldap_msgfree( m );
return result;
}
python-ldap-2.4.10/Modules/constants.h 0000644 0000764 0000144 00000001110 11172071675 020417 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: constants.h,v 1.6 2009/04/17 12:19:09 stroeder Exp $ */
#ifndef __h_constants_
#define __h_constants_
#include "common.h"
extern void LDAPinit_constants( PyObject* d );
extern PyObject* LDAPconstant( int );
#ifndef LDAP_CONTROL_PAGE_OID
#define LDAP_CONTROL_PAGE_OID "1.2.840.113556.1.4.319"
#endif /* !LDAP_CONTROL_PAGE_OID */
#ifndef LDAP_CONTROL_VALUESRETURNFILTER
#define LDAP_CONTROL_VALUESRETURNFILTER "1.2.826.0.1.3344810.2.3" /* RFC 3876 */
#endif /* !LDAP_CONTROL_VALUESRETURNFILTER */
#endif /* __h_constants_ */
python-ldap-2.4.10/Modules/functions.c 0000644 0000764 0000144 00000006231 11242162011 020376 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: functions.c,v 1.27 2009/08/17 05:00:57 leonard Exp $ */
#include "common.h"
#include "functions.h"
#include "LDAPObject.h"
#include "berval.h"
#include "errors.h"
#include "options.h"
/* ldap_initialize */
static PyObject*
l_ldap_initialize(PyObject* unused, PyObject *args)
{
char *uri;
LDAP *ld = NULL;
int ret;
if (!PyArg_ParseTuple(args, "s", &uri))
return NULL;
Py_BEGIN_ALLOW_THREADS
ret = ldap_initialize(&ld, uri);
Py_END_ALLOW_THREADS
if (ret != LDAP_SUCCESS)
return LDAPerror(ld, "ldap_initialize");
return (PyObject*)newLDAPObject(ld);
}
/* ldap_str2dn */
static PyObject*
l_ldap_str2dn( PyObject* unused, PyObject *args )
{
struct berval str;
LDAPDN dn;
int flags = 0;
PyObject *result = NULL, *tmp;
int res, i, j;
Py_ssize_t str_len;
/*
* From a DN string such as "a=b,c=d;e=f", build
* a list-equivalent of AVA structures; namely:
* ((('a','b',1),('c','d',1)),(('e','f',1),))
* The integers are a bit combination of the AVA_* flags
*/
if (!PyArg_ParseTuple( args, "z#|i:str2dn",
&str.bv_val, &str_len, &flags ))
return NULL;
str.bv_len = (ber_len_t) str_len;
res = ldap_bv2dn(&str, &dn, flags);
if (res != LDAP_SUCCESS)
return LDAPerr(res);
tmp = PyList_New(0);
if (!tmp)
goto failed;
for (i = 0; dn[i]; i++) {
LDAPRDN rdn;
PyObject *rdnlist;
rdn = dn[i];
rdnlist = PyList_New(0);
if (!rdnlist)
goto failed;
if (PyList_Append(tmp, rdnlist) == -1) {
Py_DECREF(rdnlist);
goto failed;
}
for (j = 0; rdn[j]; j++) {
LDAPAVA *ava = rdn[j];
PyObject *tuple;
tuple = Py_BuildValue("(O&O&i)",
LDAPberval_to_object, &ava->la_attr,
LDAPberval_to_object, &ava->la_value,
ava->la_flags & ~(LDAP_AVA_FREE_ATTR|LDAP_AVA_FREE_VALUE));
if (!tuple) {
Py_DECREF(rdnlist);
goto failed;
}
if (PyList_Append(rdnlist, tuple) == -1) {
Py_DECREF(tuple);
goto failed;
}
Py_DECREF(tuple);
}
Py_DECREF(rdnlist);
}
result = tmp;
tmp = NULL;
failed:
Py_XDECREF(tmp);
ldap_dnfree(dn);
return result;
}
/* ldap_set_option (global options) */
static PyObject*
l_ldap_set_option(PyObject* self, PyObject *args)
{
PyObject *value;
int option;
if (!PyArg_ParseTuple(args, "iO:set_option", &option, &value))
return NULL;
if (!LDAP_set_option(NULL, option, value))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
/* ldap_get_option (global options) */
static PyObject*
l_ldap_get_option(PyObject* self, PyObject *args)
{
int option;
if (!PyArg_ParseTuple(args, "i:get_option", &option))
return NULL;
return LDAP_get_option(NULL, option);
}
/* methods */
static PyMethodDef methods[] = {
{ "initialize", (PyCFunction)l_ldap_initialize, METH_VARARGS },
{ "str2dn", (PyCFunction)l_ldap_str2dn, METH_VARARGS },
{ "set_option", (PyCFunction)l_ldap_set_option, METH_VARARGS },
{ "get_option", (PyCFunction)l_ldap_get_option, METH_VARARGS },
{ NULL, NULL }
};
/* initialisation */
void
LDAPinit_functions( PyObject* d ) {
LDAPadd_methods( d, methods );
}
python-ldap-2.4.10/Modules/berval.c 0000644 0000764 0000144 00000004667 11242133473 017666 0 ustar michael users 0000000 0000000 /* See http://www.python-ldap.org/ for details.
* $Id: berval.c,v 1.1 2009/08/17 01:49:47 leonard Exp $ */
#include "common.h"
#include "berval.h"
/*
* Converts a Python object into a data for a berval structure.
*
* New memory is allocated, and the content of the object is copied into it.
* Then the (pre-existing) berval structure's field are filled in with pointer
* and length data.
*
* The source object must implement the buffer interface, or be None.
* If the source object is None, bv->bv_val will be set to NULL and bv_len to 0.
* Otherwise, bv->bv_val will be non-NULL (even for zero-length data).
* This allows the caller to distinguish a None argument as something special.
*
* Returns 0 on failure, leaving *bv unchanged, and setting an error.
* Returns 1 on success: the berval must be freed with LDAPberval_release().
*/
int
LDAPberval_from_object(PyObject *obj, struct berval *bv)
{
const void *data;
char *datacp;
Py_ssize_t len;
if (PyNone_Check(obj)) {
bv->bv_len = 0;
bv->bv_val = NULL;
return 1;
}
if (!PyObject_AsReadBuffer(obj, &data, &len))
return 0;
datacp = PyMem_MALLOC(len ? len : 1);
if (!datacp) {
PyErr_NoMemory();
return 0;
}
memcpy(datacp, data, len);
bv->bv_len = len;
bv->bv_val = datacp;
return 1;
}
/*
* Returns true if the object could be used to initialize a berval structure
* with LDAPberval_from_object()
*/
int
LDAPberval_from_object_check(PyObject *obj)
{
return PyNone_Check(obj) ||
PyObject_CheckReadBuffer(obj);
}
/*
* Releases memory allocated by LDAPberval_from_object().
* Has no effect if the berval pointer is NULL or the berval data is NULL.
*/
void
LDAPberval_release(struct berval *bv) {
if (bv && bv->bv_val) {
PyMem_FREE(bv->bv_val);
bv->bv_len = 0;
bv->bv_val = NULL;
}
}
/*
* Copies out the data from a berval, and returns it as a new Python object,
* Returns None if the berval pointer is NULL.
*
* Note that this function is not the exact inverse of LDAPberval_from_object
* with regards to the NULL/None conversion.
*
* Returns a new Python object on success, or NULL on failure.
*/
PyObject *
LDAPberval_to_object(const struct berval *bv)
{
PyObject *ret = NULL;
if (!bv) {
ret = Py_None;
Py_INCREF(ret);
}
else {
ret = PyString_FromStringAndSize(bv->bv_val, bv->bv_len);
}
return ret;
}
python-ldap-2.4.10/.cvsignore 0000644 0000764 0000144 00000000051 07507671454 016635 0 ustar michael users 0000000 0000000 build
dist
MANIFEST
*.pyc
*.pyo
*.bck
*~
python-ldap-2.4.10/TODO 0000644 0000764 0000144 00000002146 11764172556 015333 0 ustar michael users 0000000 0000000 *** List of things to-do in no particular order ***
General:
- Define common Python style license for all modules
- Support Python 3.2+
Modules/
- Specific support for more controls
- VLV control
- server-side sorting control
- Wrap libldif as faster drop-in replacement for module ldif?
- Attach response controls to LDAPError instances to deliver the
controls to the calling application in case of an error
- Attach more useful information to LDAPError instances, e.g. the filter used
when doing a search in case of ldap.FILTER_ERROR etc.
Lib/
- Unicode support for DNs, filter strings, etc. but not entry attributes!
(Everybody asking for the latter should check the mailing list archive first.)
- Caching of search requests for each LDAPObject instance
- LDIF parser for replication logs and change records
- DSMLv2 support
Tests/
- Clean up and finish the mess of small test scripts started.
- Create a test script that exercises everything with a server
holding the BLITS test data set
------------------------------------------------------------------
$Id: TODO,v 1.38 2012/01/25 19:24:40 stroeder Exp $
python-ldap-2.4.10/INSTALL 0000644 0000764 0000144 00000001400 11545721637 015661 0 ustar michael users 0000000 0000000 ------------------------------
Installing python-ldap
------------------------------
Prerequisites:
Required:
- Python 2.3 or newer (see http://www.python.org)
- OpenLDAP 2.4.11+ client libs (see http://www.openldap.org)
It is not possible and not supported
by the python-ldap project to build with prior versions.
Optional dependencies of OpenLDAP libs:
- Cyrus SASL 2.1.x or newer (see http://asg.web.cmu.edu/sasl/sasl-library.html)
- OpenSSL 0.9.7 or newer (see http://www.openssl.org)
- MIT Kerberos or heimdal libs
Quick build instructions:
edit setup.cfg (see Build/ for platform-specific examples)
python setup.py build
python setup.py install
$Id: INSTALL,v 1.10 2011/04/02 22:30:55 stroeder Exp $
python-ldap-2.4.10/CHANGES 0000644 0000764 0000144 00000077431 11764172556 015647 0 ustar michael users 0000000 0000000 ----------------------------------------------------------------
Released 2.4.10 2012-06-07
Changes since 2.4.9:
Lib/
* ldapobject.ReconnectLDAPObject.reconnect() now preserves
order of options set with LDAPObject.set_option before.
This is needed e.g. for setting connection-specific TLS options.
Demo/
* Better version of Demo/pyasn1/syncrepl.py
(thanks to Ben Cooksley)
----------------------------------------------------------------
Released 2.4.9 2012-03-14
Changes since 2.4.8:
Lib/
* ldapobject.ReconnectLDAPObject.reconnect() now does kind of
an internal locking to pause other threads while reconnecting
is pending.
* Changes to bind- and startTLS-related operation methods of
class ReconnectLDAPObject for more robustness
* New constant ldap.OPT_NAMES_DICT contains mapping from
integer to variable name for all option-related constants.
----------------------------------------------------------------
Released 2.4.8 2012-02-21
Changes since 2.4.7:
Lib/
* Fixed overzealous check for non-unique NAMEs in
ldap.schema.subentry.SubSchema.__init__()
* Fixed typos in control decoding method
ldap.controls.simple.OctetStringInteger.decodeControlValue()
* Added experimental support for draft-vchu-ldap-pwd-policy
----------------------------------------------------------------
Released 2.4.7 2012-12-19
Changes since 2.4.6:
Lib/
* Separate classes for request/response controls for RFC 3829
* Fixed ldap.schema.subentry.SubSchema.attribute_types() to
also eliminate double attribute types in MAY clause of
DIT content rule
Modules/
* Fixed memory leak (thanks to David Malcolm)
----------------------------------------------------------------
Released 2.4.6 2011-11-27
Changes since 2.4.5:
Lib/
* ldap.controls.ppolicy:
Another fix for decoding the password policy response control
----------------------------------------------------------------
Released 2.4.5 2011-11-25
Changes since 2.4.4:
Installation:
* defines for SASL and SSL in setup.cfg to be more friendly to
Python setup tools (easy_install)
Lib/
* Fixed typo in ldap.functions._ldap_function_call() which
always released ldap._ldap_module_lock instead of local lock
* ldap.controls.ppolicy:
Fixed decoding the password policy response control
Demo/
* Demo script for ldap.controls.ppolicy
----------------------------------------------------------------
Released 2.4.4 2011-10-26
Changes since 2.4.3:
Modules/
* Format intermediate messages as 3-tuples instead of
4-tuples to match the format of other response messages.
(thanks to Chris Mikkelson)
* Fixes for memory leaks (thanks to Chris Mikkelson)
Lib/
* New experimental(!) sub-module ldap.syncrepl implementing syncrepl
consumer (see RFC 4533, thanks to Chris Mikkelson)
Doc/
* Cleaned up rst files
* Added missing classes
----------------------------------------------------------------
Released 2.4.3 2011-07-23
Changes since 2.4.2:
Lib/
* Mostly corrected/updated __doc__ strings
Doc/
* Corrected rst files
* Added missing modules, functions, classes, methods, parameters etc.
at least as auto-generated doc
----------------------------------------------------------------
Released 2.4.2 2011-07-21
Changes since 2.4.1:
Lib/
Logging:
* pprint.pformat() is now used when writing method/function
arguments to the trace log
ldap.schema.subentry:
* SubSchema.__init__() now has new key-word argument check_uniqueness
which enables checking whether OIDs are unique in the subschema subentry
* Code-cleaning: consequent use of method SubSchema.getoid() instead of
accessing SubSchema.name2oid directly.
* SubSchema.getoid() and SubSchema.getoid() now have key-word argument
raise_keyerror=0 and raise KeyError with appropriate description.
----------------------------------------------------------------
Released 2.4.1 2011-07-05
Changes since 2.4.0:
Modules:
* New LDAP option OPT_X_TLS_PACKAGE available in OpenLDAP 2.4.26+
to determine the name of the SSL/TLS package OpenLDAP was
built with
Lib/
* ldap.modlist.modifyModlist(): New key-word argument
case_ignore_attr_types used to define attribute types for which
comparison of old and new values should be case-insensitive
* Minor changes to which data is sent to debug output for various
trace levels
* Now tag [1] is used in ldap.extop.dds.RefreshResponse in
compliance with RFC 2589 (fix available for OpenLDAP ITS#6886)
* New sub-module ldap.controls.sessiontrack implements request control
as described in draft-wahl-ldap-session (needs pyasn1_modules)
----------------------------------------------------------------
Released 2.4.0 2011-06-02
Changes since 2.3.13:
* OpenLDAP 2.4.11+ required to build
* Support for extracting LDAPv3 extended controls in
LDAP_RES_SEARCH_ENTRY responses
(see SF#2829057, thanks to Rich)
* Generic support for LDAPv3 extended operations (thanks to Rich)
Lib/
* new class API in ldap.controls, not backwards-compatible!
* new sub-modules for ldap.controls, some require pyasn1 and pyasn1_modules
* New methods LDAPObject.result4() and LDAPObject.extop_result()
* New (optional) class ldap.controls.AssertionControl
* New helper module ldap.logger contains file-like object which
sends trace messages to logging.log()
* Removed non-functional method LDAPObject.set_cache_options()
* Removed unused dictionary ldap.controls.knownLDAPControls
Modules/
* ldapcontrol.c: Fixed encode_assertion_control() and function is no longer
hidden behind ifdef-statement
----------------------------------------------------------------
Released 2.3.13 2011-02-19
Changes since 2.3.12:
Modules/
* Correct #ifdef-statement for LDAP_OPT_X_TLS_CRLFILE in
constants.c fixes build with older OpenLDAP libs
* Support for LDAP_OPT_DEFBASE (see SF#3072016, thanks to Johannes)
----------------------------------------------------------------
Released 2.3.12 2010-08-05
Changes since 2.3.11:
Lib/
* Removed tabs from various modules to make things work with python -tt.
* Quick fix to ldif.is_dn() to let multi-valued RDNs pass as valid.
Is too liberal in some corner-cases though...
* Fix to ldif.is_dn() to allow dashes in attribute type (see SF#3020292)
* ldap.open() now outputs a deprecation warning
* module-wide locking is now limited to calling _ldap.initialize().
Still ldap.functions._ldap_function_call() is used to wrap all
calls for writing debug log.
Modules/
* New LDAP options available in OpenLDAP 2.4.18+ supported in
LDAPObject.get/set_option():
ldap.OPT_X_KEEPALIVE_IDLE, ldap.OPT_X_KEEPALIVE_PROBES,
ldap.OPT_X_KEEPALIVE_INTERVAL,
ldap.OPT_X_TLS_CRLCHECK, ldap.OPT_X_TLS_CRLFILE
Doc/
* Various small updates/improvements
----------------------------------------------------------------
Released 2.3.11 2010-02-26
Changes since 2.3.10:
Lib/
* Fixed LDAP URL parsing with four ? but no real extensions
* ldap.ldapobject.LDAPObject.rename_s() now also accepts arguments
serverctrls and clientctrls
* Removed untested and undocumented class ldap.ldapobject.SmartLDAPObject
* Removed broken method ldap.ldapobject.LDAPObject.manage_dsa_it()
Modules/
* Make use of LDAP_OPT_X_TLS_NEWCTX only if available in
OpenLDAP libs used for the build
* Fixed #ifdef-statements for OPT_X_TLS_PROTOCOL_MIN
Doc/
* Some updates and corrections regarding description of use of
LDAPv3 controls
* Some more descriptions for constants
* Removed comments related to old LaTeX-based documentation system
----------------------------------------------------------------
Released 2.3.10 2009-10-30
Changes since 2.3.9:
Lib/
* The diagnosticMessage returned by a server is written to the trace
output also for successful operations.
* Fixed handling of LDAP URL extensions with implicit value None which are
mapped to class attributes of LDAPUrl.
* Fixed handling of LDAP URLs with ? being part of extensions.
* Fixed exceptions raised by get_option/set_option (SF#1964993)
* ldap.functions: Fixed import trace-related variables from base-module ldap
* Fixed ldap.resiter missing in RPMs built with python setup.py bdist_rpm
* Fix in class ldap.schema.models.SchemaElement:
repr() was liberally used in methods key_attr() and key_list() to enclose
values in quotes.
Modules/
* Changed internal API List_to_LDAPControls() to LDAPControls_from_object()
* Supported was added for retrieving the SASL username during SASL bind with
ldap_get_option(LDAP_OPT_X_SASL_USERNAME) if available in libldap.
* New LDAP option constant ldap.OPT_X_TLS_NEWCTX supported
in LDAPObject.set_option()
* New LDAP option constants supported in LDAPObject.get/set_option():
ldap.OPT_X_TLS_PROTOCOL_MIN, ldap.OPT_CONNECT_ASYNC, ldap.OPT_X_TLS_DHFILE
* Fixed setting _ldap.OPT_ON and _ldap.OPT_OFF
* l_ldap_result3(): controls are now parsed for all response types (SF#2829057)
Doc/
* Added example for ldap.resiter
----------------------------------------------------------------
Released 2.3.9 2009-07-26
Changes since 2.3.8:
Lib/
* All modules (ldap, ldif, dsml and ldapurl) have common version number now
* Non-exported function ldif.needs_base64() was abandoned and is now
implemented as method LDIFWriter._needs_base64_encoding().
This allows sub-classes of LDIFWriter to implement determining whether
attribute values have to be base64-encoded in a different manner and is
the same approach like in class dsml.DSMLWriter.
* LDAPUrlExtension._parse() now gracefully handles LDAP URL extensions
without explicit exvalue as being set with implicit value None.
Modules/
* New LDAP option constant ldap.OPT_X_SASL_NOCANON supported
in LDAPObject.get/set_option()
----------------------------------------------------------------
Released 2.3.8 2009-04-30
Changes since 2.3.7:
Lib/
* ldap.schema.models: More fault-tolerant parsing of SYNTAX in
AttributeTypeDescription
* ldap.schema.tokenizer.split_tokens():
More tolerant parsing of items separated only with a DOLLAR without
surrounding white-spaces (because WSP is declared as zero or more spaces
in RFC 4512)
----------------------------------------------------------------
Released 2.3.7 2009-04-09
Changes since 2.3.6:
Lib/
* urllib.quote() is now used in LDAPUrlExtension.unparse() to quote
all special URL characters in extension values
Modules/
* Fixed ldapcontrol.c not to raise ldap.ENCODING_ERROR in
function encode_rfc2696() on 64-bit systems
* Fixed seg fault if error code in a LDAP response was outside
the known error codes and could not be mapped to a specific
exception class (thanks to Sean)
* errors.c: LDAP_ERROR_MAX set to LDAP_PROXIED_AUTHORIZATION_DENIED
if available in OpenLDAP header
* new exception class ldap.PROXIED_AUTHORIZATION_DENIED
if available in OpenLDAP header
* Fixed functions.c not to raise ldap.ENCODING_ERROR in
function l_ldap_str2dn() on 64-bit systems (see SF#2725356)
----------------------------------------------------------------
Released 2.3.6 2009-02-22
Changes since 2.3.5:
Lib/
* Importing ldap.str2dn() which directly imported _ldap.str2dn()
is prohibited now (see SF#2181141)
Modules/
* get_option(): Added support for reading more SASL options.
(OPT_X_SASL_MECH, OPT_X_SASL_REALM, OPT_X_SASL_AUTHCID and
OPT_X_SASL_AUTHZID)
* Added some explicit type casts to fix issues while building
with SunStudio
* Fixed compiling issue with GCC 4.4
(see SF#2555793, thanks to Matej and Martin)
Doc/
* Clarified not to use ldap_get_dn() directly
* Fixed description of ldap.SASL_AVAIL and ldap.TLS_AVAIL
(see SF#2555804, thanks to Matej and Martin)
----------------------------------------------------------------
Released 2.3.5 2008-07-06
Changes since 2.3.4:
Lib/
* Fixed methods ldap.cidict.__contains__() and
ldap.schema.models.Entry.__contains__()
* FWIW method LDAPObject.cancel_s() returns a result now
* Fixed ldap.schema.models.NameForm: Class attribute oc is now
of type string, not tuple to be compliant with RFC 4512
----------------------------------------------------------------
Released 2.3.4 2008-03-29
Changes since 2.3.3:
Modules/
* Fixed seg fault when calling LDAPObject.get_option()
(see SF#1926507, thanks to Matej)
----------------------------------------------------------------
Released 2.3.3 2008-03-26
Changes since 2.3.2:
Fixed backward-compability when building with OpenLDAP 2.3.x libs.
----------------------------------------------------------------
Released 2.3.2 2008-03-26
Changes since 2.3.1:
Lib/
* ldap.dn.escape_dn_chars() now really adheres to
RFC 4514 section 2.4 by escaping null characters and a
space occurring at the beginning of the string
* New method ldap.cidict.cidict.__contains__()
* ldap.dn.explode_dn() and ldap.dn.explode_rdn()
have a new optional key-word argument flags which is
passed to ldap.dn.str2dn().
Modules/
* Removed unused OPT_PRIVATE_EXTENSION_BASE from constants.c
Doc/
* Various additions, updates, polishing (thanks to James).
----------------------------------------------------------------
Released 2.3.1 2007-07-25
Changes since 2.3.0:
* Support for setuptools (building .egg, thanks to Torsten)
* Support for matched values control (RFC 3876, thanks to Andreas)
Lib/
* Fixed ldif (see SF#1709111, thanks to Dmitry)
* ldap.schema.models:
SUP now separated by $ (method __str__() of classes
AttributeType, ObjectClass and DITStructureRule, thanks to Stefan)
Modules/
* Added constant MOD_INCREMENT to support
modify+increment extension (see RFC 4525, thanks to Andreas)
----------------------------------------------------------------
Released 2.3.0 2007-03-27
Changes since 2.2.1:
* OpenLDAP 2.3+ required now to build.
* Added support for Cancel operation ext. op. if supported
in OpenLDAP API of the libs used for the build.
Modules/
* Removed deprecated code for setting options by name
* Added l_ldap_cancel()
* Some modifications related to PEP 353 for
Python 2.5 on 64-bit platforms (see SF#1467529, thanks to Matej)
* Added new function l_ldap_str2dn(), removed functions
l_ldap_explode_dn() and l_ldap_explode_rdn()
(see SF#1657848, thanks to David)
Lib/
* Added method ldapobject.LDAPObject.cancel()
* ldap.schema.subentry.urlfetch() now can do non-anonymous
simple bind if the LDAP URL provided contains extensions
'bindname' and 'X-BINDPW'. (see SF#1589206)
* ldap.filter.escape_filter_chars() has new a key-word argument
escape_mode now which defines which chars to be escaped
(see SF#1193271).
* Various important fixes to ldapobject.ReconnectLDAPObject
* Moved all DN-related functions to sub-module ldap.dn,
import them in ldap.functions for backward compability
* ldap.dn.explode_dn() and ldap.dn.explode_rdn() use the new
wrapper function ldap.dn.str2dn() (related to SF#1657848)
* changetype issue partially fixed (see SF#1683746)
----------------------------------------------------------------
Released 2.2.1 2006-11-15
Changes since 2.2.0:
Modules/
* Fix for Python 2.5 free(): invalid pointer (see SF#1575329)
* passwd() accepts None for arguments user, oldpw, newpw
(see SF#1440151)
Lib/
* ldif.LDIFWriter.unparse() now accepts instances of
derived dict and list classes (see SF#1489898)
----------------------------------------------------------------
Released 2.2.0 2006-04-10
Changes since 2.0.11:
* OpenLDAP 2.2+ required now to build.
Modules/
* Dropped all occurences of '#ifdef #LDAP_VENDOR_VERSION'.
* Fixed wrong tuple size in l_ldap_result3() (see SF#1368108)
* Fixed get_option(ldap.OPT_API_INFO) (see SF#1440165)
* Fixed memory leak in l_ldap_result3() when all=0
(see SF#1457325)
* Fixed memory leak in l_ldap_result3() in error cases
(see SF#1464085)
Lib/
* Fixed ldap.schema.models.DITStructureRule.__str__() to
separate SUP rule-ids with a single space instead of ' $ '
* Fixed ldap.async.Dict
* Added ldap.async.IndexedDict
* ldap.schema.subentry.SubSchema.attribute_types() has new
key-word argument ignore_dit_content_rule
----------------------------------------------------------------
Released 2.0.11 2005-11-07
Changes since 2.0.10:
Lib/
* Class ldap.ldapobject.LDAPObject:
Each method returns a result now
* Class ldap.ldapobject.ReconnectLDAPObject:
Some methods called the wrong methods of LDAPObject. Fixed.
* Added new class ldap.async.Dict
* Slightly cleaned up ldap.schema.subentry.attribute_types()
* New sub-module ldap.resiter which simply provides a mix-in
class for ldap.ldapobject.LDAPObject with a generator method
allresults().
Obviously this only works with Python 2.3+. And
it's still experimental.
----------------------------------------------------------------
Released 2.0.10 2005-09-23
Changes since 2.0.9:
Lib/
* Switched back to old implementation of
ldap.schema.tokenizer.split_tokens() since the new one
had a bug which deletes the spaces from DESC
* ldap.INSUFFICIENT_ACCESS is now ignored in
ldap.ldapobject.LDAPObject.search_subschemasubentry_s()
----------------------------------------------------------------
Released 2.0.9 2005-07-28
Changes since 2.0.8:
Modules/
* Removed __doc__ strings from ldapcontrol.c to "fix"
build problems with Python versions 2.2 and earlier.
----------------------------------------------------------------
Released 2.0.8 2005-06-22 at Linuxtag 2005, Karlsruhe, Germany
Changes since 2.0.7:
* Preliminary support for receiving LDAP controls added.
Contributor:
- Andreas Ames
Lib/
- Added classes in module ldif to ldif.__all__ to fix
from ldif import *
- Removed BitString syntax from
ldap.schema.models.NOT_HUMAN_READABLE_LDAP_SYNTAXES
since the LDAP encoding is in fact human-readable
- ldapurl.LDAPUrlExtension.unparse() outputs empty string
if LDAPUrlExtension.exvalue is None
- Added ldap.controls.SimplePagedResultsControl
----------------------------------------------------------------
Released 2.0.7 2005-04-29
Changes since 2.0.6:
* Added preliminary support for sending LDAP controls
with a request.
Contributors:
- Deepak Giridharagopal
- Ingo Steuwer
(Receiving controls in LDAP results still not supported.)
Modules:
* LDAPObject.c: removed l_ldap_manage_dsa_it()
* LDAPObject.c: Added missing #ifdef around l_ldap_passwd()
for compability with older OpenLDAP libs.
Lib/
* New algorithm in ldap.schema.tokenizer.split_tokens()
contributed by Wido Depping which is more robust
when parsing very broken schema elements
(e.g. Oracle's OID).
* Fixed argument list (position of timeout) when calling
LDAPObject.search_ext_s() from search_st() and search_s().
* LDAPObject.search_ext_s() correctly calls search_ext_s() now.
* Re-implemented LDAPObject.manage_dsa_it() without calling _ldap.
----------------------------------------------------------------
Released 2.0.6 2004-12-03
Changes since 2.0.5:
Lib/
* Added sub-module ldap.dn
* Added function ldap.dn.escape_dn_chars()
* Special check when implicitly setting SUP 'top' to
structural object classes without SUP defined to avoid
a loop in the super class chain.
----------------------------------------------------------------
Released 2.0.5 2004-11-11
Changes since 2.0.4:
Some small improvements for SASL:
The noisy output during SASL bind is avoided now. Interaction
with output on stderr can be enabled by the calling application
by explicitly defining SASL flags.
Removed obsolete directory Win32/.
Lib/
* Make sure that ldap.sasl.sasl.cb_value_dict is a dictionary
even when the caller passes in None to argument cb_value_dict
* Added new key-word arg sasl_flags to method
LDAPObject.sasl_interactive_bind_s()
Modules/
* l_ldap_sasl_interactive_bind_s():
New key-word arg sasl_flags passed to
ldap_sasl_interactive_bind_s()
----------------------------------------------------------------
Released 2.0.4 2004-10-27
Changes since 2.0.3:
Modules/
* Applied some fixes for 64-bit platforms to LDAPObject.c
* Constants ldap.TLS_AVAIL and ldap.SASL_AVAIL will indicate
whether python-ldap was built with support for SSL/TLS
and/or SASL
setup.py and Modules/
* Applied some fixes for building under Win32
----------------------------------------------------------------
Released 2.0.3 2004-10-06
Changes since 2.0.2:
* Added support for LDAP Password Modify Extended Operation
(see RFC 3062)
Demo/:
* Added passwd_ext_op.py
Modules/
* Added l_ldap_passwd() in LDAPObject.c
Lib/
* Added methods passwd() and passwd_s() to
ldap.ldapobject.LDAPObject
----------------------------------------------------------------
Released 2.0.2 2004-07-29
Changes since 2.0.1:
Modules/
* Fixed detecting appropriate OpenLDAP libs version for
determining whether ldap_whoami_s() is available or not.
This fixes build problems with OpenLDAP libs 2.1.0 up
to 2.1.12.
----------------------------------------------------------------
Released 2.0.1 2004-06-29
Changes since 2.0.0:
dsml:
* Fixed wrong exception message format string
ldap.schema.models:
* Fixed Entry.__delitem__() to delete really everything
when deleting an attribute dictionary item.
----------------------------------------------------------------
Released 2.0.0 2004-05-18
Changes since 2.0.0pre21:
ldif:
* Empty records are simply ignored in ldif.LDIFWriter.unparse()
Modules/
* New method result2() returns 3-tuple containing the msgid
of the outstanding operation.
ldap.ldapobject:
* New _ldap wrapper method LDAPObject.result2() (see above)
which is now used by LDAPObject.result().
----------------------------------------------------------------
Released 2.0.0pre21 2004-03-29
Changes since 2.0.0pre20:
setup.py:
* runtime_library_dirs is set
Modules/
* (Hopefully) fixed building with OpenLDAP 2.2 libs in errors.c
* Removed meaningless repr() function from LDAPObject.c
* Removed setting LDAP_OPT_PROTOCOL_VERSION in l_ldap_sasl_bind_s()
* Modified string handling via berval instead of *char
in l_ldap_compare_ext() makes it possible to compare attribute
values with null chars.
* Wrapped ldap_sasl_bind() for simple binds instead of ldap_bind()
since 1. the latter is marked deprecated and 2. ldap_sasl_bind()
allows password credentials with null chars.
* Removed unused sources linkedlist.c and linkedlist.h
* Function l_ldap_whoami_s() only added if built against
OpenLDAP 2.1.x+ libs (should preserve compability with 2.0 libs)
ldap.ldapobject:
* LDAPObject.bind() only allows simple binds since Kerberos V4
binds of LDAPv2 are not supported anymore. An assert statement
was added to make the coder aware of that.
* Renamed former LDAPObject.sasl_bind_s() to
LDAPObject.sasl_interactive_bind_s() since it wraps OpenLDAP's
ldap_sasl_interactive_bind_s()
----------------------------------------------------------------
Released 2.0.0pre20 2004-03-19
Changes since 2.0.0pre19:
Modules/
* Removed doc strings from functions.c
* Removed probably unused wrapper function l_ldap_dn2ufn() since
ldap_dn2ufn() is deprecated in OpenLDAP 2.1+
* Removed wrapper function l_ldap_is_ldap_url().
* Removed macro add_int_r() from constants.c since it caused
incompability issues with OpenLDAP 2.2 libs
(Warning: all result types are Integers now! Use the constants!)
* New wrapper function l_ldap_whoami_s()
ldap.ldapobject:
* New wrapper method LDAPObject.whoami_s()
ldap.functions:
* Removed is_ldap_url(). The more general function
ldapurl.isLDAPUrl() should be used instead.
ldap.sasl:
* Added class cram_md5 (for SASL mech CRAM-MD5)
ldap.async:
* Use constants for search result types (see note about
add_int_r() above).
----------------------------------------------------------------
Released 2.0.0pre19 2004-01-22
Changes since 2.0.0pre18:
Modules/
* LDAPObject.c:
Most deprecated functions of OpenLDAP C API are not used anymore.
* functions.c:
Removed unused default_ldap_port().
* constants.c:
Removed unused or silly constants
AUTH_KRBV4, AUTH_KRBV41, AUTH_KRBV42, URL_ERR_BADSCOPE, URL_ERR_MEM
* errors.c:
Fixed building with OpenLDAP 2.2.x
(errors caused by negative error constants in ldap.h)
ldap.ldapobject.LDAPObject:
* Removed unused wrapper methods uncache_entry(), uncache_request(),
url_search(), url_search_st() and url_search_s()
* New wrapper methods for all the _ext() methods in _ldap.LDAPObject.
ldap.modlist:
* Some performance optimizations and simplifications
in function modifyModlist()
----------------------------------------------------------------
Released 2.0.0pre18 2003-12-09
Changes since 2.0.0pre17:
ldap.ldapobject:
* Fixed missing ldap._ldap_function_call() in
ReconnectLDAPObject.reconnect()
----------------------------------------------------------------
Released 2.0.0pre17 2003-12-03
Changes since 2.0.0pre16:
ldap.functions:
* Fixed ImportError when running python -O
----------------------------------------------------------------
Released 2.0.0pre16 2003-12-02
Changes since 2.0.0pre15:
Modules/
* Removed definition of unused constant RES_EXTENDED_PARTIAL since
the corresponding symbol LDAP_RES_EXTENDED_PARTIAL seems to not
be available in OpenLDAP-HEAD (pre 2.2) anymore.
All in Lib/
* Fixed some subtle bugs/oddities mentioned by pychecker.
dsml:
* Renamed DSMLWriter._f to DSMLWriter._output_file
* Added wrapper method DSMLWriter.unparse() which simply
calls DSMLWriter.writeRecord()
ldap.ldapobject:
* Simplified LDAPObject.search_subschemasubentry_s()
ldap.functions:
* Moved ldap._ldap_function_call() into ldap.functions.
* apply() is not used anymore since it seems deprecated
ldap.async:
* Added class DSMLWriter
ldap.schema:
* Removed unused key-word argument strict from
ldap.schema.subentry.SubSchema.attribute_types()
* Fixed backward compability issue (for Python prior to 2.2) in
ldap.schema.subentry.SubSchema.listall()
----------------------------------------------------------------
Released 2.0.0pre15 2003-11-11
Changes since 2.0.0pre14:
Modules/
Follow rule "Always include Python.h first"
ldap.schema.subentry:
* Added new method SubSchema.get_structural_oc()
* Added new method SubSchema.get_applicable_aux_classes()
* Methods SubSchema.listall() and SubSchema.tree() have
new key-word argument schema_element_filters
* Support for DIT content rules in SubSchema.attribute_types()
----------------------------------------------------------------
Released 2.0.0pre14 2003-10-03
Changes since 2.0.0pre13:
setup.py:
* Some modifications to ease building for Win32
* Added directory Build/ mainly intended for platform-specific
examples of setup.cfg
* Fixed installing ldap.filter
ldap.ldapobject:
* Added class attribute LDAPObject.network_timeout mapped to
set_option(ldap.OPT_NETWORK_TIMEOUT,..)
* LDAPObject.search_ext(): Pass arguments serverctrls,clientctrls
to _ldap.search_ext()
ldap.sasl:
* Added class ldap.sasl.external for handling
the SASL mechanism EXTERNAL
* Dictionary ldap.sasl.saslmech_handler_class built during import
for all the known SASL mechanisms derived from class definitions
ldap.schema:
* More graceful handling of KeyError in SubSchema.attribute_types()
* New method SubSchema.get_inheritedattr() for retrieving inherited
class attributes
* New method SubSchema.get_inheritedobj() for retrieving a
schema element instance including all inherited class attributes
----------------------------------------------------------------
Released 2.0.0pre13 2003-06-02
Changes since 2.0.0pre12:
ldap.async:
* Checking type of argument writer_obj relaxed in
LDIFWriter.__init__() since file-like objects are
not necessarily an instance of file.
ldap.schema:
* ldap.schema.subentry.SubSchema.attribute_types() now correctly
handles attribute types without NAME set
* If SUP is not defined for a structural object class 'top' is
assumed to be the only super-class by default
* '_' is now the abstract top node in SubSchema.tree() for all
schema element classes since ABSTRACT and AUXILIARY object
classes are not derived from 'top' by default
----------------------------------------------------------------
Released 2.0.0pre12 2003-05-27
Changes since 2.0.0pre11:
New sub-module ldap.filter:
* Added functions escape_filter_chars() and filter_format()
ldap.ldapobject:
* Trace log writes LDAP URI of connection instead of module name
* search_s() passes self.timeout as argument timeout when
calling search_ext_s()
* Key-word arguments for simple_bind() and simple_bind_s()
with defaults for anonymous bind.
* LDAPObject.protocol_version is set to LDAPv3 as default
(this might make code changes necessary in a real LDAPv2
environment)
* Default for key-word argument trace_stack_limit passed to
__init__() is 5
* Updated __doc__ strings
* Aligned and tested ReconnectLDAPObject and SmartLDAPObject
ldap.async:
* LDIFWriter uses ldif.LDIFWriter instead of calling
function ldif.CreateLDIF
* LDIFWriter accepts either file-like object or ldif.LDIFWriter
instance as argument for specifying the output
ldif:
* Abandoned argument all_records of LDIFRecordList.__init__()
ldapurl:
* urllib.unquote() used instead of urllib.unquote_plus()
----------------------------------------------------------------
Released 2.0.0pre11 2003-05-02
Changes since 2.0.0pre10:
ldap.ldapobject:
* Cosmetic change: Named argument list for LDAPObject.compare()
instead of *args,**kwargs.
* Fixed bug in ReconnectLDAPObject._apply_method_s() affecting
compability with Python 2.0. The bug was introduced with
2.0.0pre09 by dropping use of apply().
ldap.modlist:
* modifyModlist(): Only None is filtered from attribute value lists,
'' is preserved as valid attribute value. But filtering applies
to old_value and new_value now.
ldap.schema:
* Zero-length attribute values for schema elements are ignored
(needed on e.g. Active Directory)
dsml:
Added support for parsing and generating DSMLv1.
Still experimental though.
----------------------------------------------------------------
Released 2.0.0pre10 2003-04-19
Changes since 2.0.0pre09:
ldap.schema:
* Emulate BooleanType for compability with Python2.3 in assert
statements
----------------------------------------------------------------
Released 2.0.0pre09 2003-04-19
Changes since 2.0.0pre08:
Modified setup.py to support Cyrus-SASL 2.x.
ldap.ldapobject:
* apply() is not used anymore since it seems deprecated
* Fixed __setstate__() and __getstate__() of ReconnectLDAPObject
ldap.schema:
* Completed classes for nameForms, dITStructureRules and
dITContentRules
----------------------------------------------------------------
Released 2.0.0pre08 2003-04-11
Changes since 2.0.0pre07:
ldap.schema:
* For backward compability with Python versions prior to 2.2
Lib/ldap/schema/tokenizer.py and Lib/ldap/schema/models.py use
(()) instead of tuple() for creating empty tuples.
----------------------------------------------------------------
Released 2.0.0pre07 2003-04-03
Changes since 2.0.0pre06:
LDAPObject.c:
* Wrapped OpenLDAP's ldap_search_ext()
* Removed empty __doc__ strings
* Removed fileno
* Removed all stuff related to caching in OpenLDAP libs
ldap.ldapobject:
* Fixed SASL rebind in ldap.ldapobject.ReconnectLDAPObject
* use search_ext() instead ldap_search()
* new class attribute timeout for setting a global time-out
value for all synchronous operations
ldap.schema:
* Fixed two typos in ldap.schema.models
* Some attempts to improve performance of parser/tokenizer
* Completely reworked to have separate OID dictionaries for
the different schema element classes
* Fixed the Demo/schema*.py to reflect changes to ldap.schema
Documentation updates and various __doc__ string modifications.
ldapurl:
* Removed all Unicode stuff from module ldapurl
* Consistent URL encoding in module ldapurl
ldif:
* Removed ldif.FileWriter
* Proper handling of FILL (see RFC 2849)
----------------------------------------------------------------
Released 2.0.0pre06 2002-09-23
Changes since 2.0.0pre05:
- Fine-grained locking when linking against libldap_r
- New wrapper class ldap.ReconnectLDAPObject
- Security fix to module ldapurl
- Other fixes and improvements to whole package
- LDAPv3 schema support
(still somewhat premature and undocumented)
----------------------------------------------------------------
Released 2.0.0pre05 2002-07-20
----------------------------------------------------------------
Released 2.0.0pre04 2002-02-09
----------------------------------------------------------------
Released 2.0.0pre02 2002-02-01
----------------------------------------------------------------
Released 1.10alpha3 2000-09-19
$Id: CHANGES,v 1.291 2012/06/07 18:38:47 stroeder Exp $
python-ldap-2.4.10/setup.py 0000644 0000764 0000144 00000013201 11660514461 016335 0 ustar michael users 0000000 0000000 """
setup.py - Setup package with the help Python's DistUtils
See http://www.python-ldap.org/ for details.
$Id: setup.py,v 1.71 2011/10/26 19:42:25 stroeder Exp $
"""
has_setuptools = False
try:
from setuptools import setup, Extension
has_setuptools = True
except ImportError:
from distutils.core import setup, Extension
from ConfigParser import ConfigParser
import sys,os,string,time
##################################################################
# Weird Hack to grab release version of python-ldap from local dir
##################################################################
exec_startdir = os.path.dirname(os.path.abspath(sys.argv[0]))
package_init_file_name = reduce(os.path.join,[exec_startdir,'Lib','ldap','__init__.py'])
f = open(package_init_file_name,'r')
s = f.readline()
while s:
s = string.strip(s)
if s[0:11]=='__version__':
version = eval(string.split(s,'=')[1])
break
s = f.readline()
f.close()
#-- A class describing the features and requirements of OpenLDAP 2.0
class OpenLDAP2:
library_dirs = []
include_dirs = []
extra_compile_args = []
extra_link_args = []
extra_objects = []
libs = ['ldap', 'lber']
defines = [ ]
extra_files = []
LDAP_CLASS = OpenLDAP2
#-- Read the [_ldap] section of setup.cfg
cfg = ConfigParser()
cfg.read('setup.cfg')
if cfg.has_section('_ldap'):
for name in dir(LDAP_CLASS):
if cfg.has_option('_ldap', name):
print name + ': ' + cfg.get('_ldap', name)
setattr(LDAP_CLASS, name, string.split(cfg.get('_ldap', name)))
for i in range(len(LDAP_CLASS.defines)):
LDAP_CLASS.defines[i]=((LDAP_CLASS.defines[i],None))
for i in range(len(LDAP_CLASS.extra_files)):
destdir, origfiles = string.split(LDAP_CLASS.extra_files[i], ':')
origfileslist = string.split(origfiles, ',')
LDAP_CLASS.extra_files[i]=(destdir, origfileslist)
#-- Let distutils/setuptools do the rest
name = 'python-ldap'
# Python 2.3.6+ and setuptools are needed to build eggs, so
# let's handle setuptools' additional keyword arguments to
# setup() in a fashion that doesn't break compatibility to
# distutils. This still allows 'normal' builds where either
# Python > 2.3.5 or setuptools (or both ;o) are not available.
kwargs = dict()
if has_setuptools:
kwargs = dict(
include_package_data = True,
install_requires = ['setuptools'],
zip_safe = False
)
setup(
#-- Package description
name = name,
version = version,
description = 'Python modules for implementing LDAP clients',
long_description = """python-ldap:
python-ldap provides an object-oriented API to access LDAP directory servers
from Python programs. Mainly it wraps the OpenLDAP 2.x libs for that purpose.
Additionally the package contains modules for other LDAP-related stuff
(e.g. processing LDIF, LDAPURLs, LDAPv3 schema, LDAPv3 extended operations
and controls, etc.).
""",
author = 'python-ldap project',
author_email = 'python-ldap@python.org',
url = 'http://www.python-ldap.org/',
download_url = 'http://pypi.python.org/pypi/python-ldap/',
classifiers = [
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'Operating System :: OS Independent',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Programming Language :: C',
'Programming Language :: Python',
'Topic :: Database',
'Topic :: Internet',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: System :: Systems Administration :: Authentication/Directory :: LDAP',
'License :: OSI Approved :: Python Software Foundation License',
],
license = 'Python style',
#-- C extension modules
ext_modules = [
Extension(
'_ldap',
[
'Modules/LDAPObject.c',
'Modules/ldapcontrol.c',
'Modules/common.c',
'Modules/constants.c',
'Modules/errors.c',
'Modules/functions.c',
'Modules/schema.c',
'Modules/ldapmodule.c',
'Modules/message.c',
'Modules/version.c',
'Modules/options.c',
'Modules/berval.c',
],
libraries = LDAP_CLASS.libs,
include_dirs = ['Modules'] + LDAP_CLASS.include_dirs,
library_dirs = LDAP_CLASS.library_dirs,
extra_compile_args = LDAP_CLASS.extra_compile_args,
extra_link_args = LDAP_CLASS.extra_link_args,
extra_objects = LDAP_CLASS.extra_objects,
runtime_library_dirs = (not sys.platform.startswith("win"))*LDAP_CLASS.library_dirs,
define_macros = LDAP_CLASS.defines + \
('ldap_r' in LDAP_CLASS.libs or 'oldap_r' in LDAP_CLASS.libs)*[('HAVE_LIBLDAP_R',None)] + \
('sasl' in LDAP_CLASS.libs or 'sasl2' in LDAP_CLASS.libs or 'libsasl' in LDAP_CLASS.libs)*[('HAVE_SASL',None)] + \
('ssl' in LDAP_CLASS.libs and 'crypto' in LDAP_CLASS.libs)*[('HAVE_TLS',None)] + \
[('LDAPMODULE_VERSION', version)]
),
],
#-- Python "stand alone" modules
py_modules = [
'ldapurl',
'ldif',
'dsml',
'ldap',
'ldap.async',
'ldap.controls',
'ldap.controls.libldap',
'ldap.controls.ppolicy',
'ldap.controls.psearch',
'ldap.controls.readentry',
'ldap.controls.sessiontrack',
'ldap.controls.simple',
'ldap.cidict',
'ldap.dn',
'ldap.extop',
'ldap.extop.dds',
'ldap.filter',
'ldap.functions',
'ldap.ldapobject',
'ldap.logger',
'ldap.modlist',
'ldap.resiter',
'ldap.sasl',
'ldap.schema',
'ldap.schema.models',
'ldap.schema.subentry',
'ldap.schema.tokenizer',
'ldap.syncrepl',
],
package_dir = {'': 'Lib',},
data_files = LDAP_CLASS.extra_files,
**kwargs
)
python-ldap-2.4.10/PKG-INFO 0000644 0000764 0000144 00000002637 11764172736 015745 0 ustar michael users 0000000 0000000 Metadata-Version: 1.1
Name: python-ldap
Version: 2.4.10
Summary: Python modules for implementing LDAP clients
Home-page: http://www.python-ldap.org/
Author: python-ldap project
Author-email: python-ldap@python.org
License: Python style
Download-URL: http://pypi.python.org/pypi/python-ldap/
Description: python-ldap:
python-ldap provides an object-oriented API to access LDAP directory servers
from Python programs. Mainly it wraps the OpenLDAP 2.x libs for that purpose.
Additionally the package contains modules for other LDAP-related stuff
(e.g. processing LDIF, LDAPURLs, LDAPv3 schema, LDAPv3 extended operations
and controls, etc.).
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: Programming Language :: C
Classifier: Programming Language :: Python
Classifier: Topic :: Database
Classifier: Topic :: Internet
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory :: LDAP
Classifier: License :: OSI Approved :: Python Software Foundation License
python-ldap-2.4.10/MANIFEST.in 0000644 0000764 0000144 00000000355 11273113550 016361 0 ustar michael users 0000000 0000000 include MANIFEST.in Makefile CHANGES INSTALL LICENCE README TODO PKG-INFO
include Modules/*.c Modules/*.h Modules/LICENSE
recursive-include Build *.cfg*
recursive-include Lib *.py
recursive-include Demo *.py
recursive-include Tests *.py
python-ldap-2.4.10/setup.cfg 0000644 0000764 0000144 00000001030 11764172736 016453 0 ustar michael users 0000000 0000000 [_ldap]
library_dirs = /opt/openldap-RE24/lib /usr/lib
include_dirs = /opt/openldap-RE24/include /usr/include/sasl /usr/include
defines = HAVE_SASL HAVE_TLS HAVE_LIBLDAP_R
extra_compile_args =
extra_objects =
libs = ldap_r
[install]
compile = 1
optimize = 1
[bdist_rpm]
provides = python-ldap
requires = python libldap-2_4
vendor = python-ldap project
packager = Michael Ströder
distribution_name = openSUSE 11.x
release = 1
doc_files = CHANGES README INSTALL TODO Demo/
[egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
python-ldap-2.4.10/LICENCE 0000644 0000764 0000144 00000001136 07542145452 015620 0 ustar michael users 0000000 0000000
The python-ldap package is distributed under Python-style license.
Standard disclaimer:
This software is made available by the author(s) to the public for free
and "as is". All users of this free software are solely and entirely
responsible for their own choice and use of this software for their
own purposes. By using this software, each user agrees that the
author(s) shall not be liable for damages of any kind in relation to
its use or performance. The author(s) do not warrant that this software
is fit for any purpose.
$Id: LICENCE,v 1.1 2002/09/18 18:51:22 stroeder Exp $
python-ldap-2.4.10/Lib/ 0000755 0000764 0000144 00000000000 11764172736 015346 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Lib/python_ldap.egg-info/ 0000755 0000764 0000144 00000000000 11764172736 021361 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Lib/python_ldap.egg-info/requires.txt 0000644 0000764 0000144 00000000012 11764172735 023751 0 ustar michael users 0000000 0000000 setuptools python-ldap-2.4.10/Lib/python_ldap.egg-info/SOURCES.txt 0000644 0000764 0000144 00000005671 11764172735 023255 0 ustar michael users 0000000 0000000 .cvsignore
CHANGES
INSTALL
LICENCE
MANIFEST.in
PKG-INFO
README
TODO
setup.cfg
setup.py
Build/setup.cfg.mingw
Build/setup.cfg.suse-linux
Build/setup.cfg.win32
Build/build-openbsd/Makefile
Build/build-openbsd/pkg/COMMENT
Build/build-openbsd/pkg/DESCR
Build/build-openbsd/pkg/PLIST
Demo/.cvsignore
Demo/initialize.py
Demo/ldapcontrols.py
Demo/matchedvalues.py
Demo/ms_ad_bind.py
Demo/options.py
Demo/page_control.py
Demo/paged_search_ext_s.py
Demo/passwd_ext_op.py
Demo/pickle_ldapobject.py
Demo/reconnect.py
Demo/rename.py
Demo/resiter.py
Demo/sasl_bind.py
Demo/schema.py
Demo/schema_tree.py
Demo/simple.py
Demo/simplebrowse.py
Demo/Lib/.cvsignore
Demo/Lib/ldap/.cvsignore
Demo/Lib/ldap/async/.cvsignore
Demo/Lib/ldap/async/deltree.py
Demo/Lib/ldap/async/ldifwriter.py
Demo/Lib/ldap/async/sizelimit.py
Demo/Lib/ldapurl/.cvsignore
Demo/Lib/ldapurl/urlsearch.py
Demo/Lib/ldif/.cvsignore
Demo/Lib/ldif/ldifcopy.py
Demo/pyasn1/README
Demo/pyasn1/dds.py
Demo/pyasn1/ppolicy.py
Demo/pyasn1/psearch.py
Demo/pyasn1/readentrycontrol.py
Demo/pyasn1/sessiontrack.py
Demo/pyasn1/syncrepl.py
Doc/.cvsignore
Doc/Makefile
Doc/conf.py
Doc/dsml.rst
Doc/index.rst
Doc/installing.rst
Doc/ldap-async.rst
Doc/ldap-controls.rst
Doc/ldap-dn.rst
Doc/ldap-extop.rst
Doc/ldap-filter.rst
Doc/ldap-modlist.rst
Doc/ldap-resiter.rst
Doc/ldap-schema.rst
Doc/ldap-syncrepl.rst
Doc/ldap.rst
Doc/ldapurl.rst
Doc/ldif.rst
Lib/.cvsignore
Lib/dsml.py
Lib/ldapurl.py
Lib/ldif.py
Lib/ldap/.cvsignore
Lib/ldap/__init__.py
Lib/ldap/async.py
Lib/ldap/cidict.py
Lib/ldap/dn.py
Lib/ldap/filter.py
Lib/ldap/functions.py
Lib/ldap/ldapobject.py
Lib/ldap/logger.py
Lib/ldap/modlist.py
Lib/ldap/resiter.py
Lib/ldap/sasl.py
Lib/ldap/syncrepl.py
Lib/ldap/controls/__init__.py
Lib/ldap/controls/libldap.py
Lib/ldap/controls/ppolicy.py
Lib/ldap/controls/psearch.py
Lib/ldap/controls/pwdpolicy.py
Lib/ldap/controls/readentry.py
Lib/ldap/controls/sessiontrack.py
Lib/ldap/controls/simple.py
Lib/ldap/extop/__init__.py
Lib/ldap/extop/dds.py
Lib/ldap/schema/.cvsignore
Lib/ldap/schema/__init__.py
Lib/ldap/schema/models.py
Lib/ldap/schema/subentry.py
Lib/ldap/schema/tokenizer.py
Lib/python_ldap.egg-info/PKG-INFO
Lib/python_ldap.egg-info/SOURCES.txt
Lib/python_ldap.egg-info/dependency_links.txt
Lib/python_ldap.egg-info/not-zip-safe
Lib/python_ldap.egg-info/requires.txt
Lib/python_ldap.egg-info/top_level.txt
Modules/.cvsignore
Modules/LDAPObject.c
Modules/LDAPObject.h
Modules/berval.c
Modules/berval.h
Modules/common.c
Modules/common.h
Modules/constants.c
Modules/constants.h
Modules/errors.c
Modules/errors.h
Modules/functions.c
Modules/functions.h
Modules/ldapcontrol.c
Modules/ldapcontrol.h
Modules/ldapmodule.c
Modules/message.c
Modules/message.h
Modules/options.c
Modules/options.h
Modules/schema.c
Modules/schema.h
Modules/version.c
Modules/version.h
Tests/runtests.sh
Tests/search.py
Tests/slapd.py
Tests/t_cext.py
Tests/t_ldapurl.py
Tests/t_search.py
Tests/Lib/test_ldapurl.py
Tests/Lib/ldap/test_modlist.py
Tests/Lib/ldap/schema/test_tokenizer.py python-ldap-2.4.10/Lib/python_ldap.egg-info/top_level.txt 0000644 0000764 0000144 00000000035 11764172735 024110 0 ustar michael users 0000000 0000000 dsml
ldapurl
ldap
_ldap
ldif
python-ldap-2.4.10/Lib/python_ldap.egg-info/dependency_links.txt 0000644 0000764 0000144 00000000001 11764172735 025426 0 ustar michael users 0000000 0000000
python-ldap-2.4.10/Lib/python_ldap.egg-info/PKG-INFO 0000644 0000764 0000144 00000002637 11764172735 022465 0 ustar michael users 0000000 0000000 Metadata-Version: 1.1
Name: python-ldap
Version: 2.4.10
Summary: Python modules for implementing LDAP clients
Home-page: http://www.python-ldap.org/
Author: python-ldap project
Author-email: python-ldap@python.org
License: Python style
Download-URL: http://pypi.python.org/pypi/python-ldap/
Description: python-ldap:
python-ldap provides an object-oriented API to access LDAP directory servers
from Python programs. Mainly it wraps the OpenLDAP 2.x libs for that purpose.
Additionally the package contains modules for other LDAP-related stuff
(e.g. processing LDIF, LDAPURLs, LDAPv3 schema, LDAPv3 extended operations
and controls, etc.).
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: Programming Language :: C
Classifier: Programming Language :: Python
Classifier: Topic :: Database
Classifier: Topic :: Internet
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory :: LDAP
Classifier: License :: OSI Approved :: Python Software Foundation License
python-ldap-2.4.10/Lib/python_ldap.egg-info/not-zip-safe 0000644 0000764 0000144 00000000001 11612065006 023566 0 ustar michael users 0000000 0000000
python-ldap-2.4.10/Lib/ldapurl.py 0000644 0000764 0000144 00000026753 11764172710 017370 0 ustar michael users 0000000 0000000 """
ldapurl - handling of LDAP URLs as described in RFC 4516
See http://www.python-ldap.org/ for details.
\$Id: ldapurl.py,v 1.58 2012/06/07 18:40:59 stroeder Exp $
Python compability note:
This module only works with Python 2.0+ since
1. string methods are used instead of module string and
2. list comprehensions are used.
"""
__version__ = '2.4.10'
__all__ = [
# constants
'SEARCH_SCOPE','SEARCH_SCOPE_STR',
'LDAP_SCOPE_BASE','LDAP_SCOPE_ONELEVEL','LDAP_SCOPE_SUBTREE',
# functions
'isLDAPUrl',
# classes
'LDAPUrlExtension','LDAPUrlExtensions','LDAPUrl'
]
import UserDict
from urllib import quote,unquote
LDAP_SCOPE_BASE = 0
LDAP_SCOPE_ONELEVEL = 1
LDAP_SCOPE_SUBTREE = 2
SEARCH_SCOPE_STR = {None:'',0:'base',1:'one',2:'sub'}
SEARCH_SCOPE = {
'':None,
# the search scope strings defined in RFC2255
'base':LDAP_SCOPE_BASE,
'one':LDAP_SCOPE_ONELEVEL,
'sub':LDAP_SCOPE_SUBTREE,
}
# Some widely used types
StringType = type('')
TupleType=type(())
def isLDAPUrl(s):
"""
Returns 1 if s is a LDAP URL, 0 else
"""
s_lower = s.lower()
return \
s_lower.startswith('ldap://') or \
s_lower.startswith('ldaps://') or \
s_lower.startswith('ldapi://')
def ldapUrlEscape(s):
"""Returns URL encoding of string s"""
return quote(s).replace(',','%2C').replace('/','%2F')
class LDAPUrlExtension:
"""
Class for parsing and unparsing LDAP URL extensions
as described in RFC 4516.
Usable class attributes:
critical
Boolean integer marking the extension as critical
extype
Type of extension
exvalue
Value of extension
"""
def __init__(self,extensionStr=None,critical=0,extype=None,exvalue=None):
self.critical = critical
self.extype = extype
self.exvalue = exvalue
if extensionStr:
self._parse(extensionStr)
def _parse(self,extension):
extension = extension.strip()
if not extension:
# Don't parse empty strings
self.extype,self.exvalue = None,None
return
self.critical = extension[0]=='!'
if extension[0]=='!':
extension = extension[1:].strip()
try:
self.extype,self.exvalue = extension.split('=',1)
except ValueError:
# No value, just the extype
self.extype,self.exvalue = extension,None
else:
self.exvalue = unquote(self.exvalue.strip())
self.extype = self.extype.strip()
def unparse(self):
if self.exvalue is None:
return '%s%s' % ('!'*(self.critical>0),self.extype)
else:
return '%s%s=%s' % (
'!'*(self.critical>0),
self.extype,quote(self.exvalue or '')
)
def __str__(self):
return self.unparse()
def __repr__(self):
return '<%s.%s instance at %s: %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self)),
self.__dict__
)
def __eq__(self,other):
return \
(self.critical==other.critical) and \
(self.extype==other.extype) and \
(self.exvalue==other.exvalue)
def __ne__(self,other):
return not self.__eq__(other)
class LDAPUrlExtensions(UserDict.UserDict):
"""
Models a collection of LDAP URL extensions as
dictionary type
"""
def __init__(self,default=None):
UserDict.UserDict.__init__(self)
for k,v in (default or {}).items():
self[k]=v
def __setitem__(self,name,value):
"""
value
Either LDAPUrlExtension instance, (critical,exvalue)
or string'ed exvalue
"""
assert isinstance(value,LDAPUrlExtension)
assert name==value.extype
self.data[name] = value
def values(self):
return [
self[k]
for k in self.keys()
]
def __str__(self):
return ','.join(map(str,self.values()))
def __repr__(self):
return '<%s.%s instance at %s: %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self)),
self.data
)
def __eq__(self,other):
assert isinstance(other,self.__class__),TypeError(
"other has to be instance of %s" % (self.__class__)
)
return self.data==other.data
def parse(self,extListStr):
for extension_str in extListStr.strip().split(','):
if extension_str:
e = LDAPUrlExtension(extension_str)
self[e.extype] = e
def unparse(self):
return ','.join([ v.unparse() for v in self.values() ])
class LDAPUrl:
"""
Class for parsing and unparsing LDAP URLs
as described in RFC 4516.
Usable class attributes:
urlscheme
URL scheme (either ldap, ldaps or ldapi)
hostport
LDAP host (default '')
dn
String holding distinguished name (default '')
attrs
list of attribute types (default None)
scope
integer search scope for ldap-module
filterstr
String representation of LDAP Search Filters
(see RFC 4515)
extensions
Dictionary used as extensions store
who
Maps automagically to bindname LDAP URL extension
cred
Maps automagically to X-BINDPW LDAP URL extension
"""
attr2extype = {'who':'bindname','cred':'X-BINDPW'}
def __init__(
self,
ldapUrl=None,
urlscheme='ldap',
hostport='',dn='',attrs=None,scope=None,filterstr=None,
extensions=None,
who=None,cred=None
):
self.urlscheme=urlscheme
self.hostport=hostport
self.dn=dn
self.attrs=attrs
self.scope=scope
self.filterstr=filterstr
self.extensions=(extensions or LDAPUrlExtensions({}))
if ldapUrl!=None:
self._parse(ldapUrl)
if who!=None:
self.who = who
if cred!=None:
self.cred = cred
def __eq__(self,other):
return \
self.urlscheme==other.urlscheme and \
self.hostport==other.hostport and \
self.dn==other.dn and \
self.attrs==other.attrs and \
self.scope==other.scope and \
self.filterstr==other.filterstr and \
self.extensions==other.extensions
def __ne__(self,other):
return not self.__eq__(other)
def _parse(self,ldap_url):
"""
parse a LDAP URL and set the class attributes
urlscheme,host,dn,attrs,scope,filterstr,extensions
"""
if not isLDAPUrl(ldap_url):
raise ValueError,'Parameter ldap_url does not seem to be a LDAP URL.'
scheme,rest = ldap_url.split('://',1)
self.urlscheme = scheme.strip()
if not self.urlscheme in ['ldap','ldaps','ldapi']:
raise ValueError,'LDAP URL contains unsupported URL scheme %s.' % (self.urlscheme)
slash_pos = rest.find('/')
qemark_pos = rest.find('?')
if (slash_pos==-1) and (qemark_pos==-1):
# No / and ? found at all
self.hostport = unquote(rest)
self.dn = ''
return
else:
if slash_pos!=-1 and (qemark_pos==-1 or (slash_posqemark_pos)):
# Question mark separates hostport from rest, DN is assumed to be empty
self.hostport = unquote(rest[:qemark_pos])
# Do not eat question mark
rest = rest[qemark_pos:]
else:
raise ValueError,'Something completely weird happened!'
paramlist=rest.split('?',4)
paramlist_len = len(paramlist)
if paramlist_len>=1:
self.dn = unquote(paramlist[0]).strip()
if (paramlist_len>=2) and (paramlist[1]):
self.attrs = unquote(paramlist[1].strip()).split(',')
if paramlist_len>=3:
scope = paramlist[2].strip()
try:
self.scope = SEARCH_SCOPE[scope]
except KeyError:
raise ValueError,"Search scope must be either one of base, one or sub. LDAP URL contained %s" % (repr(scope))
if paramlist_len>=4:
filterstr = paramlist[3].strip()
if not filterstr:
self.filterstr = None
else:
self.filterstr = unquote(filterstr)
if paramlist_len>=5:
if paramlist[4]:
self.extensions = LDAPUrlExtensions()
self.extensions.parse(paramlist[4])
else:
self.extensions = None
return
def applyDefaults(self,defaults):
"""
Apply defaults to all class attributes which are None.
defaults
Dictionary containing a mapping from class attributes
to default values
"""
for k in defaults.keys():
if getattr(self,k) is None:
setattr(self,k,defaults[k])
def initializeUrl(self):
"""
Returns LDAP URL suitable to be passed to ldap.initialize()
"""
if self.urlscheme=='ldapi':
# hostport part might contain slashes when ldapi:// is used
hostport = ldapUrlEscape(self.hostport)
else:
hostport = self.hostport
return '%s://%s' % (self.urlscheme,hostport)
def unparse(self):
"""
Returns LDAP URL depending on class attributes set.
"""
if self.attrs is None:
attrs_str = ''
else:
attrs_str = ','.join(self.attrs)
scope_str = SEARCH_SCOPE_STR[self.scope]
if self.filterstr is None:
filterstr = ''
else:
filterstr = ldapUrlEscape(self.filterstr)
dn = ldapUrlEscape(self.dn)
if self.urlscheme=='ldapi':
# hostport part might contain slashes when ldapi:// is used
hostport = ldapUrlEscape(self.hostport)
else:
hostport = self.hostport
ldap_url = '%s://%s/%s?%s?%s?%s' % (
self.urlscheme,
hostport,dn,attrs_str,scope_str,filterstr
)
if self.extensions:
ldap_url = ldap_url+'?'+self.extensions.unparse()
return ldap_url
def htmlHREF(self,urlPrefix='',hrefText=None,hrefTarget=None):
"""
Returns a string with HTML link for this LDAP URL.
urlPrefix
Prefix before LDAP URL (e.g. for addressing another web-based client)
hrefText
link text/description
hrefTarget
string added as link target attribute
"""
assert type(urlPrefix)==StringType, "urlPrefix must be StringType"
if hrefText is None:
hrefText = self.unparse()
assert type(hrefText)==StringType, "hrefText must be StringType"
if hrefTarget is None:
target = ''
else:
assert type(hrefTarget)==StringType, "hrefTarget must be StringType"
target = ' target="%s"' % hrefTarget
return '%s' % (
target,urlPrefix,self.unparse(),hrefText
)
def __str__(self):
return self.unparse()
def __repr__(self):
return '<%s.%s instance at %s: %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self)),
self.__dict__
)
def __getattr__(self,name):
if self.attr2extype.has_key(name):
extype = self.attr2extype[name]
if self.extensions and \
self.extensions.has_key(extype) and \
not self.extensions[extype].exvalue is None:
result = unquote(self.extensions[extype].exvalue)
else:
return None
else:
raise AttributeError,"%s has no attribute %s" % (
self.__class__.__name__,name
)
return result # __getattr__()
def __setattr__(self,name,value):
if self.attr2extype.has_key(name):
extype = self.attr2extype[name]
if value is None:
# A value of None means that extension is deleted
delattr(self,name)
elif value!=None:
# Add appropriate extension
self.extensions[extype] = LDAPUrlExtension(
extype=extype,exvalue=unquote(value)
)
else:
self.__dict__[name] = value
def __delattr__(self,name):
if self.attr2extype.has_key(name):
extype = self.attr2extype[name]
if self.extensions:
try:
del self.extensions[extype]
except KeyError:
pass
else:
del self.__dict__[name]
python-ldap-2.4.10/Lib/.cvsignore 0000644 0000764 0000144 00000000025 07465025376 017343 0 ustar michael users 0000000 0000000 *.pyc
*.pyo
*.bck
*~
python-ldap-2.4.10/Lib/ldap/ 0000755 0000764 0000144 00000000000 11764172736 016266 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Lib/ldap/extop/ 0000755 0000764 0000144 00000000000 11764172736 017425 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Lib/ldap/extop/__init__.py 0000644 0000764 0000144 00000003671 11612335224 021526 0 ustar michael users 0000000 0000000 """
controls.py - support classes for LDAPv3 extended operations
See http://www.python-ldap.org/ for details.
\$Id: __init__.py,v 1.4 2011/07/22 13:27:02 stroeder Exp $
Description:
The ldap.extop module provides base classes for LDAPv3 extended operations.
Each class provides support for a certain extended operation request and
response.
"""
from ldap import __version__
class ExtendedRequest:
"""
Generic base class for a LDAPv3 extended operation request
requestName
OID as string of the LDAPv3 extended operation request
requestValue
value of the LDAPv3 extended operation request
(here it is the BER-encoded ASN.1 request value)
"""
def __init__(self,requestName,requestValue):
self.requestName = requestName
self.requestValue = requestValue
def __repr__(self):
return '%s(%s,%s)' % (self.__class__.__name__,self.requestName,self.requestValue)
def encodedRequestValue(self):
"""
returns the BER-encoded ASN.1 request value composed by class attributes
set before
"""
return self.requestValue
class ExtendedResponse:
"""
Generic base class for a LDAPv3 extended operation response
requestName
OID as string of the LDAPv3 extended operation response
encodedResponseValue
BER-encoded ASN.1 value of the LDAPv3 extended operation response
"""
def __init__(self,responseName,encodedResponseValue):
self.responseName = responseName
self.responseValue = self.decodeResponseValue(encodedResponseValue)
def __repr__(self):
return '%s(%s,%s)' % (self.__class__.__name__,self.responseName,self.responseValue)
def decodeResponseValue(self,value):
"""
decodes the BER-encoded ASN.1 extended operation response value and
sets the appropriate class attributes
"""
return value
# Optionally import sub-modules which need pyasn1 et al
try:
import pyasn1,pyasn1_modules.rfc2251
except ImportError:
pass
else:
from ldap.extop.dds import *
python-ldap-2.4.10/Lib/ldap/extop/dds.py 0000644 0000764 0000144 00000004120 11603375732 020537 0 ustar michael users 0000000 0000000 # -*- coding: utf-8 -*-
"""
ldap.extop.dds - Classes for Dynamic Entries extended operations
(see RFC 2589)
This needs the following software:
Python
pyasn1
pyasn1-modules
python-ldap 2.4+
"""
from ldap.extop import ExtendedRequest,ExtendedResponse
# Imports from pyasn1
from pyasn1.type import namedtype,univ,tag
from pyasn1.codec.der import encoder,decoder
from pyasn1_modules.rfc2251 import LDAPDN
class RefreshRequest(ExtendedRequest):
requestName = '1.3.6.1.4.1.1466.101.119.1'
defaultRequestTtl = 86400
class RefreshRequestValue(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType(
'entryName',
LDAPDN().subtype(
implicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatSimple,0)
)
),
namedtype.NamedType(
'requestTtl',
univ.Integer().subtype(
implicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatSimple,1)
)
),
)
def __init__(self,requestName=None,entryName=None,requestTtl=None):
self.entryName = entryName
self.requestTtl = requestTtl or self.defaultRequestTtl
def encodedRequestValue(self):
p = self.RefreshRequestValue()
p.setComponentByName(
'entryName',
LDAPDN(self.entryName).subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,0)
)
)
p.setComponentByName(
'requestTtl',
univ.Integer(self.requestTtl).subtype(
implicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatSimple,1)
)
)
return encoder.encode(p)
class RefreshResponse(ExtendedResponse):
responseName = '1.3.6.1.4.1.1466.101.119.1'
class RefreshResponseValue(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType(
'responseTtl',
univ.Integer().subtype(
implicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatSimple,1)
)
)
)
def decodeResponseValue(self,value):
respValue,_ = decoder.decode(value,asn1Spec=self.RefreshResponseValue())
self.responseTtl = int(respValue.getComponentByName('responseTtl'))
return self.responseTtl
python-ldap-2.4.10/Lib/ldap/modlist.py 0000644 0000764 0000144 00000010400 11573150432 020271 0 ustar michael users 0000000 0000000 """
ldap.modlist - create add/modify modlist's
See http://www.python-ldap.org/ for details.
$Id: modlist.py,v 1.18 2011/06/06 13:07:38 stroeder Exp $
Python compability note:
This module is known to work with Python 2.0+ but should work
with Python 1.5.2 as well.
"""
from ldap import __version__
import string,ldap,ldap.cidict
def list_dict(l,case_insensitive=0):
"""
return a dictionary with all items of l being the keys of the dictionary
If argument case_insensitive is non-zero ldap.cidict.cidict will be
used for case-insensitive string keys
"""
if case_insensitive:
d = ldap.cidict.cidict()
else:
d = {}
for i in l:
d[i]=None
return d
def addModlist(entry,ignore_attr_types=None):
"""Build modify list for call of method LDAPObject.add()"""
ignore_attr_types = list_dict(map(string.lower,(ignore_attr_types or [])))
modlist = []
for attrtype in entry.keys():
if ignore_attr_types.has_key(string.lower(attrtype)):
# This attribute type is ignored
continue
# Eliminate empty attr value strings in list
attrvaluelist = filter(lambda x:x!=None,entry[attrtype])
if attrvaluelist:
modlist.append((attrtype,entry[attrtype]))
return modlist # addModlist()
def modifyModlist(
old_entry,new_entry,ignore_attr_types=None,ignore_oldexistent=0,case_ignore_attr_types=None
):
"""
Build differential modify list for calling LDAPObject.modify()/modify_s()
old_entry
Dictionary holding the old entry
new_entry
Dictionary holding what the new entry should be
ignore_attr_types
List of attribute type names to be ignored completely
ignore_oldexistent
If non-zero attribute type names which are in old_entry
but are not found in new_entry at all are not deleted.
This is handy for situations where your application
sets attribute value to '' for deleting an attribute.
In most cases leave zero.
case_ignore_attr_types
List of attribute type names for which comparison will be made
case-insensitive
"""
ignore_attr_types = list_dict(map(string.lower,(ignore_attr_types or [])))
case_ignore_attr_types = list_dict(map(string.lower,(case_ignore_attr_types or [])))
modlist = []
attrtype_lower_map = {}
for a in old_entry.keys():
attrtype_lower_map[string.lower(a)]=a
for attrtype in new_entry.keys():
attrtype_lower = string.lower(attrtype)
if ignore_attr_types.has_key(attrtype_lower):
# This attribute type is ignored
continue
# Filter away null-strings
new_value = filter(lambda x:x!=None,new_entry[attrtype])
if attrtype_lower_map.has_key(attrtype_lower):
old_value = old_entry.get(attrtype_lower_map[attrtype_lower],[])
old_value = filter(lambda x:x!=None,old_value)
del attrtype_lower_map[attrtype_lower]
else:
old_value = []
if not old_value and new_value:
# Add a new attribute to entry
modlist.append((ldap.MOD_ADD,attrtype,new_value))
elif old_value and new_value:
# Replace existing attribute
replace_attr_value = len(old_value)!=len(new_value)
if not replace_attr_value:
case_insensitive = case_ignore_attr_types.has_key(attrtype_lower)
old_value_dict=list_dict(old_value,case_insensitive)
new_value_dict=list_dict(new_value,case_insensitive)
delete_values = []
for v in old_value:
if not new_value_dict.has_key(v):
replace_attr_value = 1
break
add_values = []
if not replace_attr_value:
for v in new_value:
if not old_value_dict.has_key(v):
replace_attr_value = 1
break
if replace_attr_value:
modlist.append((ldap.MOD_DELETE,attrtype,None))
modlist.append((ldap.MOD_ADD,attrtype,new_value))
elif old_value and not new_value:
# Completely delete an existing attribute
modlist.append((ldap.MOD_DELETE,attrtype,None))
if not ignore_oldexistent:
# Remove all attributes of old_entry which are not present
# in new_entry at all
for a in attrtype_lower_map.keys():
if ignore_attr_types.has_key(a):
# This attribute type is ignored
continue
attrtype = attrtype_lower_map[a]
modlist.append((ldap.MOD_DELETE,attrtype,None))
return modlist # modifyModlist()
python-ldap-2.4.10/Lib/ldap/.cvsignore 0000644 0000764 0000144 00000000025 07465025376 020263 0 ustar michael users 0000000 0000000 *.pyc
*.pyo
*.bck
*~
python-ldap-2.4.10/Lib/ldap/__init__.py 0000644 0000764 0000144 00000004255 11764172710 020375 0 ustar michael users 0000000 0000000 """
ldap - base module
See http://www.python-ldap.org/ for details.
$Id: __init__.py,v 1.83 2012/06/07 18:40:59 stroeder Exp $
"""
# This is also the overall release version number
__version__ = '2.4.10'
import sys
if __debug__:
# Tracing is only supported in debugging mode
import traceback
_trace_level = 0
_trace_file = sys.stderr
_trace_stack_limit = None
import _ldap
from _ldap import *
OPT_NAMES_DICT = {}
for k,v in vars(_ldap).items():
if k.startswith('OPT_'):
OPT_NAMES_DICT[v]=k
class DummyLock:
"""Define dummy class with methods compatible to threading.Lock"""
def __init__(self):
pass
def acquire(self):
pass
def release(self):
pass
try:
# Check if Python installation was build with thread support
import thread
except ImportError:
LDAPLockBaseClass = DummyLock
else:
import threading
LDAPLockBaseClass = threading.Lock
class LDAPLock:
"""
Mainly a wrapper class to log all locking events.
Note that this cumbersome approach with _lock attribute was taken
since threading.Lock is not suitable for sub-classing.
"""
_min_trace_level = 3
def __init__(self,lock_class=None,desc=''):
"""
lock_class
Class compatible to threading.Lock
desc
Description shown in debug log messages
"""
self._desc = desc
self._lock = (lock_class or LDAPLockBaseClass)()
def acquire(self):
if __debug__:
global _trace_level
if _trace_level>=self._min_trace_level:
_trace_file.write('***%s %s.acquire()\n' % (self._desc,self.__class__.__name__))
return self._lock.acquire()
def release(self):
if __debug__:
global _trace_level
if _trace_level>=self._min_trace_level:
_trace_file.write('***%s %s.release()\n' % (self._desc,self.__class__.__name__))
return self._lock.release()
# Create module-wide lock for serializing all calls into underlying LDAP lib
_ldap_module_lock = LDAPLock(desc='Module wide')
from functions import open,initialize,init,get_option,set_option
from ldap.dn import explode_dn,explode_rdn,str2dn,dn2str
del str2dn
del dn2str
# More constants
# For compability of 2.3 and 2.4 OpenLDAP API
OPT_DIAGNOSTIC_MESSAGE = OPT_ERROR_STRING
python-ldap-2.4.10/Lib/ldap/functions.py 0000644 0000764 0000144 00000006514 11704305353 020641 0 ustar michael users 0000000 0000000 """
functions.py - wraps functions of module _ldap
See http://www.python-ldap.org/ for details.
\$Id: functions.py,v 1.28 2011/11/23 17:27:46 stroeder Exp $
Compability:
- Tested with Python 2.0+ but should work with Python 1.5.x
- functions should behave exactly the same like in _ldap
Usage:
Directly imported by ldap/__init__.py. The symbols of _ldap are
overridden.
Thread-lock:
Basically calls into the LDAP lib are serialized by the module-wide
lock _ldapmodule_lock.
"""
from ldap import __version__
__all__ = [
'open','initialize','init',
'explode_dn','explode_rdn',
'get_option','set_option',
]
import sys,pprint,_ldap,ldap
from ldap import LDAPError
from ldap.dn import explode_dn,explode_rdn
from ldap.ldapobject import LDAPObject
if __debug__:
# Tracing is only supported in debugging mode
import traceback
def _ldap_function_call(lock,func,*args,**kwargs):
"""
Wrapper function which locks and logs calls to function
lock
Instance of threading.Lock or compatible
func
Function to call with arguments passed in via *args and **kwargs
"""
if lock:
lock.acquire()
if __debug__:
if ldap._trace_level>=1:
ldap._trace_file.write('*** %s.%s %s\n' % (
'_ldap',func.__name__,
pprint.pformat((args,kwargs))
))
if ldap._trace_level>=9:
traceback.print_stack(limit=ldap._trace_stack_limit,file=ldap._trace_file)
try:
try:
result = func(*args,**kwargs)
finally:
if lock:
lock.release()
except LDAPError,e:
if __debug__ and ldap._trace_level>=2:
ldap._trace_file.write('=> LDAPError: %s\n' % (str(e)))
raise
if __debug__ and ldap._trace_level>=2:
ldap._trace_file.write('=> result:\n%s\n' % (pprint.pformat(result)))
return result
def initialize(uri,trace_level=0,trace_file=sys.stdout,trace_stack_limit=None):
"""
Return LDAPObject instance by opening LDAP connection to
LDAP host specified by LDAP URL
Parameters:
uri
LDAP URL containing at least connection scheme and hostport,
e.g. ldap://localhost:389
trace_level
If non-zero a trace output of LDAP calls is generated.
trace_file
File object where to write the trace output to.
Default is to use stdout.
"""
return LDAPObject(uri,trace_level,trace_file,trace_stack_limit)
def open(host,port=389,trace_level=0,trace_file=sys.stdout,trace_stack_limit=None):
"""
Return LDAPObject instance by opening LDAP connection to
specified LDAP host
Parameters:
host
LDAP host and port, e.g. localhost
port
integer specifying the port number to use, e.g. 389
trace_level
If non-zero a trace output of LDAP calls is generated.
trace_file
File object where to write the trace output to.
Default is to use stdout.
"""
import warnings
warnings.warn('ldap.open() is deprecated! Use ldap.initialize() instead.', DeprecationWarning,2)
return initialize('ldap://%s:%d' % (host,port),trace_level,trace_file,trace_stack_limit)
init = open
def get_option(option):
"""
get_option(name) -> value
Get the value of an LDAP global option.
"""
return _ldap_function_call(None,_ldap.get_option,option)
def set_option(option,invalue):
"""
set_option(name, value)
Set the value of an LDAP global option.
"""
return _ldap_function_call(None,_ldap.set_option,option,invalue)
python-ldap-2.4.10/Lib/ldap/schema/ 0000755 0000764 0000144 00000000000 11764172736 017526 5 ustar michael users 0000000 0000000 python-ldap-2.4.10/Lib/ldap/schema/models.py 0000644 0000764 0000144 00000053151 11764172557 021371 0 ustar michael users 0000000 0000000 """
schema.py - support for subSchemaSubEntry information
See http://www.python-ldap.org/ for details.
\$Id: models.py,v 1.45 2012/03/07 19:07:15 stroeder Exp $
"""
import UserDict,ldap.cidict
from ldap.schema.tokenizer import split_tokens,extract_tokens
if __debug__:
from types import TupleType,StringType,IntType
try:
from types import BooleanType
except ImportError:
BooleanType = IntType
NOT_HUMAN_READABLE_LDAP_SYNTAXES = {
'1.3.6.1.4.1.1466.115.121.1.4':None, # Audio
'1.3.6.1.4.1.1466.115.121.1.5':None, # Binary
'1.3.6.1.4.1.1466.115.121.1.8':None, # Certificate
'1.3.6.1.4.1.1466.115.121.1.9':None, # Certificate List
'1.3.6.1.4.1.1466.115.121.1.10':None, # Certificate Pair
'1.3.6.1.4.1.1466.115.121.1.23':None, # G3 FAX
'1.3.6.1.4.1.1466.115.121.1.28':None, # JPEG
'1.3.6.1.4.1.1466.115.121.1.40':None, # Octet String
'1.3.6.1.4.1.1466.115.121.1.49':None, # Supported Algorithm
}
class SchemaElement:
"""
Base class for all schema element classes. Not used directly!
Arguments:
schema_element_str
String which contains the schema element description to be parsed.
Class attributes:
schema_attribute
LDAP attribute type containing a certain schema element description
token_defaults
Dictionary internally used by the schema element parser
containing the defaults for certain schema description key-words
"""
token_defaults = {
'DESC':(None,),
}
def __init__(self,schema_element_str=None):
if schema_element_str:
l = split_tokens(schema_element_str,self.token_defaults)
self.set_id(l[1])
d = extract_tokens(l,self.token_defaults)
self._set_attrs(l,d)
def _set_attrs(self,l,d):
self.desc = d['DESC'][0]
return
def set_id(self,element_id):
self.oid = element_id
def get_id(self):
return self.oid
def key_attr(self,key,value,quoted=0):
assert value is None or type(value)==StringType,TypeError("value has to be of StringType, was %s" % repr(value))
if value:
if quoted:
return " %s '%s'" % (key,value.replace("'","\\'"))
else:
return " %s %s" % (key,value)
else:
return ""
def key_list(self,key,values,sep=' ',quoted=0):
assert type(values)==TupleType,TypeError("values has to be of ListType")
if not values:
return ''
if quoted:
quoted_values = [ "'%s'" % value.replace("'","\\'") for value in values ]
else:
quoted_values = values
if len(values)==1:
return ' %s %s' % (key,quoted_values[0])
else:
return ' %s ( %s )' % (key,sep.join(quoted_values))
def __str__(self):
result = [str(self.oid)]
result.append(self.key_attr('DESC',self.desc,quoted=1))
return '( %s )' % ''.join(result)
class ObjectClass(SchemaElement):
"""
Arguments:
schema_element_str
String containing an ObjectClassDescription
Class attributes:
oid
OID assigned to the object class
names
This list of strings contains all NAMEs of the object class
desc
This string contains description text (DESC) of the object class
obsolete
Integer flag (0 or 1) indicating whether the object class is marked
as OBSOLETE in the schema
must
This list of strings contains NAMEs or OIDs of all attributes
an entry of the object class must have
may
This list of strings contains NAMEs or OIDs of additional attributes
an entry of the object class may have
kind
Kind of an object class:
0 = ABSTRACT,
1 = STRUCTURAL,
2 = AUXILIARY
sup
This list of strings contains NAMEs or OIDs of object classes
this object class is derived from
"""
schema_attribute = 'objectClasses'
token_defaults = {
'NAME':(()),
'DESC':(None,),
'OBSOLETE':None,
'SUP':(()),
'STRUCTURAL':None,
'AUXILIARY':None,
'ABSTRACT':None,
'MUST':(()),
'MAY':()
}
def _set_attrs(self,l,d):
self.obsolete = d['OBSOLETE']!=None
self.names = d['NAME']
self.desc = d['DESC'][0]
self.must = d['MUST']
self.may = d['MAY']
# Default is STRUCTURAL, see RFC2552 or draft-ietf-ldapbis-syntaxes
self.kind = 0
if d['ABSTRACT']!=None:
self.kind = 1
elif d['AUXILIARY']!=None:
self.kind = 2
if self.kind==0 and not d['SUP'] and self.oid!='2.5.6.0':
# STRUCTURAL object classes are sub-classes of 'top' by default
self.sup = ('top',)
else:
self.sup = d['SUP']
assert type(self.names)==TupleType
assert self.desc is None or type(self.desc)==StringType
assert type(self.obsolete)==BooleanType and (self.obsolete==0 or self.obsolete==1)
assert type(self.sup)==TupleType
assert type(self.kind)==IntType
assert type(self.must)==TupleType
assert type(self.may)==TupleType
return
def __str__(self):
result = [str(self.oid)]
result.append(self.key_list('NAME',self.names,quoted=1))
result.append(self.key_attr('DESC',self.desc,quoted=1))
result.append(self.key_list('SUP',self.sup,sep=' $ '))
result.append({0:'',1:' OBSOLETE'}[self.obsolete])
result.append({0:' STRUCTURAL',1:' ABSTRACT',2:' AUXILIARY'}[self.kind])
result.append(self.key_list('MUST',self.must,sep=' $ '))
result.append(self.key_list('MAY',self.may,sep=' $ '))
return '( %s )' % ''.join(result)
AttributeUsage = ldap.cidict.cidict({
'userApplication':0, # work-around for non-compliant schema
'userApplications':0,
'directoryOperation':1,
'distributedOperation':2,
'dSAOperation':3,
})
class AttributeType(SchemaElement):
"""
Arguments:
schema_element_str
String containing an AttributeTypeDescription
Class attributes:
oid
OID assigned to the attribute type
names
This list of strings contains all NAMEs of the attribute type
desc
This string contains description text (DESC) of the attribute type
obsolete
Integer flag (0 or 1) indicating whether the attribute type is marked
as OBSOLETE in the schema
single_value
Integer flag (0 or 1) indicating whether the attribute must
have only one value
syntax
String contains OID of the LDAP syntax assigned to the attribute type
no_user_mod
Integer flag (0 or 1) indicating whether the attribute is modifiable
by a client application
equality
String contains NAME or OID of the matching rule used for
checking whether attribute values are equal
substr
String contains NAME or OID of the matching rule used for
checking whether an attribute value contains another value
ordering
String contains NAME or OID of the matching rule used for
checking whether attribute values are lesser-equal than
usage
USAGE of an attribute type:
0 = userApplications
1 = directoryOperation,
2 = distributedOperation,
3 = dSAOperation
sup
This list of strings contains NAMEs or OIDs of attribute types
this attribute type is derived from
"""
schema_attribute = 'attributeTypes'
token_defaults = {
'NAME':(()),
'DESC':(None,),
'OBSOLETE':None,
'SUP':(()),
'EQUALITY':(None,),
'ORDERING':(None,),
'SUBSTR':(None,),
'SYNTAX':(None,),
'SINGLE-VALUE':None,
'COLLECTIVE':None,
'NO-USER-MODIFICATION':None,
'USAGE':('userApplications',)
}
def _set_attrs(self,l,d):
self.names = d['NAME']
self.desc = d['DESC'][0]
self.obsolete = d['OBSOLETE']!=None
self.sup = d['SUP']
self.equality = d['EQUALITY'][0]
self.ordering = d['ORDERING'][0]
self.substr = d['SUBSTR'][0]
try:
syntax = d['SYNTAX'][0]
except IndexError:
self.syntax = None
self.syntax_len = None
else:
if syntax is None:
self.syntax = None
self.syntax_len = None
else:
try:
self.syntax,syntax_len = d['SYNTAX'][0].split("{")
except ValueError:
self.syntax = d['SYNTAX'][0]
self.syntax_len = None
for i in l:
if i.startswith("{") and i.endswith("}"):
self.syntax_len=long(i[1:-1])
else:
self.syntax_len = long(syntax_len[:-1])
self.single_value = d['SINGLE-VALUE']!=None
self.collective = d['COLLECTIVE']!=None
self.no_user_mod = d['NO-USER-MODIFICATION']!=None
self.usage = AttributeUsage.get(d['USAGE'][0],0)
assert type(self.names)==TupleType
assert self.desc is None or type(self.desc)==StringType
assert type(self.sup)==TupleType,'attribute sup has type %s' % (type(self.sup))
assert type(self.obsolete)==BooleanType and (self.obsolete==0 or self.obsolete==1)
assert type(self.single_value)==BooleanType and (self.single_value==0 or self.single_value==1)
assert type(self.no_user_mod)==BooleanType and (self.no_user_mod==0 or self.no_user_mod==1)
assert self.syntax is None or type(self.syntax)==StringType
assert self.syntax_len is None or type(self.syntax_len)==type(0L)
return
def __str__(self):
result = [str(self.oid)]
result.append(self.key_list('NAME',self.names,quoted=1))
result.append(self.key_attr('DESC',self.desc,quoted=1))
result.append(self.key_list('SUP',self.sup,sep=' $ '))
result.append({0:'',1:' OBSOLETE'}[self.obsolete])
result.append(self.key_attr('EQUALITY',self.equality))
result.append(self.key_attr('ORDERING',self.ordering))
result.append(self.key_attr('SUBSTR',self.substr))
result.append(self.key_attr('SYNTAX',self.syntax))
if self.syntax_len!=None:
result.append(('{%d}' % (self.syntax_len))*(self.syntax_len>0))
result.append({0:'',1:' SINGLE-VALUE'}[self.single_value])
result.append({0:'',1:' COLLECTIVE'}[self.collective])
result.append({0:'',1:' NO-USER-MODIFICATION'}[self.no_user_mod])
result.append(
{
0:"",
1:" USAGE directoryOperation",
2:" USAGE distributedOperation",
3:" USAGE dSAOperation",
}[self.usage]
)
return '( %s )' % ''.join(result)
class LDAPSyntax(SchemaElement):
"""
SyntaxDescription
oid
OID assigned to the LDAP syntax
desc
This string contains description text (DESC) of the LDAP syntax
not_human_readable
Integer flag (0 or 1) indicating whether the attribute type is marked
as not human-readable (X-NOT-HUMAN-READABLE)
"""
schema_attribute = 'ldapSyntaxes'
token_defaults = {
'DESC':(None,),
'X-NOT-HUMAN-READABLE':(None,),
}
def _set_attrs(self,l,d):
self.desc = d['DESC'][0]
self.not_human_readable = \
NOT_HUMAN_READABLE_LDAP_SYNTAXES.has_key(self.oid) or \
d['X-NOT-HUMAN-READABLE'][0]=='TRUE'
assert self.desc is None or type(self.desc)==StringType
return
def __str__(self):
result = [str(self.oid)]
result.append(self.key_attr('DESC',self.desc,quoted=1))
result.append(
{0:'',1:" X-NOT-HUMAN-READABLE 'TRUE'"}[self.not_human_readable]
)
return '( %s )' % ''.join(result)
class MatchingRule(SchemaElement):
"""
Arguments:
schema_element_str
String containing an MatchingRuleDescription
Class attributes:
oid
OID assigned to the matching rule
names
This list of strings contains all NAMEs of the matching rule
desc
This string contains description text (DESC) of the matching rule
obsolete
Integer flag (0 or 1) indicating whether the matching rule is marked
as OBSOLETE in the schema
syntax
String contains OID of the LDAP syntax this matching rule is usable with
"""
schema_attribute = 'matchingRules'
token_defaults = {
'NAME':(()),
'DESC':(None,),
'OBSOLETE':None,
'SYNTAX':(None,),
}
def _set_attrs(self,l,d):
self.names = d['NAME']
self.desc = d['DESC'][0]
self.obsolete = d['OBSOLETE']!=None
self.syntax = d['SYNTAX'][0]
assert type(self.names)==TupleType
assert self.desc is None or type(self.desc)==StringType
assert type(self.obsolete)==BooleanType and (self.obsolete==0 or self.obsolete==1)
assert self.syntax is None or type(self.syntax)==StringType
return
def __str__(self):
result = [str(self.oid)]
result.append(self.key_list('NAME',self.names,quoted=1))
result.append(self.key_attr('DESC',self.desc,quoted=1))
result.append({0:'',1:' OBSOLETE'}[self.obsolete])
result.append(self.key_attr('SYNTAX',self.syntax))
return '( %s )' % ''.join(result)
class MatchingRuleUse(SchemaElement):
"""
Arguments:
schema_element_str
String containing an MatchingRuleUseDescription
Class attributes:
oid
OID of the accompanying matching rule
names
This list of strings contains all NAMEs of the matching rule
desc
This string contains description text (DESC) of the matching rule
obsolete
Integer flag (0 or 1) indicating whether the matching rule is marked
as OBSOLETE in the schema
applies
This list of strings contains NAMEs or OIDs of attribute types
for which this matching rule is used
"""
schema_attribute = 'matchingRuleUse'
token_defaults = {
'NAME':(()),
'DESC':(None,),
'OBSOLETE':None,
'APPLIES':(()),
}
def _set_attrs(self,l,d):
self.names = d['NAME']
self.desc = d['DESC'][0]
self.obsolete = d['OBSOLETE']!=None
self.applies = d['APPLIES']
assert type(self.names)==TupleType
assert self.desc is None or type(self.desc)==StringType
assert type(self.obsolete)==BooleanType and (self.obsolete==0 or self.obsolete==1)
assert type(self.applies)==TupleType
return
def __str__(self):
result = [str(self.oid)]
result.append(self.key_list('NAME',self.names,quoted=1))
result.append(self.key_attr('DESC',self.desc,quoted=1))
result.append({0:'',1:' OBSOLETE'}[self.obsolete])
result.append(self.key_list('APPLIES',self.applies,sep=' $ '))
return '( %s )' % ''.join(result)
class DITContentRule(SchemaElement):
"""
Arguments:
schema_element_str
String containing an DITContentRuleDescription
Class attributes:
oid
OID of the accompanying structural object class
names
This list of strings contains all NAMEs of the DIT content rule
desc
This string contains description text (DESC) of the DIT content rule
obsolete
Integer flag (0 or 1) indicating whether the DIT content rule is marked
as OBSOLETE in the schema
aux
This list of strings contains NAMEs or OIDs of all auxiliary
object classes usable in an entry of the object class
must
This list of strings contains NAMEs or OIDs of all attributes
an entry of the object class must have which may extend the
list of required attributes of the object classes of an entry
may
This list of strings contains NAMEs or OIDs of additional attributes
an entry of the object class may have which may extend the
list of optional attributes of the object classes of an entry
nots
This list of strings contains NAMEs or OIDs of attributes which
may not be present in an entry of the object class
"""
schema_attribute = 'dITContentRules'
token_defaults = {
'NAME':(()),
'DESC':(None,),
'OBSOLETE':None,
'AUX':(()),
'MUST':(()),
'MAY':(()),
'NOT':(()),
}
def _set_attrs(self,l,d):
self.names = d['NAME']
self.desc = d['DESC'][0]
self.obsolete = d['OBSOLETE']!=None
self.aux = d['AUX']
self.must = d['MUST']
self.may = d['MAY']
self.nots = d['NOT']
assert type(self.names)==TupleType
assert self.desc is None or type(self.desc)==StringType
assert type(self.obsolete)==BooleanType and (self.obsolete==0 or self.obsolete==1)
assert type(self.aux)==TupleType
assert type(self.must)==TupleType
assert type(self.may)==TupleType
assert type(self.nots)==TupleType
return
def __str__(self):
result = [str(self.oid)]
result.append(self.key_list('NAME',self.names,quoted=1))
result.append(self.key_attr('DESC',self.desc,quoted=1))
result.append({0:'',1:' OBSOLETE'}[self.obsolete])
result.append(self.key_list('AUX',self.aux,sep=' $ '))
result.append(self.key_list('MUST',self.must,sep=' $ '))
result.append(self.key_list('MAY',self.may,sep=' $ '))
result.append(self.key_list('NOT',self.nots,sep=' $ '))
return '( %s )' % ''.join(result)
class DITStructureRule(SchemaElement):
"""
Arguments:
schema_element_str
String containing an DITStructureRuleDescription
Class attributes:
ruleid
rule ID of the DIT structure rule (only locally unique)
names
This list of strings contains all NAMEs of the DIT structure rule
desc
This string contains description text (DESC) of the DIT structure rule
obsolete
Integer flag (0 or 1) indicating whether the DIT content rule is marked
as OBSOLETE in the schema
form
List of strings with NAMEs or OIDs of associated name forms
sup
List of strings with NAMEs or OIDs of allowed structural object classes
of superior entries in the DIT
"""
schema_attribute = 'dITStructureRules'
token_defaults = {
'NAME':(()),
'DESC':(None,),
'OBSOLETE':None,
'FORM':(None,),
'SUP':(()),
}
def set_id(self,element_id):
self.ruleid = element_id
def get_id(self):
return self.ruleid
def _set_attrs(self,l,d):
self.names = d['NAME']
self.desc = d['DESC'][0]
self.obsolete = d['OBSOLETE']!=None
self.form = d['FORM'][0]
self.sup = d['SUP']
assert type(self.names)==TupleType
assert self.desc is None or type(self.desc)==StringType
assert type(self.obsolete)==BooleanType and (self.obsolete==0 or self.obsolete==1)
assert type(self.form)==StringType
assert type(self.sup)==TupleType
return
def __str__(self):
result = [str(self.ruleid)]
result.append(self.key_list('NAME',self.names,quoted=1))
result.append(self.key_attr('DESC',self.desc,quoted=1))
result.append({0:'',1:' OBSOLETE'}[self.obsolete])
result.append(self.key_attr('FORM',self.form,quoted=0))
result.append(self.key_list('SUP',self.sup,sep=' $ '))
return '( %s )' % ''.join(result)
class NameForm(SchemaElement):
"""
Arguments:
schema_element_str
String containing an NameFormDescription
Class attributes:
oid
OID of the name form
names
This list of strings contains all NAMEs of the name form
desc
This string contains description text (DESC) of the name form
obsolete
Integer flag (0 or 1) indicating whether the name form is marked
as OBSOLETE in the schema
form
List of strings with NAMEs or OIDs of associated name forms
oc
String with NAME or OID of structural object classes this name form
is usable with
must
This list of strings contains NAMEs or OIDs of all attributes
an RDN must contain
may
This list of strings contains NAMEs or OIDs of additional attributes
an RDN may contain
"""
schema_attribute = 'nameForms'
token_defaults = {
'NAME':(()),
'DESC':(None,),
'OBSOLETE':None,
'OC':(None,),
'MUST':(()),
'MAY':(()),
}
def _set_attrs(self,l,d):
self.names = d['NAME']
self.desc = d['DESC'][0]
self.obsolete = d['OBSOLETE']!=None
self.oc = d['OC'][0]
self.must = d['MUST']
self.may = d['MAY']
assert type(self.names)==TupleType
assert self.desc is None or type(self.desc)==StringType
assert type(self.obsolete)==BooleanType and (self.obsolete==0 or self.obsolete==1)
assert type(self.oc)==StringType
assert type(self.must)==TupleType
assert type(self.may)==TupleType
return
def __str__(self):
result = [str(self.oid)]
result.append(self.key_list('NAME',self.names,quoted=1))
result.append(self.key_attr('DESC',self.desc,quoted=1))
result.append({0:'',1:' OBSOLETE'}[self.obsolete])
result.append(self.key_attr('OC',self.oc))
result.append(self.key_list('MUST',self.must,sep=' $ '))
result.append(self.key_list('MAY',self.may,sep=' $ '))
return '( %s )' % ''.join(result)
class Entry(UserDict.UserDict):
"""
Schema-aware implementation of an LDAP entry class.
Mainly it holds the attributes in a string-keyed dictionary with
the OID as key.
"""
def __init__(self,schema,dn,entry):
self._keytuple2attrtype = {}
self._attrtype2keytuple = {}
self._s = schema
self.dn = dn
UserDict.UserDict.__init__(self,{})
self.update(entry)
def _at2key(self,nameoroid):
"""
Return tuple of OID and all sub-types of attribute type specified
in nameoroid.
"""
try:
# Mapping already in cache
return self._attrtype2keytuple[nameoroid]
except KeyError:
# Mapping has to be constructed
oid = self._s.getoid(ldap.schema.AttributeType,nameoroid)
l = nameoroid.lower().split(';')
l[0] = oid
t = tuple(l)
self._attrtype2keytuple[nameoroid] = t
return t
def update(self,dict):
for key in dict.keys():
self[key] = dict[key]
def __contains__(self,key):
return self.has_key(key)
def __getitem__(self,nameoroid):
return self.data[self._at2key(nameoroid)]
def __setitem__(self,nameoroid,attr_values):
k = self._at2key(nameoroid)
self._keytuple2attrtype[k] = nameoroid
self.data[k] = attr_values
def __delitem__(self,nameoroid):
k = self._at2key(nameoroid)
del self.data[k]
del self._attrtype2keytuple[nameoroid]
del self._keytuple2attrtype[k]
def has_key(self,nameoroid):
k = self._at2key(nameoroid)
return self.data.has_key(k)
def get(self,nameoroid,failobj):
try:
return self[nameoroid]
except KeyError:
return failobj
def keys(self):
return self._keytuple2attrtype.values()
def items(self):
return [
(k,self[k])
for k in self.keys()
]
def attribute_types(
self,attr_type_filter=None,raise_keyerror=1
):
"""
Convenience wrapper around SubSchema.attribute_types() which
passes object classes of this particular entry as argument to
SubSchema.attribute_types()
"""
return self._s.attribute_types(
self.get('objectClass',[]),attr_type_filter,raise_keyerror
)
python-ldap-2.4.10/Lib/ldap/schema/.cvsignore 0000644 0000764 0000144 00000000025 07535750774 021530 0 ustar michael users 0000000 0000000 *.pyc
*.pyo
*.bck
*~
python-ldap-2.4.10/Lib/ldap/schema/__init__.py 0000644 0000764 0000144 00000000502 11233034606 021614 0 ustar michael users 0000000 0000000 """
ldap.schema - LDAPv3 schema handling
See http://www.python-ldap.org/ for details.
\$Id: __init__.py,v 1.7 2009/07/26 11:09:58 stroeder Exp $
"""
from ldap import __version__
from ldap.schema.subentry import SubSchema,SCHEMA_ATTRS,SCHEMA_CLASS_MAPPING,SCHEMA_ATTR_MAPPING,urlfetch
from ldap.schema.models import *
python-ldap-2.4.10/Lib/ldap/schema/tokenizer.py 0000644 0000764 0000144 00000003751 11176114343 022103 0 ustar michael users 0000000 0000000 """
ldap.schema.tokenizer - Low-level parsing functions for schema element strings
See http://www.python-ldap.org/ for details.
\$Id: tokenizer.py,v 1.13 2009/04/29 18:13:55 stroeder Exp $
"""
def split_tokens(s,keywordDict):
"""
Returns list of syntax elements with quotes and spaces
stripped.
"""
result = []
result_append = result.append
s_len = len(s)
i = 0
while istart:
result_append(s[start:i])
result_append(s[i])
i +=1 # Consume parentheses
start = i
elif s[i]==" " or s[i]=="$":
if i>start:
result_append(s[start:i])
i +=1
# Consume more space chars
while istart:
result_append(s[start:i])
i +=1
if i>=s_len:
break
start = i
while i=start:
result_append(s[start:i])
i +=1
return result # split_tokens()
def extract_tokens(l,known_tokens):
"""
Returns dictionary of known tokens with all values
"""
assert l[0].strip()=="(" and l[-1].strip()==")",ValueError(l)
result = {}
result_has_key = result.has_key
result.update(known_tokens)
i = 0
l_len = len(l)
while i