Esempio n. 1
0
    def finish(self, data):
        """Process success indicator from the server.

        Process any addiitional data passed with the success.
        Fail if the server was not authenticated.

        :Parameters:
            - `data`: an optional additional data with success.
        :Types:
            - `data`: `bytes`

        :return: success or failure indicator.
        :returntype: `sasl.Success` or `sasl.Failure`"""
        if not self._server_first_message:
            logger.debug("Got success too early")
            return Failure("bad-success")
        if self._finished:
            return Success({
                "username": self.username,
                "authzid": self.authzid
            })
        else:
            ret = self._final_challenge(data)
            if isinstance(ret, Failure):
                return ret
            if self._finished:
                return Success({
                    "username": self.username,
                    "authzid": self.authzid
                })
            else:
                logger.debug("Something went wrong when processing additional"
                             " data with success?")
                return Failure("bad-success")
Esempio n. 2
0
    def finish(self, data):
        """Handle authentication success information from the server.

        :Parameters:
            - `data`: the optional additional data returned with the success.
        :Types:
            - `data`: `bytes`

        :return: a success indicator.
        :returntype: `Success`"""
        return Success({"authzid": self.authzid})
Esempio n. 3
0
    def response(self, response):
        """Process a client reponse.

        :Parameters:
            - `response`: the response from the client.
        :Types:
            - `response`: `bytes`

        :return: a challenge, a success indicator or a failure indicator.
        :returntype: `sasl.Challenge`, `sasl.Success` or `sasl.Failure`"""
        if self.out_properties:
            return Success(self.out_properties)
        if not response:
            return Failure("not-authorized")
        return self._parse_response(response)
Esempio n. 4
0
    def _handle_final_response(self, response):
        match = CLIENT_FINAL_MESSAGE_RE.match(response)
        if not match:
            logger.debug("Bad response syntax: {0!r}".format(response))
            return Failure("not-authorized")
        if match.group("nonce") != self._nonce:
            logger.debug("Bad nonce in the final client response")
            return Failure("not-authorized")
        cb_input = a2b_base64(match.group("cb"))
        if not cb_input.startswith(self._gs2_header):
            logger.debug(
                "GS2 header in the final response ({0!r}) doesn't"
                " match the one sent in the first message ({1!r})".format(
                    cb_input, self._gs2_header))
            return Failure("not-authorized")
        if self._cb_name:
            cb_data = cb_input[len(self._gs2_header):]
            if cb_data != self.properties["channel-binding"][self._cb_name]:
                logger.debug("Channel binding data doesn't match")
                return Failure("not-authorized")

        proof = a2b_base64(match.group("proof"))

        auth_message = (self._client_first_message_bare + b"," +
                        self._server_first_message + b"," +
                        match.group("without_proof"))
        if self._stored_key is None:
            # compute something to prevent timing attack
            client_signature = self.HMAC(b"", auth_message)
            client_key = self.XOR(client_signature, proof)
            self.H(client_key)
            logger.debug("Authentication failed (bad username)")
            return Failure("not-authorized")

        client_signature = self.HMAC(self._stored_key, auth_message)
        client_key = self.XOR(client_signature, proof)
        if self.H(client_key) != self._stored_key:
            logger.debug("Authentication failed")
            return Failure("not-authorized")

        server_signature = self.HMAC(self._server_key, auth_message)
        server_final_message = b"v=" + standard_b64encode(server_signature)
        return Success(self.out_properties, server_final_message)
