Subject: java api bind() methods

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Tue, 03 Apr 2001 11:54:41 -0700

A few questions regarding the LDAPConnectionbind methods...

How does bind() interact with outstanding operations which
are implicitly abandoned by the bind request?  In particular,
with listeners for outstanding operations?

How does bind() behave when a referral is returned?  In
particular, if the referral is successfully chased, what
is the authentication state of the connection?

How does an application cancel an in-progress SASL multiple-step
bind operation?  Maybe an empty (not null) mechanism could be
used for this.

During an in-progress SASL multiple-step bind operation, what
happens with one attempt to issue other operations upon the
same session (via a clone of the connection)?

The SASL bind() methods appears to negotiate mechanisms between
those requested by the application and those advertised by the
server.  If so, is there a way to disable this negotiation and
explicitly mandate the use of a particular mechanism?

I am also concerned by this statement:
   If mechanisms is null, or if the first version of the method
   is called, the LDAP server will be interrogated for its
   supportedSaslMechanisms attribute of its root DSE. 

This implies supportedSaslMechanisms is not checked after:
	1) reconnection
	2) StartTLS()
	3) establishment of SASL provided security services

Also,
>   Parameters are: 
>    
>      dn              If non-null and non-empty, specifies that the 
>                      connection and all operations through it should 
>                      be authenticated with dn as the distinguished 
>                      name. 

This implies the provided DN is the authentication identity to
be associated with the connection.  Generally, the authentication
identity to be associated with the connection is that provided in
the credentials associated with the SASL mechanism.

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Wed, 04 Apr 2001 09:54:10 -0700

At 08:44 AM 4/4/01 -0700, Rob Weltman wrote:
>"Kurt D. Zeilenga" wrote:
>> Also,
>> >   Parameters are:
>> >
>  If the provided DN is non-null and non-empty, then it is the credential that will be provided to the SASL mechanism(s).

IMO, that's inappropriate for a number of reasons.  First, it
disallows the client from specifying a different bind name
from a SASL authentication identity (which may be useful in
some environments).  Second, it assumes that the mechanism
used supports an identity in the form of an LDAP DN.  I note
also that mechanisms such as DIGEST-MD5 are designed to work
with arbitrary UTF-8 user names and as such two strings which
might represent equivalent LDAP DNs are not generally treated
as equivalent user names.

>If the SASL negotiation is successful, it will be the authentication identity.
>
>  If the provided DN is null or is empty, the SASL mechanism will (unless it is the external or the anonymous mechanism) use a callback to obtain a credential from the application if a callback is available.

The SASL callback should be used regardless of whether the provided
DN is null or empty.  The provided bind DN should ONLY be used as the
bind name.

---

From: Rob Weltman <[email-masked]>
Date: Wed, 04 Apr 2001 10:53:26 -0700

> DN is null or empty.  The provided bind DN should ONLY be used as the

  That is all up to the mechanism implementation. Neither the Java LDAP API implementation nor an application can force a mechanism (which is protocol-independent and most likely from a different supplier than either the LDAP API implementation or the application) to call back to an application. If it decides to call back, it will. If it decides to use the bind DN as sole credential identity, it will do so. If it decides it needs additional credentials, it will request them through a callback. The Java LDAP API neither can nor should define or restrict how a SASL mechanism uses credentials during authentication.

Rob

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Wed, 04 Apr 2001 11:21:50 -0700

At 10:53 AM 4/4/01 -0700, Rob Weltman wrote:
>  That is all up to the mechanism implementation.  Neither the Java LDAP API implementation nor an application can force a mechanism (which is protocol-independent and most likely from a different supplier than either the LDAP API implementation or the application) to call back to an application.
>If it decides to call back, it will. If it decides to use the bind DN as sole credential identity, it will do so.

Only because the API told it that the bind name was the SASL
authentication identity.  The bind name is NOT the SASL
authentication identity.  It's whatever the user provides
(upon callback or other means) as the SASL authentication
identity.

>If it decides it needs additional credentials, it will request them through a callback. The Java LDAP API neither can nor should define or restrict how a SASL mechanism uses credentials during authentication.

The Java LDAP API should not be providing the bind name as a
SASL authentication identity.  It should leave the specification
of the SASL authentication identity to the application through
interaction with SASL API.  The LDAP API is just fouling the
works by assuming that bind name is or could be the SASL
authentication identity. 

Assuming use of SASL/DIGEST-MD5, how would an application
specify the use of a bind name which is different from
the DIGEST-MD5 authentication identity in a reliable manner?

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Wed, 04 Apr 2001 12:02:12 -0700

