Apache Directory Server Authentication methods

ADS follows the RFC 4513 which describes the authentication methods and security mechanisms of the LDAP protocol.

We will describe more specifically the implementation details of this RFC for documentation purposes.

Authentication methods

LDAP allows two authentication methods :

  • Simple
  • SASL 

It is important to be aware that the Anonymous authentication is just a specific case of a Simple authentication.
Another important point is that neither Simple not SASL offer a protection for the exchanged data.This is handled on another layer.

 Securing the communication

As communication are not protected by default, we have to implement one of the two following mechanisms in order to provide some secure communication :

  • SSL
  • TLS

Both mechanisms are available in Apache DS.

Authorization state

The default authorization state for a session is Anonymous until a BindRequest is successfully completed. An authorized session is immediately moved to an Anonymous state as soon as a BindRequest is received, whatever it's previous state was. That means

Authentication

Authentication is done through a BindRequest, which is described by this ASN.1 portion of the LDAP protocol grammar :

BindRequest ::= [APPLICATION 0] SEQUENCE {
             version                 INTEGER (1 ..  127),
             name                    LDAPDN,
             authentication          AuthenticationChoice }

        AuthenticationChoice ::= CHOICE {
             simple                  [0] OCTET STRING,
                                     -- 1 and 2 reserved
             sasl                    [3] SaslCredentials,
             ...  }

        SaslCredentials ::= SEQUENCE {
             mechanism               LDAPString,
             credentials             OCTET STRING OPTIONAL }

Simple authentication

The simple authentication is done through a Bind Request. It provides three authentication mechanisms :

  • anonymous 
  • unauthenticated
  • name/password

All those three mechanisms are deduced from the content of the BindRequest, when the Simple field for the AuthenticationChoice is set.
We have four different possibilities here :

BaseDN

password

Authentication

comment

empty

empty

Anonymous

This is the default server state for any unauthenticated user

"xyz"

empty

Unauthenticated

For trace purpose only. The server should throw an UnwillingToPerform result

"xyz"

abc

name/password

Check for this user if it has the pasword in the set of passwords it stores
If the baseDN  is incorrect, returns an InvalidDNSyntax result
If the authentication fails for any other reason, an InvalidCredentials result is returned

empty

abc

undefined

not accepted by ADS

Implementation

For a simple authentication, the following algorithm is applied :

a BindRequest message is received
if  the version is not LDAP V3,
  error
if the bindRequest is a simple authentication,
  then
    create a BindOperationContext,
    store the baseDN, the credentials, the controls
    call the OperationManager.bind() method

Tests

We need to cover all the different cases with the tests. Here are the list of possible tests :

  • SimpleBindUserPassword : try to connect using a known user/password and read an entry.
  • SimpleBindUserBadPassword : try to connect using a known user but with a bad password: we should get a invalidCredentials error.
  • SimpleBindBadUserPassword : try to connect using a user with an invalid DN: we should get a invalidDNSyntax error.
  • SimpleBindUnknowUserPassword : try to connect using a unknown user: we should get a invalidCredentials error.
  • SimpleBindNoUserNoPassword : covers the anonymous authentication : we should be able to read the rootDSE, but that's it
  • SimpleBindUserNoPassword : covers the Unauthenticated case : we should get a UnwillingToPerform error.
  • SimpleBindNoUserPassword : not allowed by the server. We should get a invalidCredentials error.

SASL authentication

The SASL authentication is more complex. It's described in RFC 4513. It should be the prefered authentication mechanism used for every LDAP connection, a it guarantee some level of security Simple authentication can't offer.

SASL permits the client to negociate an authentication mechanism using the LDAP protocol during the handshake phase. It's important to understand that SASL by itself does not offer any kind of confidentiality, it's the negociated mechanism which does.

Last, not least, SASL and SSL/TLS can work in pair, in this case we perform SASL EXTERNAL authentication, EXTERNAL being a SASL mechanism.

SASL mechanisms

SASL existing mechanisms are listed here :

name

Frequency

link

ADS implementation

KERBEROS_V4

OBSOLETE

RFC2222

(error)

GSSAPI

COMMON

RFC4752

(tick)

SKEY

OBSOLETE

RFC2444

(error)

EXTERNAL

COMMON

RFC4422

(tick)

CRAM-MD5

LIMITED

RFC2195

(tick)

ANONYMOUS

