Пример #1
0
 def _makeResultList(self, s):
     berdecoder = pureldap.LDAPBERDecoderContext_TopLevel(
         inherit=pureldap.LDAPBERDecoderContext_LDAPMessage(
             fallback=pureldap.LDAPBERDecoderContext(fallback=pureber.BERDecoderContext()),
             inherit=pureldap.LDAPBERDecoderContext(fallback=pureber.BERDecoderContext())))
     buffer = s
     value = []
     while 1:
         o, bytes = pureber.berDecodeObject(berdecoder, buffer)
         buffer = buffer[bytes:]
         if not o:
             break
         value.append(o.toWire())
     return value
Пример #2
0
def getldappath(buff):
    berdecoder = pureldap.LDAPBERDecoderContext_TopLevel(
        inherit=pureldap.LDAPBERDecoderContext_LDAPMessage(
            fallback=pureldap.LDAPBERDecoderContext(
                fallback=pureber.BERDecoderContext()),
            inherit=pureldap.LDAPBERDecoderContext(
                fallback=pureber.BERDecoderContext())))
    # buff=b'\x30\x81\xa9\x02\x01\x02c\x81\x86\x04fAaBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\x01\x00\n\x01\x03\x02\x01\x00\x02\x01\x00\x01\x01\x00\x87\x0bobjectClass0\x00\xa0\x1b0\x19\x04\x172.16.840.1.113730.3.4.2'
    try:
        o, bytes = pureber.berDecodeObject(berdecoder, buff)
        return o.value.baseObject
    except pureber.BERExceptionInsufficientData as ex:
        logger.warning("get error:{}".format(ex))
        return None
Пример #3
0
 def _makeResultList(self, s):
     berdecoder = pureldap.LDAPBERDecoderContext_TopLevel(
         inherit=pureldap.LDAPBERDecoderContext_LDAPMessage(
             fallback=pureldap.LDAPBERDecoderContext(
                 fallback=pureber.BERDecoderContext()),
             inherit=pureldap.LDAPBERDecoderContext(
                 fallback=pureber.BERDecoderContext())))
     buffer = s
     value = []
     while 1:
         try:
             o, bytes = pureber.berDecodeObject(berdecoder, buffer)
         except pureber.BERExceptionInsufficientData:
             o, bytes = None, 0
         buffer = buffer[bytes:]
         if not o:
             break
         value.append(str(o))
     return value
Пример #4
0
 def testPartial(self):
     """LDAPClass(encoded="...") with too short input should throw BERExceptionInsufficientData"""
     for klass, args, kwargs, decoder, encoded in self.knownValues:
         if decoder is None:
             decoder = pureldap.LDAPBERDecoderContext(
                 fallback=pureber.BERDecoderContext())
         for i in xrange(1, len(encoded)):
             m = s(*encoded)[:i]
             self.assertRaises(pureber.BERExceptionInsufficientData,
                               pureber.berDecodeObject, decoder, m)
         self.assertEquals((None, 0), pureber.berDecodeObject(decoder, ''))
Пример #5
0
 def test_length(self):
     """LDAPFilter_substrings.substrings behaves like a proper list."""
     decoder = pureldap.LDAPBERDecoderContext(
         fallback=pureber.BERDecoderContext())
     filt = pureldap.LDAPFilter_substrings.fromBER(
         tag=pureldap.LDAPFilter_substrings.tag,
         content=s(0x04, 4, 'mail', 0x30, 6, 0x80, 4, 'foo@'),
         berdecoder=decoder)
     # The confusion that used to occur here was because
     # filt.substrings was left as a BERSequence, which under the
     # current str()-to-wire-protocol system had len() > 1 even
     # when empty, and that tripped e.g. entry.match()
     self.assertEquals(len(filt.substrings), 1)
Пример #6
0
    def testFromLDAP(self):
        """LDAPClass(encoded="...") should give known result with known input"""
        for klass, args, kwargs, decoder, encoded in self.knownValues:
            if decoder is None:
                decoder = pureldap.LDAPBERDecoderContext(
                    fallback=pureber.BERDecoderContext())
            m=s(*encoded)
            result, bytes = pureber.berDecodeObject(decoder, m)
            self.assertEqual(bytes, len(m))

            shouldBe = klass(*args, **kwargs)
            assert result.toWire() == shouldBe.toWire(), \
                   "Class %s(*%s, **%s) doesn't decode properly: " \
                   "%s != %s" % (klass.__name__,
                                 repr(args), repr(kwargs),
                                 repr(result), repr(shouldBe))