At 08:44 AM 4/4/01 -0700, Rob Weltman wrote:
>  Nothing. When a clone begins a bind operation, it is dissociated from its siblings.

That seems counter to section 4.6.6.  >>>emphasis added<<<
   The clone can freely modify options and search constraints, and issue 
   requests, without affecting the source object or other clones. If the 
   clone disconnects or reconnects, it is completely dissociated from 
   the source object and other clones. >>>Reauthenticating in a clone, 
   however, is a global operation which will affect the source object 
   and all associated clones, because it applies to the single shared 
   physical connection. Any request by an associated object after one 
   has reauthenticated will carry the new identity.<<<

>  The fact that in LDAP the supported mechanisms are published outside of an authentication session can and should be used by a Java LDAP API implementation to conserve bandwidth (i.e. not attempt to authenticate with a mechanism not supported by the server) but it doesn't affect the ultimate selection of mechanisms because that is defined by the site configuration of the client and that of the server. The proposed Java LDAP API still allows a client to limit the acceptable mechanisms to a subset of the site-configured ones.

There are still cases, such as the existence of some
a priori agreement or belief a man-in-the-middle has
deleted a particular server supported mechanism, were
the client wants to mandate a specific mechanism which
is not listed by the server.  There is also the more
common case where the client just wishes to avoid an
unnecessary (to a particular application) discovery
exchange.

Kurt

---

From: Rob Weltman <[email-masked]>
Date: Wed, 04 Apr 2001 13:40:09 -0700

> the DIGEST-MD5 authentication identity in a reliable manner?

  It might help to show the layers of the SASL implementation:

   -------------------------
   | Application or server |
   -------------------------
   -------------------------
   | Protocol driver       |
   -------------------------
   -------------------------
   | SASL middleware       |
   -------------------------
   ------------------  ------------------  ------------------
   | SASL mechanism |  | SASL mechanism |  | SASL mechanism |
   ------------------  ------------------  ------------------

  For a Java application using LDAP, the Java LDAP API implementation is the protocol driver. It shares the SASL middleware layer with other protocol drivers (e.g. imap). It would be wrong for a protocol driver to dictate a certain behavior to the middleware layer, or to a mechanism. For example, it would be wrong to require that for LDAP "The SASL callback should be used regardless of whether the provided DN is null or empty.". There are mechanisms that don't want credentials at all (ANONYMOUS and the anonymous of EXTERNAL) and mechanisms that only know how to deal with a single identity. The Java LDAP API can not and should not impose specific semantics (SASL/DIGEST-MD5 with a user name different from the bind DN) on the middleware layer or on the SASL mechanisms. The semantics of a specific mechanism are implemented by the mechanism.

  Also, there are LDAP servers that only understand DNs and not usernames or other types of identity (as far as I know it does not conflict with RFC 2251 or other relevant documents for an LDAP server to only accept DNs for authentication, directly or through certificate mapping). A requirement that the bind DN not be the SASL authentication identity would not be reasonable for those servers.

Rob

---

From: Rob Weltman <[email-masked]>
Date: Wed, 04 Apr 2001 13:56:51 -0700

>    has reauthenticated will carry the new identity.<<<

  True, as I wrote a little earlier today. Since clones continue to share the connection during and after binding, they are subject to the same requirements and behavior as a thread sharing the connection that is doing the bind:

   "Clients MUST NOT invoke operations
   between two Bind requests made as part of a multi-stage bind."

  Invoking an operation while bind is in progress will therefor result in an LDAPException being thrown, just as for a thread invoking an operation on the binding connection.

>         3) establishment of SASL provided security services

  How does reading the supported mechanisms of the server help in the cases you describe? If there is an a priori agreement on what mechanism(s) to use, or the client (I assume you mean the application) wants to mandate a specific mechanism, or to avoid a discovery exchange, why would the client even bother to read the supported mechanisms of the server?

Rob

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Wed, 04 Apr 2001 14:10:59 -0700

At 01:40 PM 4/4/01 -0700, Rob Weltman wrote:
>  For a Java application using LDAP, the Java LDAP API implementation is the protocol driver. It shares the SASL middleware layer with other protocol drivers (e.g. imap). It would be wrong for a protocol driver to dictate a certain behavior to the middleware layer

YES!  By passing the LDAP bind name to the middleware layer, the
LDAP API dictating behavior which should be left to the application.
That is, the application should be the one dictating what the value
of the bind name is and what the SASL authentication identity
is.  The LDAP API should not assume that the application wants them
to be the same.

