예제 #1
0
 def cb_(result):
     if result:
         return pureldap.LDAPExtendedResponse(
             resultCode=ldaperrors.Success.resultCode,
             responseName=self.extendedRequest_LDAPPasswordModifyRequest.oid)
     else:
         raise ldaperrors.LDAPOperationsError('Internal error.')
예제 #2
0
 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
예제 #3
0
    def handle_LDAPExtendedRequest(
        self,
        request: LDAPExtendedRequest,
        controls: pureldap.LDAPControl,
        reply_fn: Callable[..., None],
    ) -> Any:
        # Handle STARTTLS locally; proxy everything else.
        if request.requestName != pureldap.LDAPStartTLSRequest.oid:
            return self.handleUnknown(request, controls, reply_fn)

        if not self.sslctx:
            raise ldaperrors.LDAPProtocolError(
                STARTTLS_NOT_SUPPORTED_ERROR_MESSAGE)

        self.checkControls(controls)  # assert can ignore controls, then do so

        try:
            # Send reply indicating TLS negotiation should start.
            msg = pureldap.LDAPExtendedResponse(
                resultCode=ldaperrors.Success.resultCode,
                responseName=pureldap.LDAPStartTLSRequest.oid,
            )
            reply_fn(msg)
            # Start TLS negotiation!
            self.transport.startTLS(self.sslctx, self.factory)
        except ldaperrors.LDAPException:
            raise
        except Exception:
            raise ldaperrors.LDAPUnwillingToPerform()
예제 #4
0
 def eb(fail, oid):
     fail.trap(ldaperrors.LDAPException)
     return pureldap.LDAPExtendedResponse(
         resultCode=fail.value.resultCode,
         errorMessage=fail.value.message,
         responseName=oid,
         )
예제 #5
0
 def test_extendedRequest_unknown(self):
     self.server.dataReceived(
         pureldap.LDAPMessage(pureldap.LDAPExtendedRequest(
             requestName='42.42.42', requestValue='foo'),
                              id=2).toWire())
     self.assertEqual(
         self.server.transport.value(),
         pureldap.LDAPMessage(pureldap.LDAPExtendedResponse(
             resultCode=ldaperrors.LDAPProtocolError.resultCode,
             errorMessage='Unknown extended request: 42.42.42'),
                              id=2).toWire())
예제 #6
0
 def test_passwordModify_notBound(self):
     self.server.dataReceived(
         pureldap.LDAPMessage(pureldap.LDAPPasswordModifyRequest(
             userIdentity='cn=thingie,ou=stuff,dc=example,dc=com',
             newPasswd='hushhush'),
                              id=2).toWire())
     self.assertEqual(
         self.server.transport.value(),
         pureldap.LDAPMessage(pureldap.LDAPExtendedResponse(
             resultCode=ldaperrors.LDAPStrongAuthRequired.resultCode,
             responseName=pureldap.LDAPPasswordModifyRequest.oid),
                              id=2).toWire())
예제 #7
0
 def test_passwordModify_someoneElse(self):
     commits = observeCommits(self.thingie)
     # first bind to some entry
     userPassword = b"{SSHA}yVLLj62rFf3kDAbzwEU0zYAVvbWrze8="  # secret
     self.thingie["userPassword"] = [userPassword]
     self.server.dataReceived(
         pureldap.LDAPMessage(
             pureldap.LDAPBindRequest(
                 dn="cn=thingie,ou=stuff,dc=example,dc=com",
                 auth=b"secret"),
             id=4,
         ).toWire())
     self.assertEqual(
         self.server.transport.value(),
         pureldap.LDAPMessage(
             pureldap.LDAPBindResponse(
                 resultCode=0,
                 matchedDN="cn=thingie,ou=stuff,dc=example,dc=com"),
             id=4,
         ).toWire(),
     )
     self.server.transport.clear()
     observer = testing.EventLoggingObserver.createWithCleanup(self, log)
     self.server.dataReceived(
         pureldap.LDAPMessage(
             pureldap.LDAPPasswordModifyRequest(
                 userIdentity="cn=another,ou=stuff,dc=example,dc=com",
                 newPasswd="hushhush",
             ),
             id=2,
         ).toWire())
     self.assertEqual(
         observer[0]["log_text"],
         "User cn=thingie,ou=stuff,dc=example,dc=com "
         "tried to change password of "
         "b'cn=another,ou=stuff,dc=example,dc=com'",
     )
     self.assertListEqual(commits, [], "Server committed data.")
     self.assertEqual(
         self.server.transport.value(),
         pureldap.LDAPMessage(
             pureldap.LDAPExtendedResponse(
                 resultCode=ldaperrors.LDAPInsufficientAccessRights.
                 resultCode,
                 responseName=pureldap.LDAPPasswordModifyRequest.oid,
             ),
             id=2,
         ).toWire(),
     )
     self.assertSequenceEqual(
         self.thingie.get("userPassword", []),
         [userPassword],
     )