Пример #7
0
class ServiceBindingProxy(unittest.TestCase):
    berdecoder = pureldap.LDAPBERDecoderContext_TopLevel(
        inherit=pureldap.LDAPBERDecoderContext_LDAPMessage(
            fallback=pureldap.LDAPBERDecoderContext(
                fallback=pureber.BERDecoderContext()),
            inherit=pureldap.LDAPBERDecoderContext(
                fallback=pureber.BERDecoderContext())))

    def createServer(self, services, fallback=None, responses=[]):
        server = testutil.createServer(
            lambda config: svcbindproxy.ServiceBindingProxy(
                config=config,
                services=services,
                fallback=fallback,
            ),
            baseDN='dc=example,dc=com',
            *responses)
        server.now = '20050213140302Z'
        server.timestamp = lambda: server.now
        return server

    def test_bind_noMatchingServicesFound_noFallback(self):
        server = self.createServer(
            services=[
                'svc1',
                'svc2',
                'svc3',
            ],
            fallback=False,
            responses=[
                [pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode)],
                [pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode)],
                [pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode)],
            ])
        server.dataReceived(
            pureldap.LDAPMessage(pureldap.LDAPBindRequest(
                dn='cn=jack,dc=example,dc=com', auth='s3krit'),
                                 id=4).toWire())
        reactor.iterate()  #TODO
        client = server.client

        client.assertSent(
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc1)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc2)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc3)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
        )
        self.assertEqual(
            server.transport.value(),
            pureldap.LDAPMessage(pureldap.LDAPBindResponse(
                resultCode=ldaperrors.LDAPInvalidCredentials.resultCode),
                                 id=4).toWire())

    def test_bind_noMatchingServicesFound_fallback_success(self):
        server = self.createServer(
            services=[
                'svc1',
                'svc2',
                'svc3',
            ],
            fallback=True,
            responses=[
                [pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode)],
                [pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode)],
                [pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode)],
                [
                    pureldap.LDAPBindResponse(
                        resultCode=ldaperrors.Success.resultCode)
                ],
            ])
        server.dataReceived(
            pureldap.LDAPMessage(pureldap.LDAPBindRequest(
                dn='cn=jack,dc=example,dc=com', auth='s3krit'),
                                 id=4).toWire())
        reactor.iterate()  #TODO
        client = server.client

        client.assertSent(
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc1)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc2)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc3)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPBindRequest(dn='cn=jack,dc=example,dc=com',
                                     auth='s3krit'))
        self.assertEqual(
            server.transport.value(),
            pureldap.LDAPMessage(pureldap.LDAPBindResponse(
                resultCode=ldaperrors.Success.resultCode),
                                 id=4).toWire())

    def test_bind_noMatchingServicesFound_fallback_badAuth(self):
        server = self.createServer(
            services=[
                'svc1',
                'svc2',
                'svc3',
            ],
            fallback=True,
            responses=[
                [pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode)],
                [pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode)],
                [pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode)],
                [
                    pureldap.LDAPBindResponse(
                        resultCode=ldaperrors.LDAPInvalidCredentials.resultCode
                    ),
                ],
            ])
        server.dataReceived(
            pureldap.LDAPMessage(pureldap.LDAPBindRequest(
                dn='cn=jack,dc=example,dc=com', auth='wrong-s3krit'),
                                 id=4).toWire())
        reactor.iterate()  #TODO
        client = server.client

        client.assertSent(
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc1)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc2)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc3)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPBindRequest(dn='cn=jack,dc=example,dc=com',
                                     auth='wrong-s3krit'))
        self.assertEqual(
            server.transport.value(),
            pureldap.LDAPMessage(pureldap.LDAPBindResponse(
                resultCode=ldaperrors.LDAPInvalidCredentials.resultCode),
                                 id=4).toWire())

    def test_bind_match_success(self):
        server = self.createServer(
            services=[
                'svc1',
                'svc2',
                'svc3',
            ],
            fallback=True,
            responses=[

                # svc1
                [
                    pureldap.LDAPSearchResultEntry(
                        r'cn=svc1+owner=cn\=jack\,dc\=example\,dc\=com,dc=example,dc=com',
                        attributes=[]),
                    pureldap.LDAPSearchResultDone(
                        ldaperrors.Success.resultCode)
                ],
                [
                    pureldap.LDAPBindResponse(
                        resultCode=ldaperrors.Success.resultCode)
                ],
            ])

        server.dataReceived(
            pureldap.LDAPMessage(pureldap.LDAPBindRequest(
                dn='cn=jack,dc=example,dc=com', auth='secret'),
                                 id=4).toWire())
        reactor.iterate()  #TODO
        client = server.client

        client.assertSent(
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc1)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPBindRequest(
                dn=
                r'cn=svc1+owner=cn\=jack\,dc\=example\,dc\=com,dc=example,dc=com',
                auth='secret'),
        )
        self.assertEqual(
            server.transport.value(),
            pureldap.LDAPMessage(pureldap.LDAPBindResponse(
                resultCode=ldaperrors.Success.resultCode,
                matchedDN='cn=jack,dc=example,dc=com'),
                                 id=4).toWire())

    def test_bind_match_success_later(self):
        server = self.createServer(
            services=[
                'svc1',
                'svc2',
                'svc3',
            ],
            fallback=True,
            responses=[

                # svc1
                [
                    pureldap.LDAPSearchResultEntry(
                        r'cn=svc1+owner=cn\=jack\,dc\=example\,dc\=com,dc=example,dc=com',
                        attributes=[]),
                    pureldap.LDAPSearchResultDone(
                        ldaperrors.Success.resultCode)
                ],
                [
                    pureldap.LDAPBindResponse(
                        resultCode=ldaperrors.LDAPInvalidCredentials.resultCode
                    )
                ],

                # svc2
                [pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode)],

                # svc3
                [
                    pureldap.LDAPSearchResultEntry(
                        r'cn=svc3+owner=cn\=jack\,dc\=example\,dc\=com,dc=example,dc=com',
                        attributes=[]),
                    pureldap.LDAPSearchResultDone(
                        ldaperrors.Success.resultCode)
                ],
                [
                    pureldap.LDAPBindResponse(
                        resultCode=ldaperrors.Success.resultCode)
                ],
            ])

        server.dataReceived(
            pureldap.LDAPMessage(pureldap.LDAPBindRequest(
                dn='cn=jack,dc=example,dc=com', auth='secret'),
                                 id=4).toWire())
        reactor.iterate()  #TODO
        client = server.client

        client.assertSent(
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc1)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPBindRequest(
                dn=
                r'cn=svc1+owner=cn\=jack\,dc\=example\,dc\=com,dc=example,dc=com',
                auth='secret'),
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc2)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc3)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPBindRequest(
                dn=
                'cn=svc3+owner=cn\=jack\,dc\=example\,dc\=com,dc=example,dc=com',
                auth='secret'),
        )
        self.assertEqual(
            server.transport.value(),
            pureldap.LDAPMessage(pureldap.LDAPBindResponse(
                resultCode=ldaperrors.Success.resultCode,
                matchedDN='cn=jack,dc=example,dc=com'),
                                 id=4).toWire())

    def test_bind_match_badAuth(self):
        server = self.createServer(
            services=[
                'svc1',
                'svc2',
                'svc3',
            ],
            fallback=True,
            responses=[

                # svc1
                [
                    pureldap.LDAPSearchResultEntry(
                        r'cn=svc1+owner=cn\=jack\,dc\=example\,dc\=com,dc=example,dc=com',
                        attributes=[]),
                    pureldap.LDAPSearchResultDone(
                        ldaperrors.Success.resultCode)
                ],
                [
                    pureldap.LDAPBindResponse(
                        resultCode=ldaperrors.LDAPInvalidCredentials.resultCode
                    )
                ],

                # svc2
                [pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode)],

                # svc3
                [
                    pureldap.LDAPSearchResultEntry(
                        r'cn=svc3+owner=cn\=jack\,dc\=example\,dc\=com,dc=example,dc=com',
                        attributes=[]),
                    pureldap.LDAPSearchResultDone(
                        ldaperrors.Success.resultCode)
                ],
                [
                    pureldap.LDAPBindResponse(
                        resultCode=ldaperrors.LDAPInvalidCredentials.resultCode
                    )
                ],
                [
                    pureldap.LDAPBindResponse(
                        resultCode=ldaperrors.LDAPInvalidCredentials.resultCode
                    )
                ],
            ])

        server.dataReceived(
            pureldap.LDAPMessage(pureldap.LDAPBindRequest(
                dn='cn=jack,dc=example,dc=com', auth='wrong-s3krit'),
                                 id=4).toWire())
        reactor.iterate()  #TODO
        client = server.client

        client.assertSent(
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc1)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPBindRequest(
                dn=
                r'cn=svc1+owner=cn\=jack\,dc\=example\,dc\=com,dc=example,dc=com',
                auth='wrong-s3krit'),
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc2)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPSearchRequest(
                baseObject='dc=example,dc=com',
                derefAliases=0,
                sizeLimit=0,
                timeLimit=0,
                typesOnly=0,
                filter=ldapfilter.parseFilter(
                    '(&' + '(objectClass=serviceSecurityObject)' +
                    '(owner=cn=jack,dc=example,dc=com)' + '(cn=svc3)' +
                    ('(|(!(validFrom=*))(validFrom<=%s))' % server.now) +
                    ('(|(!(validUntil=*))(validUntil>=%s))' % server.now) +
                    ')'),
                attributes=('1.1', )),
            pureldap.LDAPBindRequest(
                dn=
                'cn=svc3+owner=cn\=jack\,dc\=example\,dc\=com,dc=example,dc=com',
                auth='wrong-s3krit'),
            pureldap.LDAPBindRequest(version=3,
                                     dn='cn=jack,dc=example,dc=com',
                                     auth='wrong-s3krit'),
        )
        self.assertEqual(
            server.transport.value(),
            pureldap.LDAPMessage(pureldap.LDAPBindResponse(
                resultCode=ldaperrors.LDAPInvalidCredentials.resultCode),
                                 id=4).toWire())