COMMON

RFC4505

(tick)

OTP

COMMON

RFC2444

(error)(warning) May be implemented

GSS-SPNEGO

LIMITED

Paul Leach

(error)(warning) Will be implemented

PLAIN

COMMON

RFC4616

(tick)

SECURID

COMMON

RFC2808

(error)

NTLM

LIMITED

Paul Leach

(tick)

NMAS_LOGIN

LIMITED

Mark G. Gayman

(error)

NMAS_AUTHEN

LIMITED

Mark G. Gayman

(error)

DIGEST-MD5

COMMON

RFC2831

(tick)

9798-U-RSA-SHA1-ENC

COMMON

RFC3163

(error)

9798-M-RSA-SHA1-ENC

COMMON

RFC3163

(error)

9798-U-DSA-SHA1

COMMON

RFC3163

(error)

9798-M-DSA-SHA1

COMMON

RFC3163

(error)

9798-U-ECDSA-SHA1

COMMON

RFC3163

(error)

9798-M-ECDSA-SHA1

COMMON

RFC3163

(error)

KERBEROS_V5

COMMON

Simon Josefsson

(error)(warning) Will be implemented

NMAS-SAMBA-AUTH

LIMITED

Vince Brimhall

(error)

A client can request the list of the server supported list of mechanisms by readng the supportedSASLMechanisms attribute from the root DSE, this attribute being available even if the client use an anonymous authorization.

Implementation

In order to get SASL working for a specific mechanism XYZ, we must implement two or three interfaces :

  • MechanismHandler, in charge of creating a SaslServer instance, or to get the current one for the ongoing session
  • CallbackHandler, if we need to get some information like the Name, Password, etc...
  • Optionally, SaslServer, if we need an instance which is not already provided by the underlying VM

The Java 5 JVM provides SaslServer instances for GSSAPI, CramMD5 and DigestMD5 mechanisms. For PLAIN mechanim, we will just implement our own SaslServer.

Client/Server dialog

SASL is a challenge/response system. A client initiate the communication, and the server replied either by validating the request, discarding it or asking for more information. The exchange goes on until we reach a state where the session is either validated or terminated.

From the server point of view, when it receives a BindRequest, it should check if it's a new request, or a reply to a challenge it has sent back to the client. We will store the current state in the LdapSession instance.

The Session state can be one of :

  • anonymous
  • bind in progress
  • bound

The following schema shows the different possible transitions :

We have to store this state into the LdapSession so that we can determinate what to do with the incoming BindRequest received from a client.

Another important point is that each mechanism has to manage its own state machine : more than one Challenge/Response exchange can be necessary in order to get the authentication done. As this is an opaque mechanism from the server point of view, this has to be handled in a plugable mechanism (and this is why we have to implement the three former interfaces).

What is important to know is that if the server receives two consecutive BindRequests, if the second one's mechanism is empty or different from the first one, the Session state is set back to "not bound". Sending an empty mechanism is one way to stop a authentication being processed, if the client wants to redo the authentication with the same mechanism, the other one being to switch to Simple authentication.

In any case, the client can send more than just a BindRequest with the mechanism. In order to reduce the challenge/response roundtrip, the client can send some informations as if it responds to the next server challenge. For instance, if the client wants to use the PLAIN mechanism, it can feed the credentials with an opaque information, containing the authentication Id, the password, and optionally the authorization Id (this is described in RFC 4616) The server can then decipher this opaque data and do the authentication immediately.

ANONYMOUS SASL mechanism implementation

The ANONYMOUS mechanism, if used, will default to a simple bindRequest.

PLAIN SASL mechanism implementation

We don't have an implementation for PLAIN mechanism on the server side in the JDK, so we have to implement it ourself.

There are two possibilities :

  • the client don't send any credentials within the first BindRequest : we will have a C/R requesting for these credentials
  • the client send the initial BindRequest with a credentials containing the authcid and password information : we will use them to check if this user exists in the backend. Note that it fall back in the SimpleBind user/password authentication.

We don't currently support the authzid field, ie we don't proxy the authorization.

PLAN SaslServer implementation

GSSAPI SASL mechanism implementation

CRAM-MD5 SASL mechanism implementation

DIGEST-MD5 SASL mechanism implementation

NTLM SASL mechanism implementation

EXTERNAL SASL mechanism implementation

{}

  • No labels