예제 #8
0
    def extendedRequest_LDAPPasswordModifyRequest(self, data, reply):
        if not isinstance(data, pureber.BERSequence):
            raise ldaperrors.LDAPProtocolError('Extended request PasswordModify expected a BERSequence.')

        userIdentity = None
        oldPasswd = None
        newPasswd = None

        for value in data:
            if isinstance(value, pureldap.LDAPPasswordModifyRequest_userIdentity):
                if userIdentity is not None:
                    raise ldaperrors.LDAPProtocolError(
                        'Extended request PasswordModify received userIdentity twice.')
                userIdentity = value.value
            elif isinstance(value, pureldap.LDAPPasswordModifyRequest_oldPasswd):
                if oldPasswd is not None:
                    raise ldaperrors.LDAPProtocolError('Extended request PasswordModify received oldPasswd twice.')
                oldPasswd = value.value
            elif isinstance(value, pureldap.LDAPPasswordModifyRequest_newPasswd):
                if newPasswd is not None:
                    raise ldaperrors.LDAPProtocolError('Extended request PasswordModify received newPasswd twice.')
                newPasswd = value.value
            else:
                raise ldaperrors.LDAPProtocolError('Extended request PasswordModify received unexpected item.')

        if self.boundUser is None:
            raise ldaperrors.LDAPStrongAuthRequired()

        if (userIdentity is not None
            and userIdentity != self.boundUser.dn):
            #TODO this hardcodes ACL
            log.msg('User %(actor)s tried to change password of %(target)s' % {
                'actor': str(self.boundUser.dn),
                'target': str(userIdentity),
                })
            raise ldaperrors.LDAPInsufficientAccessRights()

        if (oldPasswd is not None
            or newPasswd is None):
            raise ldaperrors.LDAPOperationsError('Password does not support this case.')

        self.boundUser.setPassword(newPasswd)
        return pureldap.LDAPExtendedResponse(resultCode=ldaperrors.Success.resultCode,
                                             responseName=self.extendedRequest_LDAPPasswordModifyRequest.oid)

        # TODO
        if userIdentity is None:
            userIdentity = str(self.boundUser.dn)

        raise NotImplementedError('VALUE %r' % value)
예제 #9
0
    def test_passwordModify_simple(self):
        data = {'committed': False}

        def onCommit_(result, info):
            info['committed'] = result
            return result

        wrapCommit(self.thingie, onCommit_, data)
        # first bind to some entry
        self.thingie['userPassword'] = ['{SSHA}yVLLj62rFf3kDAbzwEU0zYAVvbWrze8=']  # "secret"
        self.server.dataReceived(
            pureldap.LDAPMessage(
                pureldap.LDAPBindRequest(
                    dn='cn=thingie,ou=stuff,dc=example,dc=com',
                    auth=b'secret'),
                id=4).toWire())
        self.assertEqual(
            self.server.transport.value(),
            pureldap.LDAPMessage(
                pureldap.LDAPBindResponse(
                    resultCode=0,
                    matchedDN='cn=thingie,ou=stuff,dc=example,dc=com'),
                id=4).toWire())
        self.server.transport.clear()
        self.server.dataReceived(
            pureldap.LDAPMessage(
                pureldap.LDAPPasswordModifyRequest(
                    userIdentity='cn=thingie,ou=stuff,dc=example,dc=com',
                    newPasswd='hushhush'),
                id=2).toWire())
        self.assertEqual(data['committed'], True, "Server never committed data.")
        self.assertEqual(
            self.server.transport.value(),
            pureldap.LDAPMessage(
                pureldap.LDAPExtendedResponse(
                    resultCode=ldaperrors.Success.resultCode,
                    responseName=pureldap.LDAPPasswordModifyRequest.oid),
                id=2).toWire())
        # tree changed
        secrets = self.thingie.get('userPassword', [])
        self.assertEqual(len(secrets), 1)
        for secret in secrets:
            self.assertEqual(secret[:len(b'{SSHA}')], b'{SSHA}')
            # DUO EDIT @mbishop
            # Nominal change to remove deprecation warning
            # raw = base64.decodestring(secret[len(b'{SSHA}'):])
            raw = base64.decodebytes(secret[len(b'{SSHA}'):])
            # END EDIT
            salt = raw[20:]
            self.assertEqual(entry.sshaDigest(b'hushhush', salt), secret)