Esempio n. 5
0
    def _make_final_challenge(self, username, realm, cnonce, digest_uri,
                              response_val, authzid, nonce_count):
        """Send the second challenge in reply to the client response.

        :Parameters:
            - `username`: user name.
            - `realm`: realm.
            - `cnonce`: cnonce value.
            - `digest_uri`: digest-uri value.
            - `response_val`: response value computed by the client.
            - `authzid`: authorization id.
            - `nonce_count`: nonce count value.
        :Types:
            - `username`: `bytes`
            - `realm`: `bytes`
            - `cnonce`: `bytes`
            - `digest_uri`: `bytes`
            - `response_val`: `bytes`
            - `authzid`: `bytes`
            - `nonce_count`: `bytes`

        :return: a challenge, a success indicator or a failure indicator.
        :returntype: `sasl.Success` or `sasl.Failure`
        """

        username_uq = username.replace(b'\\', b'')
        if authzid:
            authzid_uq = authzid.replace(b'\\', b'')
        else:
            authzid_uq = None
        if realm:
            realm_uq = realm.replace(b'\\', b'')
        else:
            realm_uq = None
        digest_uri_uq = digest_uri.replace(b'\\', b'')
        props = dict(self.in_properties)
        props["realm"] = realm_uq.decode("utf-8")
        password, pformat = self.password_database.get_password(
            username_uq.decode("utf-8"), (u"plain", u"md5:user:realm:pass"),
            props)
        if pformat == u"md5:user:realm:pass":
            urp_hash = password.a2b_hex()
        elif pformat == u"plain":
            urp_hash = _make_urp_hash(username, realm,
                                      password.encode("utf-8"))
        else:
            logger.debug(u"Couldn't get password.")
            return Failure(u"not-authorized")
        valid_response = _compute_response(urp_hash, self.nonce, cnonce,
                                           nonce_count, authzid, digest_uri)
        if response_val != valid_response:
            logger.debug(u"Response mismatch: {0!r} != {1!r}".format(
                response_val, valid_response))
            return Failure(u"not-authorized")
        try:
            fields = digest_uri_uq.split(b"/")
            if len(fields) == 3:
                serv_type, host, serv_name = [
                    f.decode("utf-8") for f in fields
                ]
            elif len(fields) == 2:
                serv_type, host = [f.decode("utf-8") for f in fields]
                serv_name = None
            else:
                raise ValueError
        except (ValueError, UnicodeError):
            logger.debug("Bad digest_uri: {0!r}".format(digest_uri_uq))
            return Failure("not-authorized")
        if "service-type" in self.in_properties:
            if serv_type != self.in_properties["service-type"]:
                logger.debug(u"Bad serv-type: {0!r} != {1!r}".format(
                    serv_type, self.in_properties["service-type"]))
                return Failure("not-authorized")
        if "service-domain" in self.in_properties:
            if serv_name:
                if serv_name != self.in_properties["service-domain"]:
                    logger.debug(u"serv-name: {0!r} != {1!r}".format(
                        serv_name, self.in_properties["service-domain"]))
                return Failure("not-authorized")
            elif (host != self.in_properties["service-domain"]
                  and host != self.in_properties.get("service-hostname")):
                logger.debug(u"bad host: {0!r} != {1!r}"
                             u" & {0!r} != {2!r}".format(
                                 host, self.in_properties["service-domain"],
                                 self.in_properties.get("service-hostname")))
                return Failure("not-authorized")
        if "service-hostname" in self.in_properties:
            if host != self.in_properties["service-hostname"]:
                logger.debug(u"bad host: {0!r} != {1!r}".format(
                    host, self.in_properties["service-hostname"]))
                return Failure("not-authorized")
        rspauth = _compute_response_auth(urp_hash, self.nonce, cnonce,
                                         nonce_count, authzid, digest_uri)
        if authzid_uq is not None:
            authzid_uq = authzid_uq.decode("utf-8")
        self.out_properties = {
            "username": username.decode("utf-8"),
            "realm": realm.decode("utf-8"),
            "authzid": authzid_uq,
            "service-type": serv_type,
            "service-domain": serv_name if serv_name else host,
            "service-hostname": host
        }
        return Success(self.out_properties, b"rspauth=" + rspauth)
Esempio n. 6
0
 def finish(self, data):
     return Success(None)
Esempio n. 7
0
 def finish(self, data):
     self.username = kerberos.authGSSClientUserName(self._gss)
     logger.debug("Authenticated as {0!r}".format(
         kerberos.authGSSClientUserName(self._gss)))
     return Success({"username": self.username, "authzid": self.authzid})