5.6. The DIGEST-MD5 mechanism

The DIGEST-MD5 mechanism is based on the same cryptographic operation as CRAM-MD5 but supports more features, such as an authorization identity (proxy authentication) and cryptographic protection of data. Like CRAM-MD5, only a hashed password is transfered, which means that you cannot use e.g. PAM as a backend since it does not support extraction of passwords. Two ways of validating the user is provided, either by having the SASL mechanism retrieve the raw password from the application and perform the validation internally, or by having the SASL mechanism retrieve a hashed version of the secret. The advantage of using the latter method is that you do not need to store plain text user passwords on the server, but rather a one-way hash of the username, realm and password. Still, this one-way hash of the secret should be handled the same way as a clear text password. The advantage is that if someone steals the one-way hash she cannot immediately read users' password. If both the callbacks are specified by the application, the one which retrieve the secret hash will be used.

While not documented in the original DIGEST-MD5 specification, this implementation normalizes the username and the authentication identity using the Unicode 3.2 NFKC form according to the proposed update of DIGEST-MD5.

This mechanism is only enabled in the client and server if you implement the respectively callbacks below and set them in the library (Chapter 7).

int (*Gsasl_client_callback_authentication_id) (Gsasl_session_ctx * ctx, char * out, size_t * outlen) ctx: libgsasl handle.

out: output array with authentication identity.

outlen: on input the maximum size of the output array, on output contains the actual size of the output array.

Type of callback function the application implements. It should populate the output array with authentiction identity of user and set the output array length, and return GSASL_OK, or fail with an error code. The authentication identity must be encoded in UTF-8, but need not be normalized in any way.

If OUT is NULL, the function should only populate the output length field with the length, and return GSASL_OK. This usage may be used by the caller to allocate the proper buffer size.

int (*Gsasl_client_callback_authorization_id) (Gsasl_session_ctx * ctx, char * out, size_t * outlen) ctx: libgsasl handle.

out: output array with authorization identity.

outlen: on input the maximum size of the output array, on output contains the actual size of the output array.

Type of callback function the application implements. It should populate the output array with authorization identity of user and set the output array length, and return GSASL_OK, or fail with an error code. The authorization identity must be encoded in UTF-8, but need not be normalized in any way.

If OUT is NULL, the function should only populate the output length field with the length, and return GSASL_OK. This usage may be used by the caller to allocate the proper buffer size.

int (*Gsasl_client_callback_password) (Gsasl_session_ctx * ctx, char * out, size_t * outlen) ctx: libgsasl handle.

out: output array with password.

outlen: on input the maximum size of the output array, on output contains the actual size of the output array.

Type of callback function the application implements. It should populate the output array with password of user and set the output array length, and return GSASL_OK, or fail with an error code. The password must be encoded in UTF-8, but need not be normalized in any way.

If OUT is NULL, the function should only populate the output length field with the length, and return GSASL_OK. This usage may be used by the caller to allocate the proper buffer size.

int (*Gsasl_client_callback_service) (Gsasl_session_ctx * ctx, char * service, size_t * servicelen, char * hostname, size_t * hostnamelen, char * servicename, size_t * servicenamelen) ctx: libgsasl handle.

service: output array with name of service.

servicelen: on input the maximum size of the service output array, on output contains the actual size of the service output array.

hostname: output array with hostname of server.

hostnamelen: on input the maximum size of the hostname output array, on output contains the actual size of the hostname output array.

servicename: output array with generic name of server in case of replication (DIGEST-MD5 only).

servicenamelen: on input the maximum size of the servicename output array, on output contains the actual size of the servicename output array.

Type of callback function the application implements. It should retrieve the service (which should be a registered GSSAPI host based service name, such as “imap”) on the server, hostname of server (usually canoncial DNS hostname) and optionally generic service name of server in case of replication (e.g. “mail.example.org” when the hostname is “mx42.example.org”, see the RFC 2831 for more information). It should return GSASL_OK, or an error such as GSASL_AUTHENTICATION_ERROR if it fails.

If SERVICE, HOSTNAME or SERVICENAME is NULL, the function should only populate SERVICELEN, HOSTNAMELEN or SERVICENAMELEN with the output length of the respective field, and return GSASL_OK. This usage may be used by the caller to allocate the proper buffer size. Furthermore, SERVICENAMELEN may also be NULL, indicating that the mechanism is not interested in this field.

int (*Gsasl_server_callback_retrieve) (Gsasl_session_ctx * ctx, char * authentication_id, char * authorization_id, char * realm, char * key, size_t * keylen) ctx: libgsasl handle.

authentication_id: input array with authentication identity.

authorization_id: input array with authorization identity, or NULL.

realm: input array with realm of user, or NULL.

key: output array with key for authentication identity.

keylen: on input the maximum size of the key output array, on output contains the actual size of the key output array.

Type of callback function the application implements. It should retrieve the password for the indicated user and return GSASL_OK, or an error code such as GSASL_AUTHENTICATION_ERROR. The key must be encoded in UTF-8, but need not be normalized in any way.

If KEY is NULL, the function should only populate the KEYLEN output length field with the length, and return GSASL_OK. This usage may be used by the caller to allocate the proper buffer size.

int (*Gsasl_server_callback_digest_md5) (Gsasl_session_ctx * ctx, char * username, char * realm, char * secrethash) ctx: libgsasl handle.

username: input array with authentication identity of user.

realm: input array with realm of user.

secrethash: output array that should contain hash of username, realm and password as described for the DIGEST-MD5 mechanism.

Type of callback function the application implements. It should retrieve the secret hash for the given user in given realm and return GSASL_OK, or an error such as GSASL_AUTHENTICATION_ERROR if it fails. The secrethash buffer is guaranteed to have size for the fixed length MD5 hash.