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")
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})
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)
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)
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)
def finish(self, data): return Success(None)
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})