Class Ht2SaslServer
- All Implemented Interfaces:
SaslServer
The initiator message format (NUL-byte separated) is:
authcid NUL extra-initiator-values NUL initiator-hashed-tokenwhere
initiator-hashed-token = HMAC(token, "Initiator" || cb-data || extra-initiator-values)
and the HMAC algorithm is derived from the mechanism name (e.g. HmacSHA256 for SHA-256 variants
and HmacSHA3-512 for SHA3-512 variants).
For the NONE (no channel binding) variant, cb-data is an empty byte sequence.
On success the server sends back a success message:
NUL extra-responder-values NUL responder-hashed-tokenwhere
responder-hashed-token = HMAC(token, "Responder" || cb-data || extra-responder-values).
This provides mutual authentication.
This is a two-message mechanism: the client sends one message; the server evaluates it
and returns the responder proof via SaslServer.evaluateResponse(byte[]).
Channel-binding data is resolved by the base class AbstractHtSaslServer before
doEvaluateResponse(byte[], byte[]) is called. Unlike HT-*, the channel-binding bytes are incorporated
into the HMAC computation. Authentication is rejected if channel-binding data cannot be
retrieved — matching the SCRAM-SHA-1-PLUS behaviour.
- See Also:
-
AbstractHtSaslServerHtSaslServer
-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected Stringprotected booleanprotected final StringThe SASL mechanism name (e.g.The SASL properties map; must contain aLocalSessionunderLocalSession.class.getCanonicalName()protected FastTokenprotected final org.jivesoftware.openfire.sasl.AbstractHtSaslServer.HashedTokenValidator -
Constructor Summary
ConstructorsConstructorDescriptionHt2SaslServer(String mechanismName, Map<String, ?> props) Constructs anHt2SaslServerfor the given mechanism name. -
Method Summary
Modifier and TypeMethodDescriptionprotected StringdecodeAuthcId(String value) Converts theauthcidfrom a FAST initiator message into a normalized local username.protected final StringdecodeUtf8(byte[] value, int offset, int length, String field) voiddispose()protected byte[]doEvaluateResponse(byte[] response, byte[] channelBindingData) Evaluates the client's initiator message (mechanism-specific part).final byte[]evaluateResponse(byte[] response) Evaluates the client's response.getNegotiatedProperty(String propName) Returns the rotated FAST token produced after successful authentication, ornullif authentication has not completed successfully.protected static intindexOf(byte[] array, byte target, int fromIndex) Returns the index of the first occurrence oftargetinarraystarting atfromIndex, or-1if not found.booleanprotected final voidrecordAuthenticatedClient(String clientId) protected byte[]Resolves the channel-binding data for this mechanism.byte[]unwrap(byte[] incoming, int offset, int len) byte[]wrap(byte[] outgoing, int offset, int len)
-
Field Details
-
mechanismName
The SASL mechanism name (e.g.HT-SHA-256-NONEorHT2-SHA-512-EXPR). -
props
The SASL properties map; must contain aLocalSessionunderLocalSession.class.getCanonicalName() -
tokenValidator
protected final org.jivesoftware.openfire.sasl.AbstractHtSaslServer.HashedTokenValidator tokenValidator -
complete
protected boolean complete -
authorizationId
-
rotatedToken
-
-
Constructor Details
-
Ht2SaslServer
Constructs anHt2SaslServerfor the given mechanism name.The mechanism name must follow the pattern
HT2-{HASH}-{CBTYPE}, e.g.HT2-SHA-256-NONE,HT2-SHA-512-UNIQ, orHT2-SHA3-512-EXPR.- Parameters:
mechanismName- the SASL mechanism name (cannot be null)props- the SASL properties map, which must contain theLocalSessioninstance underLocalSession.class.getCanonicalName()for UNIQ/ENDP/EXPR channel-binding variants (cannot be null)
-
-
Method Details
-
doEvaluateResponse
protected byte[] doEvaluateResponse(byte[] response, byte[] channelBindingData) throws SaslException Evaluates the client's initiator message (mechanism-specific part).Called by
SaslServer.evaluateResponse(byte[])after guard checks and channel-binding resolution. ThechannelBindingDatabytes are incorporated into the HMAC computation performed byFastTokenManager.validateTokenHt2(java.lang.String, java.lang.String, java.lang.String, byte[], byte[], java.lang.String, java.lang.String).Expected format:
authcid NUL extra-initiator-values NUL initiator-hashed-token- Parameters:
response- the client's initiator message bytes (never null or empty)channelBindingData- the resolved channel-binding bytes (empty for NONE variants)- Returns:
- the responder success message:
NUL extra-responder-values NUL responder-hashed-token - Throws:
SaslException- if authentication fails
-
dispose
- Specified by:
disposein interfaceSaslServer- Throws:
SaslException
-
recordAuthenticatedClient
-
getMechanismName
- Specified by:
getMechanismNamein interfaceSaslServer
-
evaluateResponse
Evaluates the client's response.This method handles the common guard checks (already-complete, null/empty response) and resolves channel-binding data for the mechanism's CB variant before delegating to
doEvaluateResponse(byte[], byte[]).- Specified by:
evaluateResponsein interfaceSaslServer- Parameters:
response- the client response bytes- Returns:
- mechanism-specific success bytes (the responder HMAC for HT-*, or the framed responder proof for HT2-*)
- Throws:
SaslException- if authentication fails
-
resolveChannelBindingData
Resolves the channel-binding data for this mechanism.The channel-binding type is derived from the mechanism name suffix:
-UNIQ→tls-unique,-ENDP→tls-server-end-point,-EXPR→tls-exporter,-NONE→ no channel binding (empty array).For non-NONE variants the server verifies that the required binding type is available, retrieves the actual bytes from the live TLS session, and throws
SaslExceptionif they cannot be obtained — matching the SCRAM-SHA-1-PLUS behaviour.- Returns:
- the channel-binding bytes (never null; empty array for NONE variants)
- Throws:
SaslException- if channel-binding data is required but cannot be retrieved
-
isComplete
public boolean isComplete()- Specified by:
isCompletein interfaceSaslServer
-
getAuthorizationID
- Specified by:
getAuthorizationIDin interfaceSaslServer
-
getRotatedToken
Returns the rotated FAST token produced after successful authentication, ornullif authentication has not completed successfully.- Returns:
- the rotated
FastToken, ornull
-
unwrap
- Specified by:
unwrapin interfaceSaslServer- Throws:
SaslException
-
wrap
- Specified by:
wrapin interfaceSaslServer- Throws:
SaslException
-
getNegotiatedProperty
- Specified by:
getNegotiatedPropertyin interfaceSaslServer
-
indexOf
protected static int indexOf(byte[] array, byte target, int fromIndex) Returns the index of the first occurrence oftargetinarraystarting atfromIndex, or-1if not found. -
decodeUtf8
protected final String decodeUtf8(byte[] value, int offset, int length, String field) throws SaslException - Throws:
SaslException
-
decodeAuthcId
Converts theauthcidfrom a FAST initiator message into a normalized local username. The value is expected to be a bare username, but a domain-qualified form (username@domain) is also accepted, provided that the domain matches the domain of this server. In both cases the returned value is the stringprep'ed node, which is the form that the caller compares against the username claimed in the stream's 'from' attribute.- Parameters:
value- the raw authcid as sent by the client (cannot be null)- Returns:
- the normalized local username (never null)
- Throws:
SaslException- if the value cannot be prepared as a username, or names another domain
-