2013-06-27 16 views
1

我使用python-ldap來搜索ActiveDirectory,就好像它是任何常規的LDAP服務器一樣。它的工作原理,SSL,身份驗證和一切。創建一個「序列序列」ldap.controls.RequestControl對象

現在我想使用server side sort request control defined in RFC 2891,它具有OID 1.2.840.113556.1.4.473

Python-ldap不支持開箱即用的控件,所以我必須自己創建它。我這樣做:

server_side_sort = ldap.controls.RequestControl('1.2.840.113556.1.4.473', True) 

但我不知道如何計算encodedControlValue參數,這是the BER-encoded ASN.1 control value

我看到,pyasn1有很多部分來對它進行編碼,如univ.SequenceOf,univ.Sequenceuniv.Boolean。望着RFC2251 module of pyasn1,我想出了這個:

class LDAPString(univ.OctetString): pass 

class AttributeDescription(LDAPString): pass 

class MatchingRuleId(LDAPString): pass 

class ServerSideSortOnName(univ.Sequence): 
    componentType = namedtype.NamedTypes(
     namedtype.NamedType('attributeDesc', AttributeDescription('name')), 
     namedtype.NamedType('reverseOrder', univ.Boolean(False))) 

class ServerSideSortControl(univ.SequenceOf): 
    componentType = ServerSideSortOnName() 

sss = ServerSideSortControl() 

serversidesort = ldap.controls.RequestControl('1.2.840.113556.1.4.473',True,sss) 

名稱可能不會被索引,我知道了。我認爲它可以幫助調試以匹配base64 value shown on this MSDN snippet

但當我添加此控制(這甚至可能不會是有效的),以ldap.search_ext,我得到的錯誤TypeError: ('expected a string', ServerSideSortControl())

我怎樣才能創建一個可在屬性name服務器端排序控制值中的python-LDAP ldap.search_ext會接受,使用pyasn1或類似?

回答

2

您必須在univ.SequenceOf中嵌套univ.Sequence並實現encodeControlValue,該函數返回服務器期望的BER編碼控件。

class SSSRequest(univ.SequenceOf): 
    componentType = univ.Sequence() 

class SSSRequestSequence(univ.Sequence): 
    componentType = namedtype.NamedTypes(
     namedtype.NamedType('attributeType', univ.OctetString()), 
    ) 

class SSS_CONTROL_REQUEST(LDAPControl): 
    def __init__(self,controlType,criticality,controlValue=None,encodedControlValue=None): 
     LDAPControl.__init__(self,controlType,criticality,controlValue,encodedControlValue) 

    def encodeControlValue(self): 
     sss = SSSRequest() 

     for k in self.controlValue: 
      Skey = SSSRequestSequence() 
      Skey.setComponentByName('attributeType', k) 
      sss.setComponentByPosition(0, Skey) 
     return encoder.encode(sss) 

    def decodeControlValue(self,encodedValue): 
     sssr = decoder.decode(encodedValue)[0] 
     rsp = SSSResponse() 
     for n, v in enumerate(sssr): 
      try: 
       rsp.setComponentByPosition(n, int(v)) 
      except Exception, e: 
       print str(e) 
     if rsp.success: 
      return True 
     return rsp.error 

if __name__ == '__main__': 
    SSSREQUEST_OID = '1.2.840.113556.1.4.473' 
    sss = SSS_CONTROL_REQUEST(SSSREQUEST_OID, False, ['cn']) 
    srv = ldap.open('localhost') 
    srv.simple_bind_s() 
    id = srv.search_ext('ou=people,dc=example,dc=com', ldap.SCOPE_SUBTREE, filterstr='(objectClass=user)', serverctrls=[sss]) 
    print srv.result3(id) 

實現相反的順序排序留作exercice)

代碼是與Windows服務器上運行的AD-LDS實例2008 R2,64位(測試成功,但你必須做出的綁定非匿名)。

+0

謝謝!您的原始代碼沒有按原樣運行。我用我的機器上的一個更新了它。 – ixe013