예제 #10
0
 def test_passwordModify_simple(self):
     commits = observeCommits(self.thingie)
     # first bind to some entry
     self.thingie["userPassword"] = [
         "{SSHA}yVLLj62rFf3kDAbzwEU0zYAVvbWrze8="
     ]  # "secret"
     self.server.dataReceived(
         pureldap.LDAPMessage(
             pureldap.LDAPBindRequest(
                 dn="cn=thingie,ou=stuff,dc=example,dc=com",
                 auth=b"secret"),
             id=4,
         ).toWire())
     self.assertEqual(
         self.server.transport.value(),
         pureldap.LDAPMessage(
             pureldap.LDAPBindResponse(
                 resultCode=0,
                 matchedDN="cn=thingie,ou=stuff,dc=example,dc=com"),
             id=4,
         ).toWire(),
     )
     self.server.transport.clear()
     self.server.dataReceived(
         pureldap.LDAPMessage(
             pureldap.LDAPPasswordModifyRequest(
                 userIdentity="cn=thingie,ou=stuff,dc=example,dc=com",
                 newPasswd="hushhush",
             ),
             id=2,
         ).toWire())
     self.assertListEqual(commits, [True], "Server never committed data.")
     self.assertEqual(
         self.server.transport.value(),
         pureldap.LDAPMessage(
             pureldap.LDAPExtendedResponse(
                 resultCode=ldaperrors.Success.resultCode,
                 responseName=pureldap.LDAPPasswordModifyRequest.oid,
             ),
             id=2,
         ).toWire(),
     )
     # tree changed
     secrets = self.thingie.get("userPassword", [])
     self.assertEqual(len(secrets), 1)
     for secret in secrets:
         self.assertEqual(secret[:len(b"{SSHA}")], b"{SSHA}")
         raw = base64.decodebytes(secret[len(b"{SSHA}"):])
         salt = raw[20:]
         self.assertEqual(entry.sshaDigest(b"hushhush", salt), secret)
예제 #11
0
    def test_unknownRequest(self):
        # make server miss one of the handle_* attributes
        # without having to modify the LDAPServer class
        class MockServer(ldapserver.LDAPServer):
            handle_LDAPBindRequest = property()

        self.server.__class__ = MockServer
        self.server.dataReceived(
            pureldap.LDAPMessage(pureldap.LDAPBindRequest(), id=2).toWire())
        self.assertEqual(
            self.server.transport.value(),
            pureldap.LDAPMessage(pureldap.LDAPExtendedResponse(
                resultCode=ldaperrors.LDAPProtocolError.resultCode,
                responseName='1.3.6.1.4.1.1466.20036',
                errorMessage='Unknown request'),
                                 id=2).toWire())
예제 #12
0
    def test_passwordModify_simple(self):
        # first bind to some entry
        self.thingie['userPassword'] = [
            '{SSHA}yVLLj62rFf3kDAbzwEU0zYAVvbWrze8='
        ]  # "secret"
        self.server.dataReceived(
            str(
                pureldap.LDAPMessage(pureldap.LDAPBindRequest(
                    dn='cn=thingie,ou=stuff,dc=example,dc=com', auth='secret'),
                                     id=4)))
        self.assertEquals(
            self.server.transport.value(),
            str(
                pureldap.LDAPMessage(pureldap.LDAPBindResponse(
                    resultCode=0,
                    matchedDN='cn=thingie,ou=stuff,dc=example,dc=com'),
                                     id=4)))
        self.server.transport.clear()

        self.server.dataReceived(
            str(
                pureldap.LDAPMessage(pureldap.LDAPPasswordModifyRequest(
                    userIdentity='cn=thingie,ou=stuff,dc=example,dc=com',
                    newPasswd='hushhush'),
                                     id=2)))
        self.assertEquals(
            self.server.transport.value(),
            str(
                pureldap.LDAPMessage(pureldap.LDAPExtendedResponse(
                    resultCode=ldaperrors.Success.resultCode,
                    responseName=pureldap.LDAPPasswordModifyRequest.oid),
                                     id=2)),
        )
        # tree changed
        secrets = self.thingie.get('userPassword', [])
        self.assertEquals(len(secrets), 1)
        for secret in secrets:
            self.assertEquals(secret[:len('{SSHA}')], '{SSHA}')
            raw = base64.decodestring(secret[len('{SSHA}'):])
            salt = raw[20:]
            self.assertEquals(entry.sshaDigest('hushhush', salt), secret)
예제 #13
0
 def failDefault(self, resultCode, errorMessage):
     return pureldap.LDAPExtendedResponse(
         resultCode=resultCode,
         responseName='1.3.6.1.4.1.1466.20036',
         errorMessage=errorMessage)