Class SaslMechanism.

Inherits EventHandler. Inherited by Anonymous, CramMD5, DigestMD5, Plain and SaslLogin.

A generic SASL authentication mechanism (RFC 2222)

This abstract base class represents a SASL authentication mechanism.

Each mechanism handler is implemented as a state machine, starting in the IssuingChallenge state, entering the AwaitingResponse state after a challenge() has been issued, reading the client's response with readResponse(), entering the Authenticating state in execute(), and entering either the Succeeded or Failed state when verify() is able to make a final decision.

The caller is expected to retrieve and send the challenge() to the client when the handler is in the IssuingChallenge state; to call the readResponse() function when the client sends a response, and to call execute() to begin verification. The mechanism will call its owner back when it is done().

If the mechanism supports a SASL initial response, it starts in the AwaitingInitialResponse state, and the caller may choose to either call readResponse() with the initial response, or change into the IssuingChallenge state and proceed as normal.

SaslMechanism subclasses must implement challenge(), readResponse(), and verify(). The default implementation of challenge() and verify() is suitable for Anonymous and Plain authentication.

The create() function returns a pointer to a newly-created handler for a named SASL authentication mechanism.

SaslMechanism::SaslMechanism( EventHandler * cmd, Type type )

Constructs an SaslMechanism of type in ChallengeNeeded mode on behalf of cmd.

static bool SaslMechanism::allowed( Type mechanism, bool privacy )

Returns true if mechanism is currently allowed, and false if not. If privacy is true, allowed() assumes that the connection does not use plain-text transmission.

static EString SaslMechanism::allowedMechanisms( const EString & prefix, bool privacy )

Returns a list of space-separated allowed mechanisms. If privacy is false and plain-text passwords disallowed, such mechanisms are not included.

Each mechanism is prefixed by prefix.

EString SaslMechanism::challenge()

This virtual function returns a challenge when the SaslMechanism is in IssuingChallenge mode. The caller must send the challenge to the client, and set the SaslMechanism to the AwaitingResponse state (so that reimplementations of this function don't need to).

The return value should be a simple string, neither Base64-encoded, nor prefixed with "+". The default implementation is suitable for challenge-less authentication.

static SaslMechanism * SaslMechanism::create( const EString & mechanism, EventHandler * command, SaslConnection * connection )

This static method creates and returns a pointer to a handler for the named mechanism on behalf of command and connection. Returns 0 if the mechanism is unsupported or not allowed. Ignores case in comparing the name.

bool SaslMechanism::done() const

Returns true if this SaslMechanism has reached a final decision about the current authentication request.

void SaslMechanism::execute()

This function expects to be called after setLogin() and setSecret(), which are typically called during readResponse(). It obtains the user's data from the database, checks the user-submitted password against the correct one, and enters the Authenticating state. It expects its parent Command to call it each time a Query notification occurs. It remains in the same state until it has enough data to make a decision.

If the login() name does not exist, this function sets the state to Failed. Otherwise, it calls verify(), which is expected to validate the request and set the state appropriately.

Reimplements EventHandler::execute().

void SaslMechanism::log( const EString & m, Log::Severity s )

Logs message m with severity s.

UString SaslMechanism::login() const

Returns the login name supplied by the client, or the empty string if no login has been set with setLogin().

EString SaslMechanism::name() const

Returns the canonical name of this object's SASL type, in lower case. For example, "cram-md5" in the case of CramMD5.

void SaslMechanism::parseResponse( const EString & response )

This pure virtual function handles a client response. response is the decoded representation of the client's response. response may contain NULs.

void SaslMechanism::readInitialResponse( const EString * r )

Reads an initial response from r, which may be 0 to indicate that no initial-response was supplied.

void SaslMechanism::readResponse( const EString * r )

Reads a response from r, which may be 0 to indicate that no response is available.

UString SaslMechanism::secret() const

Returns the secret supplied by the client, or the empty string if no secret has been set with setSecret().

void SaslMechanism::setChallenge( const EString & c )

This function is only meant to be used while testing SaslMechanism subclasses. This implementation does nothing; if a subclass uses a non-default challenge(), it should also reimplement this and use c as challenge.

void SaslMechanism::setLogin( const EString & name )

Like the other setLogin(), except that it converts name from UTF-8 to unicode first. If name is not valid UTF-8, setLogin() sets the name to an empty string and logs the problem.

void SaslMechanism::setLogin( const UString & name )

This function tells the SaslMechanism that the client supplied the name as its authorization identity. This is usually called by readResponse(), and the value is used by execute().

void SaslMechanism::setSecret( const EString & secret )

Like the other setSecret(), except that it converts secret from UTF-8 to unicode first. If secret is not valid UTF-8, setSecret() sets the secret to an empty string and logs the problem.

void SaslMechanism::setSecret( const UString & secret )

This function tells the SaslMechanism that the client supplied the secret with its credentials. Usually called by readResponse(), and the value is used by execute().

void SaslMechanism::setState( State newState )

Sets this authenticator's state to newState.

void SaslMechanism::setStoredSecret( const UString & s )

This function is only meant to be used while testing SaslMechanism subclasses. It sets the stored secret to s, rather than waiting for it to be retrieved from the database by execute().

State SaslMechanism::state() const

Returns this SaslMechanism's state, which is one of the following:

1. IssuingChallenge: Wants the server to issue another challenge(). 2. AwaitingResponse: Waiting for readResponse() to be called. 3. Authenticating: Waiting for execute() to hear from the database. 4. Succeeded: The authentication request succeeded. 5. Failed: The authentication request failed. 6. Terminated: The exchange was terminated by client request.

The initial value is IssuingChallenge.

UString SaslMechanism::storedSecret() const

Returns the secret stored on the server for the login name supplied by the client. This function expects to be called by verify(), i.e. after execute() has obtained the stored secret from the database.

void SaslMechanism::tick()

Calls GraphableCounter::tick() on the right object to account for a login failure or success. Does nothing if none of the tickers are appropriate.

Type SaslMechanism::type() const

Returns this object's SASL type, as set by the constructor.

User * SaslMechanism::user() const

Returns the user logged in by this mechanism, or a null pointer if authentication has not succeeded (yet).

void SaslMechanism::verify()

This virtual function returns true if the secret() supplied by the client corresponds to the storedSecret() on the server. It expects to be called by execute() after all relevant information has been obtained.

The default implementation is suitable for Anonymous or Plain text authentication. It returns true if the stored secret is empty, or matches the client-supplied secret, or if the user is trying to log in as anonymous and that's permitted.


This virtual destructor exists only to facilitate safe inheritance.

Reimplements EventHandler::~EventHandler().

This web page based on source code belonging to The Archiveopteryx Developers. All rights reserved.