Skip to content

Commit

Permalink
Added ldap.controls.deref implementing support for dereference control
Browse files Browse the repository at this point in the history
  • Loading branch information
stroeder committed Sep 19, 2015
1 parent 6209906 commit 96525a0
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Lib/
argument add_ctrls which is internally passed to LDAPObject.result4()
and lets the method also return response control along with the search
results.
* Added ldap.controls.deref implementing support for dereference control

Tests/
* Unit tests for module ldif (thanks to Petr Viktorin)
Expand Down Expand Up @@ -1194,4 +1195,4 @@ Released 2.0.0pre02 2002-02-01
----------------------------------------------------------------
Released 1.10alpha3 2000-09-19

$Id: CHANGES,v 1.354 2015/09/18 20:20:32 stroeder Exp $
$Id: CHANGES,v 1.355 2015/09/19 13:38:30 stroeder Exp $
47 changes: 47 additions & 0 deletions Demo/pyasn1/derefcontrol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env python
"""
This sample script demonstrates the use of the dereference control
(see https://tools.ietf.org/html/draft-masarati-ldap-deref)
Requires module pyasn1 (see http://pyasn1.sourceforge.net/)
"""

import pprint,ldap,ldap.modlist,ldap.resiter

from ldap.controls.deref import DereferenceControl

uri = "ldap://localhost:2071/"

class MyLDAPObject(ldap.ldapobject.LDAPObject,ldap.resiter.ResultProcessor):
pass


l = MyLDAPObject(uri,trace_level=2)
l.simple_bind_s('uid=diradm,dc=example,dc=com','testsecret')

dc = DereferenceControl(
True,
{
'member':[
'uid',
'description',
# 'cn',
# 'mail',
],
}
)
print dc._derefSpecs().prettyPrint()
dc.encodeControlValue()

msg_id = l.search_ext(
'dc=example,dc=com',
ldap.SCOPE_SUBTREE,
'(objectClass=groupOfNames)',
attrlist=['cn','objectClass','member','description'],
serverctrls = [dc]
)

for res_type,res_data,res_msgid,res_controls in l.allresults(msg_id,add_ctrls=1):
for dn,entry,deref_control in res_data:
# process dn and entry
print dn,entry['objectClass']
125 changes: 125 additions & 0 deletions Lib/ldap/controls/deref.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# -*- coding: utf-8 -*-
"""
ldap.controls.deref - classes for
(see https://tools.ietf.org/html/draft-masarati-ldap-deref)
See http://www.python-ldap.org/ for project details.
$Id: deref.py,v 1.1 2015/09/19 13:38:30 stroeder Exp $
"""

__all__ = [
'DEREF_CONTROL_OID',
'DereferenceControl',
]

import ldap.controls
from ldap.controls import LDAPControl,KNOWN_RESPONSE_CONTROLS

import pyasn1_modules.rfc2251
from pyasn1.type import namedtype,univ,tag
from pyasn1.codec.ber import encoder,decoder
from pyasn1_modules.rfc2251 import LDAPDN,AttributeDescription,AttributeDescriptionList,AttributeValue


DEREF_CONTROL_OID = '1.3.6.1.4.1.4203.666.5.16'


# Request types
#---------------------------------------------------------------------------

# For compability with ASN.1 declaration in I-D
AttributeList = AttributeDescriptionList

class DerefSpec(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType(
'derefAttr',
AttributeDescription()
),
namedtype.NamedType(
'attributes',
AttributeList()
),
)

class DerefSpecs(univ.SequenceOf):
componentType = DerefSpec()

# Response types
#---------------------------------------------------------------------------


class AttributeValues(univ.SetOf):
componentType = AttributeValue()


class PartialAttribute(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeDescription()),
namedtype.NamedType('vals', AttributeValues()),
)


class PartialAttributeList(univ.SequenceOf):
componentType = PartialAttribute()
tagSet = univ.Sequence.tagSet.tagImplicitly(
tag.Tag(tag.tagClassContext,tag.tagFormatConstructed,0)
)


class DerefRes(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('derefAttr', AttributeDescription()),
namedtype.NamedType('derefVal', LDAPDN()),
namedtype.OptionalNamedType('attrVals', PartialAttributeList()),
)


class DerefResultControlValue(univ.SequenceOf):
componentType = DerefRes()


class DereferenceControl(LDAPControl):
controlType = DEREF_CONTROL_OID

def __init__(self,criticality=False,derefSpecs=None):
LDAPControl.__init__(self,self.controlType,criticality)
self.derefSpecs = derefSpecs or {}

def _derefSpecs(self):
deref_specs = DerefSpecs()
i = 0
for deref_attr,deref_attribute_names in self.derefSpecs.items():
deref_spec = DerefSpec()
deref_attributes = AttributeList()
for j in range(len(deref_attribute_names)):
deref_attributes.setComponentByPosition(j,deref_attribute_names[j])
deref_spec.setComponentByName('derefAttr',AttributeDescription(deref_attr))
deref_spec.setComponentByName('attributes',deref_attributes)
deref_specs.setComponentByPosition(i,deref_spec)
i += 1
return deref_specs

def encodeControlValue(self):
return encoder.encode(self._derefSpecs())

def decodeControlValue(self,encodedControlValue):
decodedValue,_ = decoder.decode(encodedControlValue,asn1Spec=DerefResultControlValue())
print decodedValue.prettyPrint()
self.derefRes = {}
for deref_res in decodedValue:
deref_attr,deref_val,deref_vals = deref_res
partial_attrs_dict = dict([
(str(t),map(str,v))
for t,v in deref_vals or []
])
try:
self.derefRes[str(deref_attr)].append((str(deref_val),partial_attrs_dict))
except KeyError:
self.derefRes[str(deref_attr)] = [(str(deref_val),partial_attrs_dict)]
import pprint
pprint.pprint(self.derefRes)


KNOWN_RESPONSE_CONTROLS[DereferenceControl.controlType] = DereferenceControl
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
See http://www.python-ldap.org/ for details.
$Id: setup.py,v 1.72 2014/03/12 20:29:23 stroeder Exp $
$Id: setup.py,v 1.73 2015/09/19 13:38:30 stroeder Exp $
"""

has_setuptools = False
Expand Down Expand Up @@ -150,6 +150,7 @@ class OpenLDAP2:
'ldap',
'ldap.async',
'ldap.controls',
'ldap.controls.deref',
'ldap.controls.libldap',
'ldap.controls.openldap',
'ldap.controls.ppolicy',
Expand Down

0 comments on commit 96525a0

Please sign in to comment.