negotiate method
- XMLNode nonza
override
Called with the currently received nonza nonza
when the negotiator is active.
If the negotiator is just elected to be the next one, then nonza
is equal to
the <stream:features /> nonza.
Returns the next state of the negotiator. If done or retryLater is selected, then negotiator won't be called again. If retryLater is returned, then the negotiator must switch some internal state to prevent getting matched immediately again. If ready is returned, then the negotiator indicates that it is not done with negotiation.
Implementation
@override
Future<Result<NegotiatorState, NegotiatorError>> negotiate(
XMLNode nonza,
) async {
switch (_scramState) {
case ScramState.preSent:
attributes.sendNonza(
SaslScramAuthNonza(
body: await getRawStep(''),
type: hashType,
),
);
return const Result(NegotiatorState.ready);
case ScramState.initialMessageSent:
if (nonza.tag != 'challenge') {
final error = nonza.children.first.tag;
await attributes.sendEvent(AuthenticationFailedEvent(error));
_scramState = ScramState.error;
return Result(
SaslError.fromFailure(nonza),
);
}
attributes.sendNonza(
SaslScramResponseNonza(body: await getRawStep(nonza.innerText())),
);
return const Result(NegotiatorState.ready);
case ScramState.challengeResponseSent:
if (nonza.tag != 'success') {
// We assume it's a <failure />
final error = nonza.children.first.tag;
await attributes.sendEvent(AuthenticationFailedEvent(error));
_scramState = ScramState.error;
return Result(
SaslError.fromFailure(nonza),
);
}
if (!_checkSignature(nonza.innerText())) {
// TODO(Unknown): Notify of a signature mismatch
//final error = nonza.children.first.tag;
//attributes.sendEvent(AuthenticationFailedEvent(error));
_scramState = ScramState.error;
return Result(
SaslError.fromFailure(nonza),
);
}
attributes.setAuthenticated();
return const Result(NegotiatorState.done);
case ScramState.error:
return Result(
SaslError.fromFailure(nonza),
);
}
}