>, or to a mechanism. For example, it would be wrong to require that for LDAP "The SASL callback should be used regardless of whether the provided DN is null or empty.".

My point here is its the application which should drive what is
sent as the bind name and what is used as the SASL authentication
identity.  There are cases where they can and should be different.

>There are mechanisms that don't want credentials at all (ANONYMOUS and the anonymous of EXTERNAL) and mechanisms that only know how to deal with a single identity. The Java LDAP API can not and should not impose specific semantics

It is impose the semantics that the bind name cannot be different
from the user name by providing this value to the SASL middleware
layer.  The LDAP API should leave this to the application.

>(SASL/DIGEST-MD5 with a user name different from the bind DN) on the middleware layer or on the SASL mechanisms. The semantics of a specific mechanism are implemented by the mechanism.

>  Also, there are LDAP servers that only understand DNs and not usernames or other types of identity (as far as I know it does not conflict with RFC 2251 or other relevant documents for an LDAP server to only accept DNs for authentication, directly or through certificate mapping).

And the Application is free to provide a DN as the SASL authentication
identity.  But there are also LDAP implementations which don't understand
DNs as the authentication identity and make use of the bind name,
a DN, for other (non-authentication) purposes.  This is also not in
conflict with RFC 2251/RFC2829.

>A requirement that the bind DN not be the SASL authentication identity would not be reasonable for those servers.

That's not the requirement I'm after.  I'm after the requirement:
        The DN provided with a bind() call is sent to the server
        as the bind name.  It is not provided to the SASL layer
        as the authentication identity nor as the authorization
        identity.  The application may provide an authentication
        identity and/or authorization identity or other information
        appropriate used by the SASL mechanism to the SASL layer
        using the facilities of the SASL API.

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Wed, 04 Apr 2001 14:14:47 -0700

At 01:56 PM 4/4/01 -0700, Rob Weltman wrote:
>  How does reading the supported mechanisms of the server help in the cases you describe?

The case I raised is an independent issue.  That is,
the desire for an application to bypass discovery is
independent from ensuring the API properly does
rediscovery (when not bypassed).

---

From: Rob Weltman <[email-masked]>
Date: Wed, 04 Apr 2001 14:43:37 -0700

>         using the facilities of the SASL API.

  The point is that you cannot require that, because you cannot mandate that a SASL mechanism will use the callback facility (which is all it has at its disposal) to ask the application for an authentication identity. It is up to the SASL mechanism. A DIGEST/MD5 mechanism will ignore the DN provided in the bind() call, send an empty credentials field to the server, and obtain credentials from the user with a callback. It will then use them to create a "digest-response" to send to the server. Other mechanisms will send the DN in the initial SASL bind request. They may or may not request additional credentials from the application. Again, it is up to the mechanism, not the Java LDAP API, to decide what credentials to use, how to use them, and when to obtain them.

Rob

---

From: Rob Weltman <[email-masked]>
Date: Wed, 04 Apr 2001 15:15:23 -0700

"Kurt D. Zeilenga" wrote:
> 
> At 02:43 PM 4/4/01 -0700, Rob Weltman wrote:
> My point is that it *should* be up to the application to specify
> the value it wants to send as the bind name and the value it
> wants to use as the authentication identity.  If the application
> choose them to be the same or different, that's it's choice.
> The job of the LDAP API is to provide a means for the application
> to provide the value for specific uses, but not to make any
> assumptions that a value provided in one use (a bind name) can
> or should be used in another use (a SASL authentication identity).
> 
> If the application wants to do a DIGEST-MD5 authentication with
> an bind name of "cn=john" and a SASL authentication identity of
> "mary", the LDAP API should provide facilities to accomplish.
> If this is not possible with the current LDAP API then the API
> is flawed.

  That is supported. It is also supported for a mechanism to not request a separate SASL identity but to either use the bind DN for that or to not use any identity (for ANONYMOUS or SASL). If you broaden the examination to mechanisms other than DIGEST-MD5 I think you will see that it is up to the mechanism, not the application, to decide what credentials are required and how and when to send them to the server.

Rob

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Wed, 04 Apr 2001 15:40:59 -0700

At 03:15 PM 4/4/01 -0700, Rob Weltman wrote:
>  That is supported.

It's not obvious to me how to do it.  An example would
do wonders.

        Kurt

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Wed, 04 Apr 2001 15:02:32 -0700

Kurt

---

From: Rob Weltman <[email-masked]>
Date: Wed, 04 Apr 2001 16:11:33 -0700