Пример #8
0
class BaseLDAPServer(protocol.Protocol):
    debug = False

    def __init__(self):
        self.buffer = ''
        self.connected = None

    berdecoder = pureldap.LDAPBERDecoderContext_TopLevel(
        inherit=pureldap.LDAPBERDecoderContext_LDAPMessage(
            fallback=pureldap.LDAPBERDecoderContext(
                fallback=pureber.BERDecoderContext()),
            inherit=pureldap.LDAPBERDecoderContext(
                fallback=pureber.BERDecoderContext())))

    def dataReceived(self, recd):
        self.buffer += recd
        while 1:
            try:
                o, bytes = pureber.berDecodeObject(
                    self.berdecoder, self.buffer)
            except pureber.BERExceptionInsufficientData:
                o, bytes = None, 0
            self.buffer = self.buffer[bytes:]
            if o is None:
                break
            self.handle(o)

    def connectionMade(self):
        """TCP connection has opened"""
        self.connected = 1

    def connectionLost(self, reason=protocol.connectionDone):
        """Called when TCP connection has been lost"""
        self.connected = 0

    def queue(self, id, op):
        if not self.connected:
            raise LDAPServerConnectionLostException()
        msg = pureldap.LDAPMessage(op, id=id)
        if self.debug:
            log.msg('S->C %s' % repr(msg), debug=True)
        self.transport.write(str(msg))

    def unsolicitedNotification(self, msg):
        log.msg("Got unsolicited notification: %s" % repr(msg))

    def checkControls(self, controls):
        if controls is not None:
            for controlType, criticality, controlValue in controls:
                if criticality:
                    raise ldaperrors.LDAPUnavailableCriticalExtension(
                        'Unknown control %s' % controlType)

    def handleUnknown(self, request, controls, callback):
        log.msg('Unknown request: %r' % request)
        msg = pureldap.LDAPExtendedResponse(
            resultCode=ldaperrors.LDAPProtocolError.resultCode,
            responseName='1.3.6.1.4.1.1466.20036',
            errorMessage='Unknown request')
        return msg

    def _cbLDAPError(self, reason, name):
        reason.trap(ldaperrors.LDAPException)
        return self._callErrorHandler(name=name,
                                      resultCode=reason.value.resultCode,
                                      errorMessage=reason.value.message)

    def _cbHandle(self, response, id):
        if response is not None:
            self.queue(id, response)

    def failDefault(self, resultCode, errorMessage):
        return pureldap.LDAPExtendedResponse(
            resultCode=resultCode,
            responseName='1.3.6.1.4.1.1466.20036',
            errorMessage=errorMessage)

    def _callErrorHandler(self, name, resultCode, errorMessage):
        errh = getattr(self, 'fail_'+name, self.failDefault)
        return errh(resultCode=resultCode, errorMessage=errorMessage)

    def _cbOtherError(self, reason, name):
        return self._callErrorHandler(
            name=name,
            resultCode=ldaperrors.LDAPProtocolError.resultCode,
            errorMessage=reason.getErrorMessage())

    def handle(self, msg):
        assert isinstance(msg.value, pureldap.LDAPProtocolRequest)
        if self.debug:
            log.msg('S<-C %s' % repr(msg), debug=True)

        if msg.id == 0:
            self.unsolicitedNotification(msg.value)
        else:
            name = msg.value.__class__.__name__
            handler = getattr(self, 'handle_'+name, self.handleUnknown)
            d = defer.maybeDeferred(handler,
                                    msg.value,
                                    msg.controls,
                                    lambda response: self._cbHandle(
                                        response, msg.id))
            d.addErrback(self._cbLDAPError, name)
            d.addErrback(defer.logError)
            d.addErrback(self._cbOtherError, name)
            d.addCallback(self._cbHandle, msg.id)
