By default Halon supports two SASL AUTH mechanisms (LOGIN and PLAIN), both of which are simple username/password based methods, which does note require complex state transitions or a server based reply in order to obtain a username and password which can then be easily authenticated in the AUTH script. There are various way of verifying the username and password. Common way of doing so in Halon MTA includes
- Forwarding SMTP lookup (connect to another SMTP server to verify the same username/password)
- LDAP bind lookup
- API lookup using eg. HTTP to verify credentials
- Dovecot AUTH
- A manual list of usernames and passwords
However other SASL mechanisms exist and most of them do not have a simple username/password scheme, some rely on a server generated challenge or multiple steps (responses/replies) in order to authenticate the user (e.g. OAUTHBEARER, OTP and CRAM-MD5). In order to enable you to build custom authentication we've given you direct access to the client response data (as defined by rfc4954), and also the ability to send a custom reply (response) while holding a state in the AUTH script.
The initial client response will be available in the first execution of the AUTH script (in the $saslresponse) variable. The $saslstate will be zero.
AUTH mechanism [initial-response]
You may then choose any of the four functions
- Accept - Accept the request (you should also set the username by argument).
- Defer - Deny the authentication request with a temporary error.
- Reject - Deny the authentication request with a permanent error.
- Reply - Send a reply, which will cause the next user-input to execute the authentication script again.
The actions of Accept, Defer and Reject are straight forward regardless of the $saslstate they are called in, so let us focus on how to use the Reply functions. The Reply function sends a 334 reply to the client with the response you provided base64 encoded. The next user input will execute the AUTH script once again with $saslstate incremented by one (in this example it's gonna be one).
334 [reply]
[client-response]
This chat scheme will move on until you call either Accept, Defer or Reject. In order to save state between each AUTH script execution, you can store data in the $context variable, based on the current $saslstate.
In order to announce and support (run the AUTH script for that mechanism) custom SASL mechanism you will need to add them to the SMTP servers list of supported mechanisms. That is done on the Configuration -> Email engine -> Settings page per SMTP server configuration.
CRAM-MD5
In this section we will implement the CRAM-MD5 mechanism to our AUTH script. We start by announcing support for it to the SMTP server on the Configuration -> Email engine -> Settings page, add CRAM-MD5 to the Mechanisms input field alongside the other mechanisms (e.g. LOGIN,PLAIN). Then add the following to your AUTH script.
if ($saslmechanism == "CRAM-MD5")
{
if ($saslstate == 0)
{
if ($saslresponse != none)
Reject("Bad syntax");
$context["saslchallenge"] = "<" . uuid() . "@" . gethostname() . ">";
Reply($context["saslchallenge"]);
}
if ($saslstate == 1)
{
[$username, $password] = explode(" ", $saslresponse);
if ($username == "john.doe" and $password == hmac_md5("secret", $context["saslchallenge"]))
Accept(["username" => $username]);
Reject("Sorry");
}
}
Comments
0 comments
Article is closed for comments.