Using the Mechanisms
Once the application has created a mechanism, it uses the mechanism to obtain SASL tokens to exchange with the peer. The client typically indicates to the server via the application protocol which mechanism to use. Some protocols allows the client to accompany the request with an optional initial response for mechanisms that have an initial response. This feature can be used to reduce the number of message exchanges that are required for authentication. Here is an example of how a client might use SaslClient for authentication.
// Get optional initial response
byte[] response = (sc.hasInitialResponse() ? sc.evaluateChallenge(new byte[]) : null);
String mechanism = sc.getName();
// Send selected mechanism name and optional initial response to server
send(mechanism, response);
// Read response
msg = receive();
while (!sc.isComplete() && (msg.status == CONTINUE || msg.status == SUCCESS)) {
// Evaluate server challenge
response = sc.evaluateChallenge(msg.contents);
if (msg.status == SUCCESS) {
// done; server doesn't expect any more SASL data
if (response != null) {
throw new IOException(“Protocol error: attempting to send response after completion”);
}
break;
} else {
send(mechanism, response);
msg = receive();
}
}
The client application iterates through each step of the authentication by using the mechanism (sc) to evaluate the challenge gotten from the server and to get a response to send back to the server. It continues this cycle until either the mechanism or application-level protocol indicates that the authentication has completed, or if the mechanism cannot evaluate a challenge. If the mechanism cannot evaluate the challenge, it throws an exception to indicate the error and terminates the authentication. Disagreement between the mechanism and protocol about the completion state must be treated as an error because it might indicate a compromise of the authentication exchange.
Here is an example of how a server might use SaslServer.
// Read request that contains mechanism name and optional initial response
msg.receive();
// Obtain a SaslServer to perform authentication
SaslServer ss = Sasl.createSaslServer(msg.mechanism, protocol, myName, props, callbackHandler);
// Perform authentication steps until done
while (!ss.isComplete()) {
try {
// Process response
byte[] challenge = sc.evaluateResponse(msg.contents);
if (ss.isComplete()) {
send(mechanism, challenge, SUCCESS);
} else {
send(mechanism, challenge, CONTINUE);
msg.receive();
}
} catch (SaslException e) {
send(ERROR);
sc.dispose();
break;
}
}
The server application iterates through each step of the authentication by giving the clients response to the mechanism (ss) to process. If the response is incorrect, the mechanism indicates the error by throwing a SaslException so that the server can report the error and terminate the authentication. If the response is correct, the mechanism returns challenge data to be sent to the client and indicates whether the authentication is complete. Note that challenge data can accompany a success indication. This might be used, for example, to tell the client to finalize some negotiated state.