Пример #9
0
class LDAPClient(protocol.Protocol):
    """An LDAP client"""
    debug = False

    def __init__(self):
        self.onwire = {}
        self.buffer = ''
        self.connected = None

    berdecoder = pureldap.LDAPBERDecoderContext_TopLevel(
        inherit=pureldap.LDAPBERDecoderContext_LDAPMessage(
            fallback=pureldap.LDAPBERDecoderContext(
                fallback=pureber.BERDecoderContext()),
            inherit=pureldap.LDAPBERDecoderContext(
                fallback=pureber.BERDecoderContext())))

    def dataReceived(self, recd):
        self.buffer += recd
        while 1:
            try:
                o, bytes = pureber.berDecodeObject(self.berdecoder,
                                                   self.buffer)
            except pureber.BERExceptionInsufficientData:
                o, bytes = None, 0
            self.buffer = self.buffer[bytes:]
            if not o:
                break
            self.handle(o)

    def connectionMade(self):
        """TCP connection has opened"""
        self.connected = 1

    def connectionLost(self, reason=protocol.connectionDone):
        """Called when TCP connection has been lost"""
        self.connected = 0
        # notify handlers of operations in flight
        while self.onwire:
            k, v = self.onwire.popitem()
            d, _, _, _ = v
            d.errback(reason)

    def _send(self, op):
        if not self.connected:
            raise LDAPClientConnectionLostException()
        msg = pureldap.LDAPMessage(op)
        if self.debug:
            log.debug('C->S %s' % repr(msg))
        assert not self.onwire.has_key(msg.id)
        return msg

    def _cbSend(self, msg, d):
        d.callback(msg)
        return True

    def send(self, op):
        """
        Send an LDAP operation to the server.

        @param op: the operation to send

        @type op: LDAPProtocolRequest

        @return: the response from server

        @rtype: Deferred LDAPProtocolResponse
        """
        msg = self._send(op)
        assert op.needs_answer
        d = defer.Deferred()
        self.onwire[msg.id] = (d, None, None, None)
        self.transport.write(str(msg))
        return d

    def send_multiResponse(self, op, handler, *args, **kwargs):
        """
        Send an LDAP operation to the server, expecting one or more
        responses.

        @param op: the operation to send

        @type op: LDAPProtocolRequest

        @param handler: a callable that will be called for each
        response. It should return a boolean, whether this was the
        final response.

        @param args: positional arguments to pass to handler

        @param kwargs: keyword arguments to pass to handler

        @return: the result from the last handler as a deferred that
        completes when the last response has been received

        @rtype: Deferred LDAPProtocolResponse
        """
        msg = self._send(op)
        assert op.needs_answer
        d = defer.Deferred()
        self.onwire[msg.id] = (d, handler, args, kwargs)
        self.transport.write(str(msg))
        return d

    def send_noResponse(self, op):
        """
        Send an LDAP operation to the server, with no response
        expected.

        @param op: the operation to send
        @type op: LDAPProtocolRequest
        """
        msg = self._send(op)
        assert not op.needs_answer
        self.transport.write(str(msg))

    def unsolicitedNotification(self, msg):
        log.msg("Got unsolicited notification: %s" % repr(msg))

    def handle(self, msg):
        assert isinstance(msg.value, pureldap.LDAPProtocolResponse)
        if self.debug:
            log.debug('C<-S %s' % repr(msg))

        if msg.id == 0:
            self.unsolicitedNotification(msg.value)
        else:
            d, handler, args, kwargs = self.onwire[msg.id]

            if handler is None:
                assert args is None
                assert kwargs is None
                d.callback(msg.value)
                del self.onwire[msg.id]
            else:
                assert args is not None
                assert kwargs is not None
                # Return true to mark request as fully handled
                if handler(msg.value, *args, **kwargs):
                    del self.onwire[msg.id]

    ##Bind
    def bind(self, dn='', auth=''):
        """
        @depreciated: Use e.bind(auth).

        @todo: Remove this method when there are no callers.
        """
        if not self.connected:
            raise LDAPClientConnectionLostException()
        else:
            r = pureldap.LDAPBindRequest(dn=dn, auth=auth)
            d = self.send(r)
            d.addCallback(self._handle_bind_msg)
        return d

    def _handle_bind_msg(self, msg):
        assert isinstance(msg, pureldap.LDAPBindResponse)
        assert msg.referral is None  #TODO
        if msg.resultCode != ldaperrors.Success.resultCode:
            raise ldaperrors.get(msg.resultCode, msg.errorMessage)
        return (msg.matchedDN, msg.serverSaslCreds)

    ##Unbind
    def unbind(self):
        if not self.connected:
            raise "Not connected (TODO)"  #TODO make this a real object
        r = pureldap.LDAPUnbindRequest()
        self.send_noResponse(r)
        self.transport.loseConnection()

    def _cbStartTLS(self, msg, ctx):
        assert isinstance(msg, pureldap.LDAPExtendedResponse)
        assert msg.referral is None  #TODO
        if msg.resultCode != ldaperrors.Success.resultCode:
            raise ldaperrors.get(msg.resultCode, msg.errorMessage)

        self.transport.startTLS(ctx)
        return self

    def startTLS(self, ctx=None):
        """
        Start Transport Layer Security.

        It is the callers responsibility to make sure other things
        are not happening at the same time.

        @todo: server hostname check, see rfc2830 section 3.6.

        """
        if ctx is None:
            ctx = ssl.ClientContextFactory()
        # we always delay by one event loop iteration to make
        # sure the previous handler has exited and self.onwire
        # has been cleaned up
        d = defer.Deferred()
        d.addCallback(self._startTLS)
        reactor.callLater(0, d.callback, ctx)
        return d

    def _startTLS(self, ctx):
        if not self.connected:
            raise LDAPClientConnectionLostException
        elif self.onwire:
            raise LDAPStartTLSBusyError, self.onwire
        else:
            op = pureldap.LDAPStartTLSRequest()
            d = self.send(op)
            d.addCallback(self._cbStartTLS, ctx)
            return d