> It's not obvious to me how to do it.  An example would

  class MarysCallbackHandler implements CallbackHandler {
      public void handle(Callback[] callbacks)
          throws IOException, UnsupportedCallbackException {
          for (int i = 0; i < callbacks.length; i++) {
             if (callbacks[i] instanceof NameCallback) {
                 NameCallback nc = (NameCallback)callbacks[i];
                 nc.setName( "mary" );
             } else if (callbacks[i] instanceof PasswordCallback) {
                 ...
             }
          }
      }
  }
...
...
   
  ldc.bind( "cn=john",
            new String[] {"DIGEST-MD5"},
            null,
            new MarysCallbackHandler() );

  For how to use callback handlers and callbacks, see http://java.sun.com/security/jaas/doc/api.html#CallbackHandler.

Rob

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Wed, 04 Apr 2001 16:29:08 -0700

>            new MarysCallbackHandler() );

Okay... so the confusion I had must have been this language:

Shouldn't this just be:

        dn              The distinguished name to use as the bind name.

as clearly in your example it's the callback which is providing
the authentication identity.

---

From: Rob Weltman <[email-masked]>
Date: Wed, 04 Apr 2001 16:40:23 -0700

> the authentication identity.

  Your formulation is fine with me, if it is more clear than what is in the draft.

Rob

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Wed, 04 Apr 2001 16:53:58 -0700

>  Your formulation is fine with me, if it is more clear than what is in the draft.

My only concern would be to ensure that the API is not doing
else with this name, such as providing it to the SASL layer
as either an authentication or authorization identity, which
would cause the example code you provided not to behave as
intended.

Hence, I would suggest:

        dn              The distinguished name to use as the bind name.
                        This value is not used as either a SASL
                        authentication nor authorization identity.
                        The application provides these identities
                        via other facilities.

Detailing these facilities, of course, would be quite appropriate.

---

From: Rob Weltman <[email-masked]>
Date: Wed, 04 Apr 2001 08:44:35 -0700

> with listeners for outstanding operations?

  As per RFC 2251 (to "simplify server implementation"), outstanding operations on the connection are abandoned. LDAPListener.getMessageIDs() returns a null-length array and LDAPListener.getResponse() throws an LDAPException.

> is the authentication state of the connection?

  If the API implementation successfully chases the referral and the bind completes successfully, the state of the connection is authenticated. This may or may not make sense in a particular environment. In some cases it may be a sign of an incorrectly configured server. In others there may be a pass-through authentication mechanism in place (such as that of the iPlanet Directory Server).

> bind operation?  Maybe an empty (not null) mechanism could be

  That is what is suggested by RFC 2251 (issue a new SASL bind request with an empty mechanism name).

> explicitly mandate the use of a particular mechanism?

  See below.

>         3) establishment of SASL provided security services

  Short summary of SASL mechanism negotiation: successful completion of SASL authentication requires that the client and the server support at least one mechanism in common. If the server supports mechanisms a - d and the client supports mechanisms c - f, they can negotiate authentication using mechanisms c or d.

  The way a client or server indicates which mechanisms it supports is different for different protocols. LDAP is somewhat unique in that the server publishes a list of supported mechanisms outside of any authentication process. With IMAP, for example, the client just proposes a mechanism and the server either accepts it or rejects it, forcing the client to try various mechanisms until it finds one that the server accepts. [ftp://ftp.isi.edu/in-notes/rfc2222.txt].

  The first version of my I-D on a Java SASL binding followed the low-level RFC 2222 sequencing closely. An application would have to try each mechanism it was capable of until it found one that the server accepted. But after discussions with John Myers (author of SASL) and with a couple of the implementors of the Cygnus SASL project at CMU, I modified the I-D to put the responsibility on the middleware (i.e. the API) implementation and on the site administrators instead. As currently envisioned, a site administrator will typically configure the mechanism factories that she will allow applications to use at her site. That configuration may limit the number of mechanisms that are available to a server or client at the site and also establish a priority order among them. An application doesn't need to know anything about them. The Java SASL API implementation is responsible for attempting to use only the site-configured mechanisms and to attempt each one in the site-configured!
 order. An application can find out afterwards which mechanism was ultimately negotiated, but it cannot (at least not directly) find out which mechanisms were discussed during the negotiations. That is also the approach of the C SASL binding developed at the Cygnus project (at least as it was presented to me by a couple of its developers).

> the credentials associated with the SASL mechanism.

  If the provided DN is non-null and non-empty, then it is the credential that will be provided to the SASL mechanism(s). If the SASL negotiation is successful, it will be the authentication identity.

Rob