Пример #10
0
class LDAPClient(protocol.Protocol):
    """An LDAP client"""
    debug = False
    # DUO EDIT D46272: Added "is_logging_insecure" support
    is_logging_insecure = False

    # END EDIT

    def __init__(self):
        self.onwire = {}
        self.buffer = b''
        self.connected = None

    berdecoder = pureldap.LDAPBERDecoderContext_TopLevel(
        inherit=pureldap.LDAPBERDecoderContext_LDAPMessage(
            fallback=pureldap.LDAPBERDecoderContext(
                fallback=pureber.BERDecoderContext()),
            inherit=pureldap.LDAPBERDecoderContext(
                fallback=pureber.BERDecoderContext())))

    def dataReceived(self, recd):
        self.buffer += recd
        while 1:
            try:
                o, bytes = pureber.berDecodeObject(self.berdecoder,
                                                   self.buffer)
            except pureber.BERExceptionInsufficientData:
                o, bytes = None, 0
            self.buffer = self.buffer[bytes:]
            if not o:
                break
            self.handle(o)

    def connectionMade(self):
        """TCP connection has opened"""
        self.connected = 1

    def connectionLost(self, reason=protocol.connectionDone):
        """Called when TCP connection has been lost"""
        self.connected = 0
        # notify handlers of operations in flight
        while self.onwire:
            k, v = self.onwire.popitem()
            # DUO EDIT D46273: Remove depenence on specific number of elemnts in items
            # Change originally made here
            # https://github.com/tv42/ldaptor/tree/024250a206ea1c10dfee5deb5eb2b7d1a34eecc6
            # d, _, _, _, _ = v
            d = v[0]
            # END EDIT
            d.errback(reason)

    def _send(self, op, controls=None):
        if not self.connected:
            raise LDAPClientConnectionLostException()
        msg = pureldap.LDAPMessage(op, controls=controls)
        if self.debug:
            # DUO EDIT D46272: Added "is_logging_insecure" support
            op.is_logging_insecure = self.is_logging_insecure
            # END EDIT
            log.msg('C->S %s' % repr(msg))
        assert msg.id not in self.onwire
        return msg

    # DUO EDIT D46274: Add support for response handlers
    def send(self, op, controls=None, handler=None, return_controls=False):
        """
        Send an LDAP operation to the server.

        @param op: the operation to send

        @type op: LDAPProtocolRequest

        @param controls: LDAP controls to send with the message as a
        list of 3-tuples ('OID string', criticality, value).
        Criticality and value can be None to omit them from the
        message that is sent. Otherwise, criticality must be boolean.

        @type controls: list

        @param handler: Callable that will be called for each
        response. It must return a boolean indicating whether this was
        the final response. functools.partial can be used to give
        further arguments or keyword arguments to the callable.

        @type handler: Callable.

        @param return_controls: If true, the handler will be called with
        the LDAP Message's value as well as the controls

        @type handle_controls: bool

        @return: the response from server

        @rtype: Deferred LDAPProtocolResponse
        """
        msg = self._send(op, controls=controls)
        assert op.needs_answer
        d = defer.Deferred()
        # self.onwire[msg.id] = (d, False, None, None, None)
        if handler is not None:
            self.onwire[msg.id] = (d, return_controls, handler, [], {})
        else:
            self.onwire[msg.id] = (d, return_controls, None, None, None)
        self.transport.write(msg.toWire())
        return d

    # END EDIT

    def send_multiResponse(self, op, handler, *args, **kwargs):
        """
        Send an LDAP operation to the server, expecting one or more
        responses.

        If `handler` is provided, it will receive a LDAP response as
        its first argument. The Deferred returned by this function will
        never fire.

        If `handler` is not provided, the Deferred returned by this
        function will fire with the final LDAP response.

        @param op: the operation to send
        @type op: LDAPProtocolRequest
        @param handler: a callable that will be called for each
        response. It should return a boolean, whether this was the
        final response.
        @param args: positional arguments to pass to handler
        @param kwargs: keyword arguments to pass to handler
        @return: the result from the first handler as a deferred that
        completes when the first response has been received
        @rtype: Deferred LDAPProtocolResponse
        """
        msg = self._send(op)
        assert op.needs_answer
        d = defer.Deferred()
        self.onwire[msg.id] = (d, False, handler, args, kwargs)
        self.transport.write(msg.toWire())
        return d

    def send_multiResponse_ex(self,
                              op,
                              controls=None,
                              handler=None,
                              *args,
                              **kwargs):
        """
        Send an LDAP operation to the server, expecting one or more
        responses.

        If `handler` is provided, it will receive a LDAP response *and*
        response controls as its first 2 arguments. The Deferred returned
        by this function will never fire.

        If `handler` is not provided, the Deferred returned by this
        function will fire with a tuple of the first LDAP response
        and any associated response controls.

        @param op: the operation to send
        @type op: LDAPProtocolRequest
        @param controls: LDAP controls to send with the message.
        @type controls: LDAPControls
        @param handler: a callable that will be called for each
        response. It should return a boolean, whether this was the
        final response.
        @param args: positional arguments to pass to handler
        @param kwargs: keyword arguments to pass to handler
        @return: the result from the last handler as a deferred that
        completes when the last response has been received
        @rtype: Deferred LDAPProtocolResponse
        """
        msg = self._send(op, controls=controls)
        assert op.needs_answer
        d = defer.Deferred()
        self.onwire[msg.id] = (d, True, handler, args, kwargs)
        self.transport.write(msg.toWire())
        return d

    def send_noResponse(self, op, controls=None):
        """
        Send an LDAP operation to the server, with no response
        expected.

        @param op: the operation to send
        @type op: LDAPProtocolRequest
        """
        msg = self._send(op, controls=controls)
        assert not op.needs_answer
        self.transport.write(msg.toWire())

    def unsolicitedNotification(self, msg):
        log.msg("Got unsolicited notification: %s" % repr(msg))

    def handle(self, msg):
        assert isinstance(msg.value, pureldap.LDAPProtocolResponse)
        if self.debug:
            log.msg('C<-S %s' % repr(msg))

        if msg.id == 0:
            self.unsolicitedNotification(msg.value)
        else:
            d, return_controls, handler, args, kwargs = self.onwire[msg.id]

            if handler is None:
                assert (args is None) or (args == ())
                assert (kwargs is None) or (kwargs == {})
                if return_controls:
                    d.callback((msg.value, msg.controls))
                else:
                    d.callback(msg.value)
                del self.onwire[msg.id]
            else:
                assert args is not None
                assert kwargs is not None
                # Return true to mark request as fully handled
                if return_controls:
                    if handler(msg.value, msg.controls, *args, **kwargs):
                        del self.onwire[msg.id]
                        # DUO EDIT D46274: Add support for response handlers
                        d.callback(None)
                        # END EDIT
                else:
                    if handler(msg.value, *args, **kwargs):
                        del self.onwire[msg.id]
                        # DUO EDIT D46274: Add support for response handlers
                        d.callback(None)
                        # END EDIT

    def bind(self, dn='', auth=''):
        """
        @depreciated: Use e.bind(auth).

        @todo: Remove this method when there are no callers.
        """
        if not self.connected:
            raise LDAPClientConnectionLostException()
        else:
            r = pureldap.LDAPBindRequest(dn=dn, auth=auth)
            d = self.send(r)
            d.addCallback(self._handle_bind_msg)
        return d

    def _handle_bind_msg(self, msg):
        assert isinstance(msg, pureldap.LDAPBindResponse)
        assert msg.referral is None  # TODO
        if msg.resultCode != ldaperrors.Success.resultCode:
            raise ldaperrors.get(msg.resultCode, msg.errorMessage)
        return (msg.matchedDN, msg.serverSaslCreds)

    def unbind(self):
        if not self.connected:
            raise Exception(
                "Not connected (TODO)")  # TODO make this a real object
        r = pureldap.LDAPUnbindRequest()
        self.send_noResponse(r)
        self.transport.loseConnection()

    def _cbStartTLS(self, msg, ctx):
        assert isinstance(msg, pureldap.LDAPExtendedResponse)
        assert msg.referral is None  # TODO
        if msg.resultCode != ldaperrors.Success.resultCode:
            raise ldaperrors.get(msg.resultCode, msg.errorMessage)

        if (msg.responseName is not None) and \
                (msg.responseName != pureldap.LDAPStartTLSResponse.oid):
            raise LDAPStartTLSInvalidResponseName(msg.responseName)

        self.transport.startTLS(ctx)
        return self

    def startTLS(self, ctx=None):
        """
        Start Transport Layer Security.

        It is the callers responsibility to make sure other things
        are not happening at the same time.

        @todo: server hostname check, see rfc2830 section 3.6.
        @return: a deferred that will complete when the TLS handshake is
        complete.
        """
        if ctx is None:
            ctx = ssl.ClientContextFactory()
        # we always delay by one event loop iteration to make
        # sure the previous handler has exited and self.onwire
        # has been cleaned up
        d = defer.Deferred()
        d.addCallback(self._startTLS)
        reactor.callLater(0, d.callback, ctx)
        return d

    def _startTLS(self, ctx):
        if not self.connected:
            raise LDAPClientConnectionLostException()
        elif self.onwire:
            raise LDAPStartTLSBusyError(self.onwire)
        else:
            op = pureldap.LDAPStartTLSRequest()
            d = self.send(op)
            d.addCallback(self._cbStartTLS, ctx)
            return d
Пример #11
0
import binascii
from ldaptor import ldapfilter
from ldaptor.protocols import pureber, pureldap
from ldaptor.protocols.ldap import ldaperrors
from samba import ndr
from samba.dcerpc import nbt
from samba.dcerpc import misc

packet = binascii.unhexlify(
    '3084000001040201016384000000fb04000a01000a0100020100020100010100a084000000d4a3840000001c0409446e73446f6d61696e040f6d69736b61746f6e69632e756e692ea384000000170404486f7374040f4445534b544f502d44514c4d473337a384000000250409446f6d61696e5369640418010400000000000515000000b9e81cc93f161323478e6dbca3840000001e040a446f6d61696e4775696404109833dc516c2789468b2bcf581b826058a3840000000d04054e74566572040416000000a3840000002d040b446e73486f73744e616d65041e4445534b544f502d44514c4d4733372e6d69736b61746f6e69632e756e6930840000000a04084e65746c6f676f6e'
)

berdecoder = pureldap.LDAPBERDecoderContext_TopLevel(
    inherit=pureldap.LDAPBERDecoderContext_LDAPMessage(
        fallback=pureldap.LDAPBERDecoderContext(
            fallback=pureber.BERDecoderContext()),
        inherit=pureldap.LDAPBERDecoderContext(
            fallback=pureber.BERDecoderContext())))

msg, bytes = pureber.berDecodeObject(berdecoder, packet)
msgId = msg.id
print msgId
msg = msg.value
assert isinstance(msg, pureldap.LDAPProtocolRequest)
print msg.__class__.__name__
print msg.baseObject
print msg.scope


def findDomain(filt):
    if isinstance(filt, pureldap.LDAPFilter_and):
Пример #12
0
class KnownValues(unittest.TestCase):
    knownValues = (  # class, args, kwargs, expected_result
        (pureldap.LDAPModifyRequest, [], {
            "object":
            'cn=foo, dc=example, dc=com',
            "modification": [
                pureber.BERSequence([
                    pureber.BEREnumerated(0),
                    pureber.BERSequence([
                        pureldap.LDAPAttributeDescription('bar'),
                        pureber.BERSet([
                            pureldap.LDAPString('a'),
                            pureldap.LDAPString('b'),
                        ]),
                    ]),
                ]),
            ],
        }, None, [0x66, 50] +
         ([0x04, 0x1a] + l("cn=foo, dc=example, dc=com") + [0x30, 20] +
          ([0x30, 18] +
           ([0x0a, 0x01, 0x00] + [0x30, 13] +
            ([0x04, len("bar")] + l("bar") + [0x31, 0x06] +
             ([0x04, len("a")] + l("a") + [0x04, len("b")] + l("b"))))))),
        (pureldap.LDAPModifyRequest, [], {
            "object":
            'cn=foo, dc=example, dc=com',
            "modification": [
                pureber.BERSequence([
                    pureber.BEREnumerated(1L),
                    pureber.BERSequence([
                        pureber.BEROctetString('bar'),
                        pureber.BERSet([]),
                    ]),
                ]),
            ],
        }, None, [0x66, 0x2c] +
         ([0x04, 0x1a] + l("cn=foo, dc=example, dc=com") + [0x30, 0x0e] +
          ([0x30, 0x0c] + ([0x0a, 0x01, 0x01] + [0x30, 0x07] +
                           ([0x04, 0x03] + l("bar") + [0x31, 0x00]))))),
        (pureldap.LDAPFilter_not, [], {
            "value": pureldap.LDAPFilter_present("foo"),
        },
         pureldap.LDAPBERDecoderContext_Filter(
             fallback=pureber.BERDecoderContext()),
         [0xa2, 0x05] + [0x87] + [len("foo")] + l("foo")),
        (
            pureldap.LDAPFilter_or,
            [],
            {
                "value": [
                    pureldap.LDAPFilter_equalityMatch(
                        attributeDesc=pureldap.LDAPAttributeDescription(
                            value='cn'),
                        assertionValue=pureldap.LDAPAssertionValue(
                            value='foo')),
                    pureldap.LDAPFilter_equalityMatch(
                        attributeDesc=pureldap.LDAPAttributeDescription(
                            value='uid'),
                        assertionValue=pureldap.LDAPAssertionValue(
                            value='foo')),
                ]
            },
            pureldap.LDAPBERDecoderContext_Filter(
                fallback=pureber.BERDecoderContext()),
            [0xa1, 23] + [0xa3, 9] + [0x04] + [len("cn")] + l("cn") + [0x04] +
            [len("foo")] + l("foo") + [0xa3, 10] + [0x04] + [len("uid")] +
            l("uid") + [0x04] + [len("foo")] + l("foo"),
        ),
        (
            pureldap.LDAPFilter_and,
            [],
            {
                "value": [
                    pureldap.LDAPFilter_equalityMatch(
                        attributeDesc=pureldap.LDAPAttributeDescription(
                            value='cn'),
                        assertionValue=pureldap.LDAPAssertionValue(
                            value='foo')),
                    pureldap.LDAPFilter_equalityMatch(
                        attributeDesc=pureldap.LDAPAttributeDescription(
                            value='uid'),
                        assertionValue=pureldap.LDAPAssertionValue(
                            value='foo')),
                ]
            },
            pureldap.LDAPBERDecoderContext_Filter(
                fallback=pureber.BERDecoderContext()),
            [0xa0, 23] + [0xa3, 9] + [0x04] + [len("cn")] + l("cn") + [0x04] +
            [len("foo")] + l("foo") + [0xa3, 10] + [0x04] + [len("uid")] +
            l("uid") + [0x04] + [len("foo")] + l("foo"),
        ),
        (pureldap.LDAPModifyDNRequest, [], {
            'entry': 'cn=foo,dc=example,dc=com',
            'newrdn': 'uid=bar',
            'deleteoldrdn': 0,
        }, None, [0x6c, 0x26] + [0x04] + [len("cn=foo,dc=example,dc=com")] +
         l("cn=foo,dc=example,dc=com") + [0x04] + [len("uid=bar")] +
         l("uid=bar") + [0x01, 0x01, 0x00]),
        (pureldap.LDAPModifyDNRequest, [], {
            'entry': 'cn=aoue,dc=example,dc=com',
            'newrdn': 'uid=aoue',
            'deleteoldrdn': 0,
            'newSuperior': 'ou=People,dc=example,dc=com',
        }, None, [0x6c, 69] + [0x04] + [len("cn=aoue,dc=example,dc=com")] +
         l("cn=aoue,dc=example,dc=com") + [0x04] + [len("uid=aoue")] +
         l("uid=aoue") + [0x01, 0x01, 0x00] + [0x80] +
         [len("ou=People,dc=example,dc=com")] +
         l("ou=People,dc=example,dc=com")),
        (
            pureldap.LDAPSearchRequest,
            [],
            {
                'baseObject': 'dc=yoja,dc=example,dc=com',
            },
            None,
            [0x63, 57] + [0x04] + [len('dc=yoja,dc=example,dc=com')] +
            l('dc=yoja,dc=example,dc=com')
            # scope
            + [0x0a, 1, 2]
            # derefAliases
            + [0x0a, 1, 0]
            # sizeLimit
            + [0x02, 1, 0]
            # timeLimit
            + [0x02, 1, 0]
            # typesOnly
            + [0x01, 1, 0]
            # filter
            + [135, 11] + l('objectClass')
            # attributes
            + [48, 0]),
        (pureldap.LDAPUnbindRequest, [], {}, None, [0x42, 0x00]),
        (
            pureldap.LDAPSearchResultDone,
            [],
            {
                'resultCode': 0,
            },
            None,
            [0x65, 0x07]
            # resultCode
            + [0x0a, 0x01, 0x00]
            # matchedDN
            + [0x04] + [len('')] + l('')
            # errorMessage
            + [0x04] + [len('')] + l('')
            # referral, TODO
            + []),
        (
            pureldap.LDAPSearchResultDone,
            [],
            {
                'resultCode': 0,
                'matchedDN': 'dc=foo,dc=example,dc=com',
            },
            None,
            [0x65, 31]
            # resultCode
            + [0x0a, 0x01, 0x00]
            # matchedDN
            + [0x04] + [len('dc=foo,dc=example,dc=com')] +
            l('dc=foo,dc=example,dc=com')
            # errorMessage
            + [0x04] + [len('')] + l('')
            # referral, TODO
            + []),
        (
            pureldap.LDAPSearchResultDone,
            [],
            {
                'resultCode': 0,
                'matchedDN': 'dc=foo,dc=example,dc=com',
                'errorMessage': 'the foobar was fubar',
            },
            None,
            [0x65, 51]
            # resultCode
            + [0x0a, 0x01, 0x00]
            # matchedDN
            + [0x04] + [len('dc=foo,dc=example,dc=com')] +
            l('dc=foo,dc=example,dc=com')
            # errorMessage
            + [0x04] + [len('the foobar was fubar')] +
            l('the foobar was fubar', )
            # referral, TODO
            + []),
        (
            pureldap.LDAPSearchResultDone,
            [],
            {
                'resultCode': 0,
                'errorMessage': 'the foobar was fubar',
            },
            None,
            [0x65, 27]
            # resultCode
            + [0x0a, 0x01, 0x00]
            # matchedDN
            + [0x04] + [len('')] + l('')
            # errorMessage
            + [0x04] + [len('the foobar was fubar')] +
            l('the foobar was fubar', )
            # referral, TODO
            + []),
        (
            pureldap.LDAPMessage,
            [],
            {
                'id': 42,
                'value': pureldap.LDAPBindRequest(),
            },
            pureldap.LDAPBERDecoderContext_TopLevel(
                inherit=pureldap.LDAPBERDecoderContext_LDAPMessage(
                    fallback=pureldap.LDAPBERDecoderContext(
                        fallback=pureber.BERDecoderContext()),
                    inherit=pureldap.LDAPBERDecoderContext(
                        fallback=pureber.BERDecoderContext()))),
            [0x30, 12]
            # id
            + [0x02, 0x01, 42]
            # value
            + l(str(pureldap.LDAPBindRequest()))),
        (
            pureldap.LDAPControl,
            [],
            {
                'controlType': '1.2.3.4',
            },
            None,
            [0x30, 9]
            # controlType
            + [0x04, 7] + l("1.2.3.4")),
        (
            pureldap.LDAPControl,
            [],
            {
                'controlType': '1.2.3.4',
                'criticality': True,
            },
            None,
            [0x30, 12]
            # controlType
            + [0x04, 7] + l("1.2.3.4")
            # criticality
            + [0x01, 1, 0xFF]),
        (
            pureldap.LDAPControl,
            [],
            {
                'controlType': '1.2.3.4',
                'criticality': True,
                'controlValue': 'silly',
            },
            None,
            [0x30, 19]
            # controlType
            + [0x04, 7] + l("1.2.3.4")
            # criticality
            + [0x01, 1, 0xFF]
            # controlValue
            + [0x04, len("silly")] + l("silly")),
        (
            pureldap.LDAPMessage,
            [],
            {
                'id':
                42,
                'value':
                pureldap.LDAPBindRequest(),
                'controls': [
                    ('1.2.3.4', None, None),
                    ('2.3.4.5', False),
                    ('3.4.5.6', True, '\x00\x01\x02\xFF'),
                ],
            },
            pureldap.LDAPBERDecoderContext_TopLevel(
                inherit=pureldap.LDAPBERDecoderContext_LDAPMessage(
                    fallback=pureldap.LDAPBERDecoderContext(
                        fallback=pureber.BERDecoderContext()),
                    inherit=pureldap.LDAPBERDecoderContext(
                        fallback=pureber.BERDecoderContext()))),
            [0x30, 59]
            # id
            + [0x02, 0x01, 42]
            # value
            + l(str(pureldap.LDAPBindRequest()))
            # controls
            + l(
                str(
                    pureldap.LDAPControls(value=[
                        pureldap.LDAPControl(controlType='1.2.3.4'),
                        pureldap.LDAPControl(controlType='2.3.4.5',
                                             criticality=False),
                        pureldap.LDAPControl(controlType='3.4.5.6',
                                             criticality=True,
                                             controlValue='\x00\x01\x02\xFF'),
                    ]))),
        ),
        (pureldap.LDAPFilter_equalityMatch, [], {
            'attributeDesc': pureldap.LDAPAttributeDescription('cn'),
            'assertionValue': pureldap.LDAPAssertionValue('foo'),
        },
         pureldap.LDAPBERDecoderContext_Filter(
             fallback=pureldap.LDAPBERDecoderContext(
                 fallback=pureber.BERDecoderContext()),
             inherit=pureldap.LDAPBERDecoderContext(
                 fallback=pureber.BERDecoderContext())),
         [0xa3, 9] + ([0x04, 2] + l('cn') + [0x04, 3] + l('foo'))),
        (pureldap.LDAPFilter_or, [[
            pureldap.LDAPFilter_equalityMatch(
                attributeDesc=pureldap.LDAPAttributeDescription('cn'),
                assertionValue=pureldap.LDAPAssertionValue('foo')),
            pureldap.LDAPFilter_equalityMatch(
                attributeDesc=pureldap.LDAPAttributeDescription('uid'),
                assertionValue=pureldap.LDAPAssertionValue('foo')),
            pureldap.LDAPFilter_equalityMatch(
                attributeDesc=pureldap.LDAPAttributeDescription('mail'),
                assertionValue=pureldap.LDAPAssertionValue('foo')),
            pureldap.LDAPFilter_substrings(
                type='mail',
                substrings=[pureldap.LDAPFilter_substrings_initial('foo@')]),
        ]], {},
         pureldap.LDAPBERDecoderContext_Filter(
             fallback=pureldap.LDAPBERDecoderContext(
                 fallback=pureber.BERDecoderContext()),
             inherit=pureldap.LDAPBERDecoderContext(
                 fallback=pureber.BERDecoderContext())), [0xA1, 52] +
         ([0xa3, 9] +
          ([0x04, 2] + l('cn') + [0x04, 3] + l('foo')) + [0xa3, 10] +
          ([0x04, 3] + l('uid') + [0x04, 3] + l('foo')) + [0xa3, 11] +
          ([0x04, 4] + l('mail') + [0x04, 3] + l('foo')) + [0xa4, 14] +
          ([0x04, 4] + l('mail') + [0x30, 6] + ([0x80, 4] + l('foo@'))))),
        (pureldap.LDAPSearchRequest, [], {
            'baseObject':
            'dc=example,dc=com',
            'scope':
            pureldap.LDAP_SCOPE_wholeSubtree,
            'derefAliases':
            pureldap.LDAP_DEREF_neverDerefAliases,
            'sizeLimit':
            1,
            'timeLimit':
            0,
            'typesOnly':
            False,
            'filter':
            pureldap.LDAPFilter_or([
                pureldap.LDAPFilter_equalityMatch(
                    attributeDesc=pureldap.LDAPAttributeDescription('cn'),
                    assertionValue=pureldap.LDAPAssertionValue('foo')),
                pureldap.LDAPFilter_equalityMatch(
                    attributeDesc=pureldap.LDAPAttributeDescription('uid'),
                    assertionValue=pureldap.LDAPAssertionValue('foo')),
                pureldap.LDAPFilter_equalityMatch(
                    attributeDesc=pureldap.LDAPAttributeDescription('mail'),
                    assertionValue=pureldap.LDAPAssertionValue('foo')),
                pureldap.LDAPFilter_substrings(
                    type='mail',
                    substrings=[
                        pureldap.LDAPFilter_substrings_initial('foo@')
                    ]),
            ]),
            'attributes': [''],
        },
         pureldap.LDAPBERDecoderContext_LDAPMessage(
             fallback=pureldap.LDAPBERDecoderContext(
                 fallback=pureber.BERDecoderContext()),
             inherit=pureldap.LDAPBERDecoderContext(
                 fallback=pureber.BERDecoderContext())), [0x63, 92] +
         ([0x04, 17] + l('dc=example,dc=com') + [0x0a, 1, 0x02] +
          [0x0a, 1, 0x00] + [0x02, 1, 0x01] + [0x02, 1, 0x00] +
          [0x01, 1, 0x00] + [0xA1, 52] +
          ([0xa3, 9] +
           ([0x04, 2] + l('cn') + [0x04, 3] + l('foo')) + [0xa3, 10] +
           ([0x04, 3] + l('uid') + [0x04, 3] + l('foo')) + [0xa3, 11] +
           ([0x04, 4] + l('mail') + [0x04, 3] + l('foo')) + [0xa4, 14] +
           ([0x04, 4] + l('mail') + [0x30, 6] +
            ([0x80, 4] + l('foo@')))) + [0x30, 2] + ([0x04, 0]))),
        (
            pureldap.LDAPMessage,
            [],
            {
                'id':
                1L,
                'value':
                pureldap.LDAPSearchRequest(
                    baseObject='dc=example,dc=com',
                    scope=pureldap.LDAP_SCOPE_wholeSubtree,
                    derefAliases=pureldap.LDAP_DEREF_neverDerefAliases,
                    sizeLimit=1,
                    timeLimit=0,
                    typesOnly=False,
                    filter=pureldap.LDAPFilter_or([
                        pureldap.LDAPFilter_equalityMatch(
                            attributeDesc=pureldap.LDAPAttributeDescription(
                                'cn'),
                            assertionValue=pureldap.LDAPAssertionValue('foo')),
                        pureldap.LDAPFilter_equalityMatch(
                            attributeDesc=pureldap.LDAPAttributeDescription(
                                'uid'),
                            assertionValue=pureldap.LDAPAssertionValue('foo')),
                        pureldap.LDAPFilter_equalityMatch(
                            attributeDesc=pureldap.LDAPAttributeDescription(
                                'mail'),
                            assertionValue=pureldap.LDAPAssertionValue('foo')),
                        pureldap.LDAPFilter_substrings(
                            type='mail',
                            substrings=[
                                pureldap.LDAPFilter_substrings_initial('foo@')
                            ]),
                    ]),
                    attributes=[''],
                ),
            },
            pureldap.LDAPBERDecoderContext_TopLevel(
                inherit=pureldap.LDAPBERDecoderContext_LDAPMessage(
                    fallback=pureldap.LDAPBERDecoderContext(
                        fallback=pureber.BERDecoderContext()),
                    inherit=pureldap.LDAPBERDecoderContext(
                        fallback=pureber.BERDecoderContext()))),
            [0x30, 97]
            # id
            + [0x02, 1, 1]
            # value
            + [0x63, 92] +
            ([0x04, 17] + l('dc=example,dc=com') + [0x0a, 1, 0x02] +
             [0x0a, 1, 0x00] + [0x02, 1, 0x01] + [0x02, 1, 0x00] +
             [0x01, 1, 0x00] + [0xA1, 52] +
             ([0xa3, 9] +
              ([0x04, 2] + l('cn') + [0x04, 3] + l('foo')) + [0xa3, 10] +
              ([0x04, 3] + l('uid') + [0x04, 3] + l('foo')) + [0xa3, 11] +
              ([0x04, 4] + l('mail') + [0x04, 3] + l('foo')) + [0xa4, 14] +
              ([0x04, 4] + l('mail') + [0x30, 6] +
               ([0x80, 4] + l('foo@')))) + [0x30, 2] + ([0x04, 0]))),
        (pureldap.LDAPExtendedRequest, [], {
            'requestName': '42.42.42',
            'requestValue': 'foo',
        }, None, [0x40 | 0x20 | 23, 1 + 1 + 8 + 1 + 1 + 3] +
         ([0x80 | 0] + [len('42.42.42')] + l('42.42.42')) +
         ([0x80 | 1] + [len('foo')] + l('foo'))),
    )

    def testToLDAP(self):
        """str(LDAPClass(...)) should give known result with known input"""
        for klass, args, kwargs, decoder, encoded in self.knownValues:
            result = klass(*args, **kwargs)
            result = str(result)
            result = map(ord, result)
            if result != encoded:
                raise AssertionError, \
                      "Class %s(*%s, **%s) doesn't encode properly: " \
                      "%s != %s" % (klass.__name__,
                                    repr(args), repr(kwargs),
                                    repr(result), repr(encoded))

    def testFromLDAP(self):
        """LDAPClass(encoded="...") should give known result with known input"""
        for klass, args, kwargs, decoder, encoded in self.knownValues:
            if decoder is None:
                decoder = pureldap.LDAPBERDecoderContext(
                    fallback=pureber.BERDecoderContext())
            m = s(*encoded)
            result, bytes = pureber.berDecodeObject(decoder, m)
            self.assertEquals(bytes, len(m))

            shouldBe = klass(*args, **kwargs)
            #TODO shouldn't use str below
            assert str(result)==str(shouldBe), \
                   "Class %s(*%s, **%s) doesn't decode properly: " \
                   "%s != %s" % (klass.__name__,
                                 repr(args), repr(kwargs),
                                 repr(result), repr(shouldBe))

    def testPartial(self):
        """LDAPClass(encoded="...") with too short input should throw BERExceptionInsufficientData"""
        for klass, args, kwargs, decoder, encoded in self.knownValues:
            if decoder is None:
                decoder = pureldap.LDAPBERDecoderContext(
                    fallback=pureber.BERDecoderContext())
            for i in xrange(1, len(encoded)):
                m = s(*encoded)[:i]
                self.assertRaises(pureber.BERExceptionInsufficientData,
                                  pureber.berDecodeObject, decoder, m)
            self.assertEquals((None, 0), pureber.berDecodeObject(decoder, ''))