[Date Prev][Date Next] [Chronological] [Thread] [Top]

[no subject]



ESMTP id e8P68sj13059
        for <ietf-ldapext@openldap.org>; Mon, 25 Sep 2000 06:08:54 GMT
Received: from aka.mcom.com (aka.mcom.com [205.217.237.180])
        by netscape.com (8.10.0/8.10.0) with ESMTP id e8P614M16682;
        Sun, 24 Sep 2000 23:01:04 -0700 (PDT)
Received: (from list@localhost)
        by aka.mcom.com (8.10.0/8.10.0) id e8P67VQ20714;
        Sun, 24 Sep 2000 23:07:31 -0700 (PDT)
Resent-Date: Sun, 24 Sep 2000 23:07:31 -0700 (PDT)
Message-ID: <39CEEC62.F793684C@worldspot.com>
Date: Sun, 24 Sep 2000 23:10:43 -0700
From: Rob Weltman <robw@worldspot.com>
X-Mailer: Mozilla 4.73 [en] (WinNT; U)
X-Accept-Language: en-US,sv,ja
MIME-Version: 1.0
To: Steve Sonntag <VTAG@novell.com>, Steven Merrill <SMERRILL@novell.com>
CC: ietf-ldapext@netscape.com, aclark@novell.com,
   Miodrag Kekic <miodrag@netscape.com>
Subject: Re: Java LDAP API issues
References: <39C59B3F.A94F2396@worldspot.com>
Content-Type: multipart/alternative;
 boundary="------------480A17C14EE6A0A3B94F7B2C"
Resent-Message-ID: <"rCwXD.A.YDF.iuuz5"@glacier>
Resent-From: ietf-ldapext@netscape.com
X-Mailing-List: <ietf-ldapext@netscape.com> 
X-Loop: ietf-ldapext@netscape.com
Precedence: list
Resent-Sender: ietf-ldapext-request@netscape.com


--------------480A17C14EE6A0A3B94F7B2C
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

  I've collected all the issues raised (hope I didn't miss any) and responded
in short to each one. Many thanks to Miodrag for helping me evaluate the
issues. And to Steve and Steven for raising them :-)

Rob


1.
> Section 4.39.13 LDAPV2.setOption
>
>  This method of the LDAPV2 interface seems a little strange.
>
>   1) It probably does not belong under the interface LDAPV2,
>      but instead under LDAPConnection. This would allow it
>      to support setting client & server controls which it
>      cannot do under LDAPV2.  This functionality is currently
>      missing in the method.
>
>      Setting STRING_FORMAT is also an LDAPV3 setting, as UTF-8
>      is only meaningful under LDAPV3.

  OK, but see 4 below (which renders this issue mute)


>   2) STRING_FORMAT is set only by the setOption method.
>      There should be a way to set or get STRING_FORMAT with
>      LDAPSearchConstraints methods.

  OK, but see 4 below (which renders this issue mute)


>   3) setOption operates only on the LDAPSearchConstraints object
>      that is associated with an LDAPConnection object.  Yet
>      there may also be an LDAPConstraints object associated
>      with the LDAPConnection object.  It may or may not be
>      the same as the LDAPSearchConstraints object.  Should
>      there be a setOption kind of method that operates on
>      the LDAPConstraints object associated with a connection?

  LDAPSearchConstraints extends LDAPConstraints. There is only one such object
per connection, and it is an LDAPSearchConstraints. If there was an
LDAPConstraints object as well, there would be ambiguity as to which object
controlled operations other than search.   Also, see 4 below (which renders
this issue mute)


>   4) All functionality of SetOption can be performed by code
>      that references the LDAPSearchConstraints object of a
>      connection - i.e. LDAPConnection.getSearchConstraints.method().
>

  Yes, let's eliminate it.


2.
> If references to LDAPv2 are not removed from the draft,
> then the methods that were previously in LDAPAsynchronous
> Connection which are now in LDAPConnection - these methods
> should also be in one of the LDAPV2 or LDAPV3 interfaces
> to identify where they can be used.

  Let's eliminate the references to LDAPv2; the API will assume LDAPv3.


3.
>
>  In the java-api-11 I-D, an application doing asynchronous search
>  operations is confronted with two different data formats when handling
>  referrals and search continuation references.
>
>  When the application gets a referral status on a search operation,
>  referral URL information is retrieved by LDAPResponse.getReferrals()
>  as an array of String objects.
>
>  When the application gets search continuation references as part of
>  the search data, the continuation references are retrieved by
>  LDAPSearchResultReference.getURLs() as an array of LDAPUrl objects.
>
>  To be consistent, shouldn't both return an array of LDAPUrl objects?

Returning String[] seems more flexible. Steve has recognized that in one of
his comments following this one. "...This is because the only way to get the
list is via the getURLs() method of the LDAPSearchResultReference.Perhaps it
should return the  URLs as a string array, and let the applicationturn them
into LDAPUrl objects if desired.  This is backwards to what I said in an
earlier e-mail, butnow I see the need for Strings instead of LDAPUrls".

So let's return String[] in both cases.


4.
> An application doing its own referral handling may need to make
>  decisions based on the scheme of URLs returned from search
>  continuation references or referrals.
>
>  Shouldn't the LDAPUrl object provide a method to retrieve
>  the URL scheme, viz. ldap, http, & etc.

This is an LDAP only URL and not a generic URL, so there is no reason to
report a URL scheme. However, there is a need to support ldaps with some LDAP
servers. To accomodate them, we propose a boolean method isSecure().


5.
> I am puzzled why the draft specifies that automatic referral
>  following is done only for synchronous operations.  While
>  it is simple for an application using async to merge results from
>  multiple listeners or to specify the same listener for multiple
>  requests, it is not so simple to determine when a request
>  and all its child referral requests are complete.  Why put
>  this burden on the application?
>
>  IMO there is no technical reason that automatic referral
>  following mechanisms cannot be used across the board,
>  for both synchronous and asynchronous operations.
>
>  Could you fill me in on the reason for the current design.

When originally implementing the asynchronous interfaces, we looked at this
option, but we concluded that implementation would be difficult, and the
asynchronous interfaces are intended to allow the client to interact with the
protocol at a low level anyway, so it was not unreasonable for the client to
manage the interactions. SASL authentication is another feature which is not
handled automatically by the API for the asynchronous interfaces, for the same
reason.


6.
> Re: referrals as defined in draft-ietf-ldapext-ldap-java-api-11.txt
>
>  The I-D seems silent on what happens if an application has automatic
>  referral handling enabled, and for some reason one or more of the
>  referrals or search continuation references cannot be followed.
>
>  This could happen for at least three reasons:
>  1- The bind fails when explicitly binding using the LDAPBind object
>  2- The bind fails when implicitly binding using anonymous credentials,
>       or when using the LDAPRebind object to obtain credentials
>  3- None of the servers in the referrals list have the scheme ldap://
>     specified and thus are ignored (per the draft) (4.7.10)
>
>  I assume that if automatic referral following succeeds, the
>  application doesn't see any referral URLs, i.e. no LDAPReferralException
>  is thrown when doing LDAPSearchResults.next(), (4.35.4) and
>  LDAPSearchResults.nextElement() (4.35.5) does not return an
>  LDAPReferralException object.
>
>  The draft indicates that LDAPReferralException is only thrown
>  if automatic referral handling has not been enabled.  It doesn't
>  indicate whether the LDAPReferralException object is returned
>  on LDAPSearchResults.getElement(), I assume it is not returned. (4.26)
>
>  So what happens if a referral cannot automatically be followed.
>  I think the application needs to be notified of this error, and the
>  logical way to do that is to return the referral information to
>  the application.
>
>  IMO, LDAPReferralException should be returned / thrown on
>  synchronous operations any time a referral is not followed, not just
>  if automatic referral following is disabled.
>
>  Thus, LDAPReferralException would always be returned / thrown
>  if automatic referal following is not enabled.  If enabled,
>  LDAPReferralException would be thrown / returned when none of
>  the servers in a referral response list can be used to follow the referral
>  and would be treated by the application as an error situation.
>
>  Changing the draft to reflect this will  clear up these issues.

A good point, however there should be more info in the exception, so that the
application can clearly differentiate between a referral not being followed
and errors during automatic referral following. The actual LDAPException that
caused the referral following to fail (cannot connect, auth failed, no such
object) could be stored in the LDAPReferralException. The app can then simply
check

catch (LDAPReferralException ex) {
    if (ex.getReferralFailureException() == null) {
        // I am supposed to follow referrals
        LDAPUrls[] = ex.getURLs();
        ...
    } else {
        // The SDK could not follow the referral
        System.err.println("Failed to follow referral " + getUrls()[0] + " " +
            ex.getReferralFailureException());
    }


7.
>
>  I would like clarification on how LDAPBind vs LDAPRebind objects
>  are used in the Java API.
>
>  The I-D implies, but never quite says that the two objects don't
>  normally exist in the LDAPConstraints object at the same time.
>  (Implied by Appendix G - LDAPConstraints - they should
>  not be specified on the same constructor)
>
>  They certainly can both be set by using the set methods, but
>  are probably not both used at the same time.
>
>  I surmise from the draft that these objects are used as follows:
>
>  1. Neither object is used unless Referrals are enabled in the
>      LDAPConstraint object (automatic referral following enabled).
>
>  2. An LDAPRebind object is used only if present and if an LDAPBind
>      object is not present in the LDAPConstraint object.
>
>  3. An LDAPBind object is used if present.  If present, the LDAPRebind
>      object is not needed by LDAPConnection as no implicit binding is done.
>      Explicit binding is the responsibility of the LDAPBind object. 
Therefore
>      the LDAPRebind object is not used in this case.
>
>  If my guesses are correct, maybe the draft should be clarified as to the
>  usage of these objects.

This is a correct interpretation. An improvement to the I-D would be be to
specify a single field in LDAPConstraints - rebindHandler - which would accept
either LDAPBind or LDAPRebind. An additional tag interface would need to be
declared, somthing like this:

public interface LDAPReferralHandler {  // the tag interface
}

public class LDAPConstraints {
     private LDAPReferralHandler rebindProc;
     ...
}

public interface LDAPBind extends LDAPReferralHandler {
...
}

public interface LDAPRebind extends LDAPReferralHandler {
...
}


8.
> Re: LDAPBind as defined in draft-ietf-ldapext-ldap-java-api-11.txt
>
>  It is unclear from the draft how the LDAPConnection object must be
>  used by an application implementing the LDAPBind interface.
>
>  I am guessing that the LDAPConnection object passed to the bind()
>  method of the LDAPBind implementation is a new LDAPConnection object
>  created by automatic referall following code in the original LDAPConnection
>  object. The object contains the  AuthenticationDN and
>  AuthenticationPassword from the LDAPConnection that the continuation
>  reference was received on. The Host and Port are filled in from the
>  referral/reference host & port. When passed to the bind() method,
>  neither connect nor bind has been performed on this LDAPConnection object.
>
>  In order to make this work, I believe the iimplementation of the
>  LDAPBind.bind() method MUST use the LDAPConnection object, which
>  was passed as a parameter, to perform its connect and bind calls.
>  It then returns success if both operations succeed.  The original
>  LDAPConnection object referral handling code can then use the
>  new LDAPConnection object when it resends the search request,
>  updated with the new search base and possibly search filter.
>
>  The above should be clarified in the draft.

  OK


>  It seems that the LDAPRebind interface would be easier to implement if
>  additional data were provided in the new LDAPConnection object.  Such as:
>
>  1. A reference to the LDAPSocketFactory class from the original
LDAPConnection
>      object.  This allows it to connect in the same way as the original
connection.
>  2. An LDAPConstraints object containing a reference to the LDAPRebind
object
>      from the original LDAPConnection object.  The LDAPBind.bind() method
may
>      want to get authentication information using and LDAPRebindAuth object,
and
>      this gives it a way to do that.
>  3. The protocol version used in the connect/bind of the original object. 
This allows
>      The LDAPBind.bind function to bind with same protocol version used in
the
>      original connection.
>  4. The mechanism used when binding.  This could be the mechanism used on
the
>      bind in the original LDAPConnection object, or perhaps LDAPRebindAuth
could
>      be modified to provide the triplet - UserDN, Password, and Mechanism
for the
>      specified host.
>
>  IMO the above changes would give the application, using explicit bind,
greater flexibility
>  when dealing with referrals / continuation references during automatic
referral
>  following:
>

  It's questionable that this is necessary. Can't you do all that with
LDAPBind (rather than LDAPRebind)?

  If it really is required (which duplicates what you can do with LDAPBind),
how about the following instead (let the implementation pull whatever it needs
from the original connection, as LDAPBind does)?

LDAPConnection bind(String ldapurl, LDAPConnection origConn);


9.  (from Kurt)
> You might consider renaming getSubTypes to getOptions as
> not all options (e.g. ;binary) are subtypes.

  Not worth changing, I don't think.


10.
> The I-D interchanges referrals and search continuation references.
>
>  A referral happens only on an operation and no other results are returned.
>
>  A search continuation reference happens only on a search and is mixed in
with
>  returned search entries.
>
>  The I-D refers to continuation references only in section 2.2 and 2.34.
>
>  It sometimes uses referrals where search continuation references should
>  be used, and generally where both apply.
>
>  Line 473 - referred to -> referred-to
>
>  The following should probably refer to both referrals and continuation
references
>  Section 1: line 459, 468
>  Section 2.2: LDAPRebind / LDAPBind
>  Section 2.3 - LDAPRebindAuth
>  Section 2.4 - LDAPReferralException
>  Section 4.4 - LDAPBind
>  Section 4.7.x - doReferrals / binder /reauth / hop_limit
>  Section 4.7.x - RebindProc, BindProc, Referrals
>      as well as the methods to get and set the above
>  Section 4.24 - LDAPRebindAuth
>  Section 4.25 - LDAPRebind
>  Section 4.26 - LDAPReferralException
>  Section 4.27 - LDAPResponse
>
>  The following refer to search references
>
>  Section 4.31.1 - LDAPSearchConstraints - doReferrals, reauth binder,
hop_limit params
>  Section 4.35.4 - LDAPSearchResults.next()
>  Section 4.35.5 - LDAPSearchResults.nextElement()
>  Section 4.39.13 - SetOption ( search options relating to referrals)
>

Yes. The API makes the distinction transparent to the user of the API. The I-D
could state that more explicitly.


11.
> Resend - properly indicating where comments are
>
> Steve Sonntag wrote:
>
> >  Re: LDAPBind as defined in draft-ietf-ldapext-ldap-java-api-11.txt It
> > is unclear from the draft how the LDAPConnection object must beused by
> > an application implementing the LDAPBind interface. I am guessing that
> > the LDAPConnection object passed to the bind()method of the LDAPBind
> > implementation is a new LDAPConnection objectcreated by automatic
> > referall following code in the original LDAPConnectionobject. The
> > object contains the  AuthenticationDN andAuthenticationPassword from
> > the LDAPConnection that the continuationreference was received on. The
> > Host and Port are filled in from thereferral/reference host & port.
> > When passed to the bind() method,neither connect nor bind has been
> > performed on this LDAPConnection object. In order to make this work, I
> > believe the iimplementation of theLDAPBind.bind() method MUST use the
> > LDAPConnection object, whichwas passed as a parameter, to perform its
> > connect and bind calls.It then returns success if both operations
> > succeed.  The originalLDAPConnection object referral handling code can
> > then use thenew LDAPConnection object when it resends the search
> > request,updated with the new search base and possibly search filter.
>
> It is also necessary that the application implementing the
> LDAPBind.bind()
> method use a synchronous bind do bind to the referred-to-server, or
> if using an asyncronous bind, it must wait until the bind operation has
> completed before returning status.

This is the same as #8.


12.
> Re: Referrals on operations as defined
>        in draft-ietf-ldapext-ldap-java-api-11.txt
>
>  When a referral occurs on an asynchronous operation
>     the referral is returned as an LDAPResponse object.
>     The referral info is obtained using the getReferrals() method.
>
>  When a referral occurs on a synchronous operation
>      An LDAPException is thrown.  The exception object is
>      specialized as an LDAPReferralException object and
>      the referral info can be obtained via the getURLs() method
>      with appropriate casting on the object.
>
>  Is this correct?
>
>  Should the doc be clarified?

Yes this is correct. For asynch interfaces exceptions are raised only for
connection errors. LDAP result messages are converted into LDAPResponse
objects which are to be checked by the app for errors and referrals. Again,
asynch interfaces operate at a low level, close to the protocol.


13.
>
>  Section 4.40.3: - LDAPv3.extendedOperation
>     Shouldn't this method have a method that
>     includes LDAPConstraints as an argument.
>    The protocol allows extended operations to
>    support controls.

OK.


>  Section 4.40.2 - LDAPV3.connect
>    This special version of connect is really
>    a connect and a bind combinded.  Should
>    this also have a method with an LDAPConstraints
>    object? - or if the application needs that
>    should they just do the two separate operations
>    and put the LDAPConstraints on the bind?

Let's remove the method from the I-D. It's just a convenience.


14.
>
>  I think the draft should describe more fully the
>  semantics of the implicit bind w/r automatic referral following:
>
>  I will describe what the I-D describes and where
>  I have questions:
>
>  1. Authentication - uses anonomyous credentials unless
>     LDAPRebind specified in LDAPConstraints.

Yes


>  2. Protocol Version ?? - Does it use the same protocol
>      version as the LDAPConnection receiving the referral or is it
>      always V2??  I vote for the having it the same as the originating
>      connection.

Yes.


>  3. AuthenticationMethod: Is it the same as the originating connection,
>      or is it "simple" - I assume simple is used.

Yes. LDAPBind must be used if SASL is desired for the referral connection.


>  4. Does it use the LDAPSocketFactory if specified on the
>      originating connection.  I am not sure what to do here.
>      It seems better to use it if available, then an encrypted
>      connection can be established and thus prevent
>      clear text password transmittion on the wire.  I just
>      talked myself into it - it should be used.

If the referral ldap url specifies ldaps, the referral connection should use
ldaps (regardless of the original connection). At least in our implementation
:-) - since ldaps is being deprecated in favor of startTLS, we may not want to
mention it in this I-D (I just remembered that I owe LDAPEXT an informational
RFC draft on ldaps). For startTLS, I guess the referral connection should
attempt to use startTLS if the original connection was in startTLS mode. Is
there any other way to determine whether or not to use startTLS?


15.
>  When performing a search it is possible for the server
>  to return multiple search continuation references, each
>  with a different search base.
>
>  The I-D states that when retrieving results from a
>  search using LDAPSearchResults.next() that all the
>  results are returned to the application after which
>  on the last call to next() an LDAPReferralException
>  is thrown.
>
>  My question is: how does the application get the
>  rest of the continuation references, as a
>  ReferralException object encapsulates the
>  reference list from one search continuation reply.
>
>  If the application did another next() call would
>  another LDAPReferralException be thrown?
>  How would the application know when to stop?
>  Does it check the enumeration count to see if
>  more items exist in the enumeration, and thus
>  continue to call next() and get an LDAPReferralException
>  each time.  As an alternative, the application
>  could switch to calling nextElement() to get the
>  rest of the search references as LDAPReferralException
>  objects.  How do you envision the application doing this?
>
>  The I-D should make it clear that the application
>  can get more than one search continuation
>  reference, and indicate a mechanism to deal
>  with the situation.
>

The app should continue as long as hasMoreElements() returns true. Calling
nextElement() is not a good idea. The following example from the Mozilla
implemenation javadocs demonstrates proper handling. Note the "continue" after
the exception has been processed.

LDAPSearchResults res = ld.search( MY_SEARCHBASE,
                              LDAPConnection.SCOPE_BASE, MY_FILTER,
                              null, false );
      while ( res.hasMoreElements() ) {
        try {
          LDAPEntry findEntry = res.next();
        } catch ( LDAPReferralException e ) {
          LDAPUrl refUrls[] = e.getURLs();
          for ( int i = 0; i < refUrls.length; i++ ) {
          // Your code for handling referrals
          }
          continue;
        } catch ( LDAPException e ) {
          // Your code for handling errors on limits exceeded
          continue;
        }
        ...
      }


16.
>
>  Since LDAPResponseListener and LDAPSearchListener
>  objects implement exactly the same set of methods,
>  does it seem reasonable that an interface be created
>  named something like LDAPListener that specifies
>  those four methods, and that LDAPSearchListener
>  and LDAPResponseListener implement this interface.
>  This forces those methods to stay the same in both classes.
>

> If an LDAPListener interface were created, then
> the two methods in LDAPv2.abandon
>
>    public void abandon(LDAPSearchListener listener)
>    public void abandon(LDAPResponseListener listener)
>
> Could be combined into one
>
>    public void abandon(LDAPListener listener)

We have responded to this earlier, but here is a brief recap. In the very
first asynch draft, LDAPSearchListener extended LDAPResponseListener. Later
when we adding abandon(int) method, we investigated removing
LDAPSearchListener and leaving only LDAPResponseListener because there were
implementation issues (multiplexing, and raising exceptions as a result of a
lost connection). Then, in order not to change the draft considerably, we
decided to make only minor changes and just resolve the implementation
problems. We kept LDAPSearchListener, but it does not extend
LDAPResponseListener any more.


17.
>
>  4.6.19 setConstraints
>
>  Sets the constraints that apply to all operations performed
>  through this connection
>
>  Wouldn't it be more clear to state:
>
>  Sets the constraints that apply to all non search operations
>  performed through this connection.
>  - - - - - - - - - - - - - - - - - - - -

The constraints (hop limit, bind handler, referrals, timeout, controls) apply
to all operations (including search operations).


>  4.39.13 setOption
>
>  Seems to set only the search constraints options, but
>  the first paragraph has a confusing sentence that
>  talks about LDAPConstraints.
>
>  Was it your intention that the LDAPConstraints be
>  the same object as LDAPSearchConstraints or
>  that they be different objects?
>
>     "These options represent the default search constraints for the
>     current connection. Some of these options are also propagated through
>     the LDAPConstraints, which can be obtained from the connection object
>     with the getSearchConstraints method."
>  The above two sections 4.39.13 & 4.6.19 could be
>  construed to indicate that the LDAPConstraints and the
>  LDAPSearchConstraints objects for a connection are
>  in fact the the same object, however, that fact that
>  each has a separate set & get method seems to indicate
>  they are different objects.
>
>  Could you please clarify this?
>

Yes this is intentional. Originally we had only LDAPSearchConstraints but it
did not make a lot of sense to use  "search" constraints for non-search
operations. We separated the interfaces such that LDAPSearchConstraints
extends LDAPConstraints and all properties set on LDAPConstraints are also
visible in LDAPSearchConstraints.

But see 1.4 above.


18.
>
>  4.39.1 LDAPv2.abandon
>
>  The RFC 2251 and the C api draft allow controls to be specified
>  on an abandon operation.  In java it is allowed only using the default
>  constraints object or search constraints object.  Should methods
>  be defined that allow constraints to be specified on abandon?

Strictly speaking this is true, but if we look at the properties in
LDAPConstraints, none of them are applicable to abandon(). This change is not
required.


>  When calling abandon( int id), it is unclear whether LDAPConstraints
>  or LDAPSearchConstraints should be used for the default
>  constraints.

LDAPSearchConstraints is only for search.


19.

> The JAVA LDAP API (draft-ietf-ldapext-ldap-java-api-11.txt) defines the
following method for
> extended operations:
>
>
> "public LDAPExtendedOperation extendedOperation(LDAPExtendedOperation op)
throws
> LDAPException"
>
> I would think that you would return an LDAPExtendedResponse object rather
than an
> LDAPExtendedOperation object. I agree that one could reuse the
LDAPExtendedOperation object
> (as it has the same set of fields) but then why bother defining a
LDAPExtendedResponse object
> in the draft?
>

OK.


20.

>  Section 4.7.11 LDAPConstraints.setTimeLimit
>
>  LDAP Constraints applies to all operations, not just search operations.
>
>  The first sentence should probably be changed from:
>
>       Sets the maximum number of milliseconds to wait for any operation
>       under these search constraints.
>  To something like:
>
>       Sets the maximum number of milliseconds the client waits for any
operation
>       under these constraints.
>
>  Section 4.7.5 LDAPConstraints.getReferrals
>
>      Change nor to or
>
>      Specifies whether nor not ...
>
>  -Steve
>

OK.


21
LDAPSortKey.

> It is still listed in section 2.2
>
>  >>> Rob Weltman  01-Sep-00 2:59:45 PM >>>
>    Someone pointed out that LDAPSortKey is not used/referenced, so I removed
it from the draft.
>
>    In the Netscape implementation, it is used by LDAPSortControl. The
current API draft does not cover any particular controls.
>

OK


22.

> Re: LDAP_PARTIAL_RESULTS Result Code defined in
> section 4.16.6 of draft-ietf-ldapext-ldap-java-api-11.txt
>
> Section 4.16.6 instructs the reader to review RFC 2251 for
> a discussion of the meanings of the codes defined in that
> section.
>
> RFC 2251 does not discuss the meaning of the LDAP_PARTIAL_RESULTS
> result code. Should this be defined or referenced in this draft?
>
OK.


23.

> In the Bibliography, [3] refers to RFC 1960.
>
>  Shouldn't it refer to RFC 2254 instead?
>

OK.


24.


>  4.40.1
>
>  In the explaination of bind operations that use mechanisms should the first
>  Paragraph be changed from
>
>     Authenticates to the LDAP server (that the object is currently
>     connected to) using the specified name and of a specified set of
>     mechanisms. If none of the requested SASL mechanisms is available, an
>
>      Authenticates to the LDAP server (that the object is currently
>     connected to) using the specified name and ONE of a specified set of 
<----
>     mechanisms. If none of the requested SASL mechanisms is available, an
>

OK.


>  What does it mean -
>
>     if the first version of the method (i.e. the one that specifies no
mechanism)
>     is called, the LDAP server will be interrogated for its
>     supportedSaslMechanisms attribute of its root DSE.
>
>  What does it do after the LDAP server is interrogated?  Does it use one
>  of them, and if so how does the application know which one is used
>  and how does it know what kind of credentials to supply?
>

Yes, if no mechanisms are specified, the mechanisms supported by the server
are processed until one is mutually agreed on. The callback handler is called
to obtain credentials. Are you thinking that the credentials to be returned
depend on the mechanism being negotiated? Let me think about that a little...


25.

>  4.40.1 bind specifying a mechanism
>
>  It would seem that if the mechanism is "simple"
>  that the API should specify how the password
>  is to be specified in the Hashtable object props
>  so that it is consistent across implementations.
>  Other mechanisms and associated Hashtable
>  values are the subject of other I-Ds.
>
>
>  My suggestions:
>
>        props.put("password", new String("user-password-value");)
>

  Credentials are obtained from the callback handler.


26.


> Shouldn't the SASL bind mechanisms also support the ability
> for the application to specify an LDAPConstraints
> object so that call specific controls can be specified?
>

OK.


27.

> When using an explicit bind for referrals where sasl mechanisms
> were used on the original LDAPConnection, the LDAPBind.bind()
> method will need access to the Hashtable parameter passed on the
> bind to get the credentials used.  A method needs to be
> supplied in LDAPConnection to get the Hashtable object with
> semantics similar to what is now used for getAuthenticationPassword()
>

  Does it need to be a public method? Can't it be a package scope
(implementation-defined) method?


28.

> I am trying to understand the encode/decode functions
>  in the LDAPUrl class.
>
>  I assume that the encode method turns unsafe characters
>  (as defined by RFC1738, RFC 2255, & etc.) into characters
>  of the form %HH and that decode turns those characters
>  back into the raw unencoded characters.
>
>  Question 1: The reference to decoding "+" into " "
>  and encoding " " into "+" .  I could not find any reference
>  to the need for doing this in the RFCs.  Could someone
>  please tell me why someone might expect that this behavior?
>
  " " does not need to be encoded in LDAP URLs.


>  Question 2:  What kind of strings do the constructors of the
>  LDAPUrl class expect.  Do the constructors expect the
>  strings to be already encoded?
>

  Yes.


>  Question 3:  Does the encode method take into account the field
>  in the URL when doing the encoding (e.g. filters vs. base DN) which
>  may have different reserved characters and thus slightly different
>  encoding rules ? which boils down to the real question - does
>  the encode function expect a full correctly formatted URL
>  or can one hand it just the base-DN, or just the filter and
>  expect it to be correctly encoded?
>
>  i.e., does the LDAPUrl constructor with individual parts expect
>  encoded strings and will the encode function do it?
>

  LDAPUrl.encode() expects to receive a string to be encoded. For all
practical purposes, it should be a DN or a filter string (and not a full LDAP
URL). After encoding, the DN and filter can be passed to the LDAPUrl
constructor.


29.

> 4.16 LDAPException
>
>  The LDAPException class has a method getMatchedDN() but has no way to set
>  the matched DN in the object.  Shouldn't there be a constructor with
MatchedDN
>  as a parameter?
>
> Steve,
>
>  I wouldn't think so.  This is really meant to provide access to what a
SERVER responds with, and thus I wouldn't know why a CLIENT would want to
>  "setMatchedDN()".
>
>  Regards,
>  Tim Hahn
>
> I was thinking from the API perspective.  An implementation of the API would
need to
>  take the ber encoded packet and extract from it the matched DN, and then
>  generate the exception.  My point is that the API needs to be
>  able to set the matchedDN data in the exception.  Are you suggesting that
it
>  should use a package method?  The only problem with a package method
>  is that an extension written in a different package may also need to set
>  matchedDN when generating an exception, but wouldn't have any way
>  to set the value.
>

  Is that realistic - that a class in some other package would create an
exception and put in its own matchedDN?


30.

> 4.26 LDAPException
>
>  I am trying to understand where the information in the
>  constructor serverMessage comes from.  I am not
>  aware of any message that is returned by the server with a
>  referral result, except for the actual referral URLs.
>
>  Do you intend that the class gets primed with the
>  referral URLs using the serverMessage parameter
>  and if so how are the referrals delimited - otherwise
>  can you elaborate on the meaning of this parameter
>  and explain how the referral URLs are placed into the
>  class.
>

  That is correct. The server returns the referral URLs in the message field.
I don't know if it is necessary to define the representation there (it is a
contract between the upper layer of an implementation and the BER decoding
layer - which is not defined in the I-D); clients query getURLs() to get the
URLs.


31.

> In draft-ietf-ldapext-ldap-c-api-04.txt section 11.6 Searching, it states:
>
> filter       A character string as described in [13], representing the
>              search filter.  The value NULL can be passed to indicate
>              that the filter "(objectclass=*)" which matches all entries
>              is to be used.
>
> It might be helpful to note this behavior in sections 4.38.1 and 4.39.12 of
> draft-ietf-ldapext-ldap-java-api-11.txt. (Which would make those sections
> consistent with 4.38.8 of the same draft which states that (objectclass=*)
> is the default filter.)
>
  OK.


32.

> Also, in the Bibliograpy, [7] should be updated. (To
draft-ietf-ldapext-ldap-c-api-04.txt)
>
  OK.



--------------480A17C14EE6A0A3B94F7B2C
Content-Type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
  I've collected all the issues raised (hope I didn't miss any) and responded
in short to each one. Many thanks to Miodrag for helping me evaluate the
issues. And to Steve and Steven for raising them :-) 

Rob 
  

1. 
> Section 4.39.13 LDAPV2.setOption 
> 
>  This method of the LDAPV2 interface seems a little strange. 
> 
>   1) It probably does not belong under the interface LDAPV2, 
>      but instead under LDAPConnection. This would allow it 
>      to support setting client & server controls which it 
>      cannot do under LDAPV2.  This functionality is currently 
>      missing in the method. 
> 
>      Setting STRING_FORMAT is also an LDAPV3 setting, as UTF-8 
>      is only meaningful under LDAPV3. 

  OK, but see 4 below (which renders this issue mute) 
  

>   2) STRING_FORMAT is set only by the setOption method. 
>      There should be a way to set or get STRING_FORMAT with 
>      LDAPSearchConstraints methods. 

  OK, but see 4 below (which renders this issue mute) 
  

>   3) setOption operates only on the LDAPSearchConstraints object 
>      that is associated with an LDAPConnection object.  Yet 
>      there may also be an LDAPConstraints object associated 
>      with the LDAPConnection object.  It may or may not be 
>      the same as the LDAPSearchConstraints object.  Should 
>      there be a setOption kind of method that operates on 
>      the LDAPConstraints object associated with a connection? 

  LDAPSearchConstraints extends LDAPConstraints. There is only one such object
per connection, and it is an LDAPSearchConstraints. If there was an
LDAPConstraints object as well, there would be ambiguity as to which object
controlled operations other than search.   Also, see 4 below (which renders
this issue mute) 
  

>   4) All functionality of SetOption can be performed by code 
>      that references the LDAPSearchConstraints object of a 
>      connection - i.e. LDAPConnection.getSearchConstraints.method(). 
> 

  Yes, let's eliminate it. 
  

2. 
> If references to LDAPv2 are not removed from the draft, 
> then the methods that were previously in LDAPAsynchronous 
> Connection which are now in LDAPConnection - these methods 
> should also be in one of the LDAPV2 or LDAPV3 interfaces 
> to identify where they can be used. 

  Let's eliminate the references to LDAPv2; the API will assume LDAPv3. 
  

3. 
> 
>  In the java-api-11 I-D, an application doing asynchronous search 
>  operations is confronted with two different data formats when handling 
>  referrals and search continuation references. 
> 
>  When the application gets a referral status on a search operation, 
>  referral URL information is retrieved by LDAPResponse.getReferrals() 
>  as an array of String objects. 
> 
>  When the application gets search continuation references as part of 
>  the search data, the continuation references are retrieved by 
>  LDAPSearchResultReference.getURLs() as an array of LDAPUrl objects. 
> 
>  To be consistent, shouldn't both return an array of LDAPUrl objects? 

Returning String[] seems more flexible. Steve has recognized that in one of
his comments following this one. "...This is because the only way to get the
list is via the getURLs() method of the LDAPSearchResultReference.Perhaps it
should return the  URLs as a string array, and let the applicationturn them
into LDAPUrl objects if desired.  This is backwards to what I said in an
earlier e-mail, butnow I see the need for Strings instead of LDAPUrls". 

So let's return String[] in both cases. 
  

4. 
> An application doing its own referral handling may need to make 
>  decisions based on the scheme of URLs returned from search 
>  continuation references or referrals. 
> 
>  Shouldn't the LDAPUrl object provide a method to retrieve 
>  the URL scheme, viz. ldap, http, & etc. 

This is an LDAP only URL and not a generic URL, so there is no reason to
report a URL scheme. However, there is a need to support ldaps with some LDAP
servers. To accomodate them, we propose a boolean method isSecure(). 
  

5. 
> I am puzzled why the draft specifies that automatic referral 
>  following is done only for synchronous operations.  While 
>  it is simple for an application using async to merge results from 
>  multiple listeners or to specify the same listener for multiple 
>  requests, it is not so simple to determine when a request 
>  and all its child referral requests are complete.  Why put 
>  this burden on the application? 
> 
>  IMO there is no technical reason that automatic referral 
>  following mechanisms cannot be used across the board, 
>  for both synchronous and asynchronous operations. 
> 
>  Could you fill me in on the reason for the current design. 

When originally implementing the asynchronous interfaces, we looked at this
option, but we concluded that implementation would be difficult, and the
asynchronous interfaces are intended to allow the client to interact with the
protocol at a low level anyway, so it was not unreasonable for the client to
manage the interactions. SASL authentication is another feature which is not
handled automatically by the API for the asynchronous interfaces, for the same
reason. 
  

6. 
> Re: referrals as defined in draft-ietf-ldapext-ldap-java-api-11.txt 
> 
>  The I-D seems silent on what happens if an application has automatic 
>  referral handling enabled, and for some reason one or more of the 
>  referrals or search continuation references cannot be followed. 
> 
>  This could happen for at least three reasons: 
>  1- The bind fails when explicitly binding using the LDAPBind object 
>  2- The bind fails when implicitly binding using anonymous credentials, 
>       or when using the LDAPRebind object to obtain credentials 
>  3- None of the servers in the referrals list have the scheme ldap:// 
>     specified and thus are ignored (per the draft) (4.7.10) 
> 
>  I assume that if automatic referral following succeeds, the 
>  application doesn't see any referral URLs, i.e. no LDAPReferralException 
>  is thrown when doing LDAPSearchResults.next(), (4.35.4) and 
>  LDAPSearchResults.nextElement() (4.35.5) does not return an 
>  LDAPReferralException object. 
> 
>  The draft indicates that LDAPReferralException is only thrown 
>  if automatic referral handling has not been enabled.  It doesn't 
>  indicate whether the LDAPReferralException object is returned 
>  on LDAPSearchResults.getElement(), I assume it is not returned. (4.26) 
> 
>  So what happens if a referral cannot automatically be followed. 
>  I think the application needs to be notified of this error, and the 
>  logical way to do that is to return the referral information to 
>  the application. 
> 
>  IMO, LDAPReferralException should be returned / thrown on 
>  synchronous operations any time a referral is not followed, not just 
>  if automatic referral following is disabled. 
> 
>  Thus, LDAPReferralException would always be returned / thrown 
>  if automatic referal following is not enabled.  If enabled, 
>  LDAPReferralException would be thrown / returned when none of 
>  the servers in a referral response list can be used to follow the referral 
>  and would be treated by the application as an error situation. 
> 
>  Changing the draft to reflect this will  clear up these issues. 

A good point, however there should be more info in the exception, so that the
application can clearly differentiate between a referral not being followed
and errors during automatic referral following. The actual LDAPException that
caused the referral following to fail (cannot connect, auth failed, no such
object) could be stored in the LDAPReferralException. The app can then simply
check 

catch (LDAPReferralException ex) { 
    if (ex.getReferralFailureException() == null) { 
        // I am supposed to follow referrals 
        LDAPUrls[] = ex.getURLs(); 
        ... 
    } else { 
        // The SDK could not follow the referral 
        System.err.println("Failed to follow referral " + getUrls()[0] + " " + 
            ex.getReferralFailureException()); 
    } 
  

7. 
> 
>  I would like clarification on how LDAPBind vs LDAPRebind objects 
>  are used in the Java API. 
> 
>  The I-D implies, but never quite says that the two objects don't 
>  normally exist in the LDAPConstraints object at the same time. 
>  (Implied by Appendix G - LDAPConstraints - they should 
>  not be specified on the same constructor) 
> 
>  They certainly can both be set by using the set methods, but 
>  are probably not both used at the same time. 
> 
>  I surmise from the draft that these objects are used as follows: 
> 
>  1. Neither object is used unless Referrals are enabled in the 
>      LDAPConstraint object (automatic referral following enabled). 
> 
>  2. An LDAPRebind object is used only if present and if an LDAPBind 
>      object is not present in the LDAPConstraint object. 
> 
>  3. An LDAPBind object is used if present.  If present, the LDAPRebind 
>      object is not needed by LDAPConnection as no implicit binding is done. 
>      Explicit binding is the responsibility of the LDAPBind object. 
Therefore 
>      the LDAPRebind object is not used in this case. 
> 
>  If my guesses are correct, maybe the draft should be clarified as to the 
>  usage of these objects. 

This is a correct interpretation. An improvement to the I-D would be be to
specify a single field in LDAPConstraints - rebindHandler - which would accept
either LDAPBind or LDAPRebind. An additional tag interface would need to be
declared, somthing like this: 

public interface LDAPReferralHandler {  // the tag interface 
} 

public class LDAPConstraints { 
     private LDAPReferralHandler rebindProc; 
     ... 
} 

public interface LDAPBind extends LDAPReferralHandler { 
... 
} 

public interface LDAPRebind extends LDAPReferralHandler { 
... 
} 
  

8. 
> Re: LDAPBind as defined in draft-ietf-ldapext-ldap-java-api-11.txt 
> 
>  It is unclear from the draft how the LDAPConnection object must be 
>  used by an application implementing the LDAPBind interface. 
> 
>  I am guessing that the LDAPConnection object passed to the bind() 
>  method of the LDAPBind implementation is a new LDAPConnection object 
>  created by automatic referall following code in the original LDAPConnection

>  object. The object contains the  AuthenticationDN and 
>  AuthenticationPassword from the LDAPConnection that the continuation 
>  reference was received on. The Host and Port are filled in from the 
>  referral/reference host & port. When passed to the bind() method, 
>  neither connect nor bind has been performed on this LDAPConnection object. 
> 
>  In order to make this work, I believe the iimplementation of the 
>  LDAPBind.bind() method MUST use the LDAPConnection object, which 
>  was passed as a parameter, to perform its connect and bind calls. 
>  It then returns success if both operations succeed.  The original 
>  LDAPConnection object referral handling code can then use the 
>  new LDAPConnection object when it resends the search request, 
>  updated with the new search base and possibly search filter. 
> 
>  The above should be clarified in the draft. 

  OK 
  

>  It seems that the LDAPRebind interface would be easier to implement if 
>  additional data were provided in the new LDAPConnection object.  Such as: 
> 
>  1. A reference to the LDAPSocketFactory class from the original
LDAPConnection 
>      object.  This allows it to connect in the same way as the original
connection. 
>  2. An LDAPConstraints object containing a reference to the LDAPRebind
object 
>      from the original LDAPConnection object.  The LDAPBind.bind() method
may 
>      want to get authentication information using and LDAPRebindAuth object,
and 
>      this gives it a way to do that. 
>  3. The protocol version used in the connect/bind of the original object. 
This allows 
>      The LDAPBind.bind function to bind with same protocol version used in
the 
>      original connection. 
>  4. The mechanism used when binding.  This could be the mechanism used on
the 
>      bind in the original LDAPConnection object, or perhaps LDAPRebindAuth
could 
>      be modified to provide the triplet - UserDN, Password, and Mechanism
for the 
>      specified host. 
> 
>  IMO the above changes would give the application, using explicit bind,
greater flexibility 
>  when dealing with referrals / continuation references during automatic
referral 
>  following: 
> 

  It's questionable that this is necessary. Can't you do all that with
LDAPBind (rather than LDAPRebind)? 

  If it really is required (which duplicates what you can do with LDAPBind),
how about the following instead (let the implementation pull whatever it needs
from the original connection, as LDAPBind does)? 

LDAPConnection bind(String ldapurl, LDAPConnection origConn); 
  

9.  (from Kurt) 
> You might consider renaming getSubTypes to getOptions as 
> not all options (e.g. ;binary) are subtypes. 

  Not worth changing, I don't think. 
  

10. 
> The I-D interchanges referrals and search continuation references. 
> 
>  A referral happens only on an operation and no other results are returned. 
> 
>  A search continuation reference happens only on a search and is mixed in
with 
>  returned search entries. 
> 
>  The I-D refers to continuation references only in section 2.2 and 2.34. 
> 
>  It sometimes uses referrals where search continuation references should 
>  be used, and generally where both apply. 
> 
>  Line 473 - referred to -> referred-to 
> 
>  The following should probably refer to both referrals and continuation
references 
>  Section 1: line 459, 468 
>  Section 2.2: LDAPRebind / LDAPBind 
>  Section 2.3 - LDAPRebindAuth 
>  Section 2.4 - LDAPReferralException 
>  Section 4.4 - LDAPBind 
>  Section 4.7.x - doReferrals / binder /reauth / hop_limit 
>  Section 4.7.x - RebindProc, BindProc, Referrals 
>      as well as the methods to get and set the above 
>  Section 4.24 - LDAPRebindAuth 
>  Section 4.25 - LDAPRebind 
>  Section 4.26 - LDAPReferralException 
>  Section 4.27 - LDAPResponse 
> 
>  The following refer to search references 
> 
>  Section 4.31.1 - LDAPSearchConstraints - doReferrals, reauth binder,
hop_limit params 
>  Section 4.35.4 - LDAPSearchResults.next() 
>  Section 4.35.5 - LDAPSearchResults.nextElement() 
>  Section 4.39.13 - SetOption ( search options relating to referrals) 
> 

Yes. The API makes the distinction transparent to the user of the API. The I-D
could state that more explicitly. 
  

11. 
> Resend - properly indicating where comments are 
> 
> Steve Sonntag wrote: 
> 
> >  Re: LDAPBind as defined in draft-ietf-ldapext-ldap-java-api-11.txt It 
> > is unclear from the draft how the LDAPConnection object must beused by 
> > an application implementing the LDAPBind interface. I am guessing that 
> > the LDAPConnection object passed to the bind()method of the LDAPBind 
> > implementation is a new LDAPConnection objectcreated by automatic 
> > referall following code in the original LDAPConnectionobject. The 
> > object contains the  AuthenticationDN andAuthenticationPassword from 
> > the LDAPConnection that the continuationreference was received on. The 
> > Host and Port are filled in from thereferral/reference host & port. 
> > When passed to the bind() method,neither connect nor bind has been 
> > performed on this LDAPConnection object. In order to make this work, I 
> > believe the iimplementation of theLDAPBind.bind() method MUST use the 
> > LDAPConnection object, whichwas passed as a parameter, to perform its 
> > connect and bind calls.It then returns success if both operations 
> > succeed.  The originalLDAPConnection object referral handling code can 
> > then use thenew LDAPConnection object when it resends the search 
> > request,updated with the new search base and possibly search filter. 
> 
> It is also necessary that the application implementing the 
> LDAPBind.bind() 
> method use a synchronous bind do bind to the referred-to-server, or 
> if using an asyncronous bind, it must wait until the bind operation has 
> completed before returning status. 

This is the same as #8. 
  

12. 
> Re: Referrals on operations as defined 
>        in draft-ietf-ldapext-ldap-java-api-11.txt 
> 
>  When a referral occurs on an asynchronous operation 
>     the referral is returned as an LDAPResponse object. 
>     The referral info is obtained using the getReferrals() method. 
> 
>  When a referral occurs on a synchronous operation 
>      An LDAPException is thrown.  The exception object is 
>      specialized as an LDAPReferralException object and 
>      the referral info can be obtained via the getURLs() method 
>      with appropriate casting on the object. 
> 
>  Is this correct? 
> 
>  Should the doc be clarified? 

Yes this is correct. For asynch interfaces exceptions are raised only for
connection errors. LDAP result messages are converted into LDAPResponse
objects which are to be checked by the app for errors and referrals. Again,
asynch interfaces operate at a low level, close to the protocol. 
  

13. 
> 
>  Section 4.40.3: - LDAPv3.extendedOperation 
>     Shouldn't this method have a method that 
>     includes LDAPConstraints as an argument. 
>    The protocol allows extended operations to 
>    support controls. 

OK. 
  

>  Section 4.40.2 - LDAPV3.connect 
>    This special version of connect is really 
>    a connect and a bind combinded.  Should 
>    this also have a method with an LDAPConstraints 
>    object? - or if the application needs that 
>    should they just do the two separate operations 
>    and put the LDAPConstraints on the bind? 

Let's remove the method from the I-D. It's just a convenience. 
  

14. 
> 
>  I think the draft should describe more fully the 
>  semantics of the implicit bind w/r automatic referral following: 
> 
>  I will describe what the I-D describes and where 
>  I have questions: 
> 
>  1. Authentication - uses anonomyous credentials unless 
>     LDAPRebind specified in LDAPConstraints. 

Yes 
  

>  2. Protocol Version ?? - Does it use the same protocol 
>      version as the LDAPConnection receiving the referral or is it 
>      always V2??  I vote for the having it the same as the originating 
>      connection. 

Yes. 
  

>  3. AuthenticationMethod: Is it the same as the originating connection, 
>      or is it "simple" - I assume simple is used. 

Yes. LDAPBind must be used if SASL is desired for the referral connection. 
  

>  4. Does it use the LDAPSocketFactory if specified on the 
>      originating connection.  I am not sure what to do here. 
>      It seems better to use it if available, then an encrypted 
>      connection can be established and thus prevent 
>      clear text password transmittion on the wire.  I just 
>      talked myself into it - it should be used. 

If the referral ldap url specifies ldaps, the referral connection should use
ldaps (regardless of the original connection). At least in our implementation
:-) - since ldaps is being deprecated in favor of startTLS, we may not want to
mention it in this I-D (I just remembered that I owe LDAPEXT an informational
RFC draft on ldaps). For startTLS, I guess the referral connection should
attempt to use startTLS if the original connection was in startTLS mode. Is
there any other way to determine whether or not to use startTLS? 
  

15. 
>  When performing a search it is possible for the server 
>  to return multiple search continuation references, each 
>  with a different search base. 
> 
>  The I-D states that when retrieving results from a 
>  search using LDAPSearchResults.next() that all the 
>  results are returned to the application after which 
>  on the last call to next() an LDAPReferralException 
>  is thrown. 
> 
>  My question is: how does the application get the 
>  rest of the continuation references, as a 
>  ReferralException object encapsulates the 
>  reference list from one search continuation reply. 
> 
>  If the application did another next() call would 
>  another LDAPReferralException be thrown? 
>  How would the application know when to stop? 
>  Does it check the enumeration count to see if 
>  more items exist in the enumeration, and thus 
>  continue to call next() and get an LDAPReferralException 
>  each time.  As an alternative, the application 
>  could switch to calling nextElement() to get the 
>  rest of the search references as LDAPReferralException 
>  objects.  How do you envision the application doing this? 
> 
>  The I-D should make it clear that the application 
>  can get more than one search continuation 
>  reference, and indicate a mechanism to deal 
>  with the situation. 
> 

The app should continue as long as hasMoreElements() returns true. Calling
nextElement() is not a good idea. The following example from the Mozilla
implemenation javadocs demonstrates proper handling. Note the "continue" after
the exception has been processed. 

LDAPSearchResults res = ld.search( MY_SEARCHBASE, 
                              LDAPConnection.SCOPE_BASE, MY_FILTER, 
                              null, false ); 
      while ( res.hasMoreElements() ) { 
        try { 
          LDAPEntry findEntry = res.next(); 
        } catch ( LDAPReferralException e ) { 
          LDAPUrl refUrls[] = e.getURLs(); 
          for ( int i = 0; i < refUrls.length; i++ ) { 
          // Your code for handling referrals 
          } 
          continue; 
        } catch ( LDAPException e ) { 
          // Your code for handling errors on limits exceeded 
          continue; 
        } 
        ... 
      } 
  

16. 
> 
>  Since LDAPResponseListener and LDAPSearchListener 
>  objects implement exactly the same set of methods, 
>  does it seem reasonable that an interface be created 
>  named something like LDAPListener that specifies 
>  those four methods, and that LDAPSearchListener 
>  and LDAPResponseListener implement this interface. 
>  This forces those methods to stay the same in both classes. 
> 

> If an LDAPListener interface were created, then 
> the two methods in LDAPv2.abandon 
> 
>    public void abandon(LDAPSearchListener listener) 
>    public void abandon(LDAPResponseListener listener) 
> 
> Could be combined into one 
> 
>    public void abandon(LDAPListener listener) 

We have responded to this earlier, but here is a brief recap. In the very
first asynch draft, LDAPSearchListener extended LDAPResponseListener. Later
when we adding abandon(int) method, we investigated removing
LDAPSearchListener and leaving only LDAPResponseListener because there were
implementation issues (multiplexing, and raising exceptions as a result of a
lost connection). Then, in order not to change the draft considerably, we
decided to make only minor changes and just resolve the implementation
problems. We kept LDAPSearchListener, but it does not extend
LDAPResponseListener any more. 
  

17. 
> 
>  4.6.19 setConstraints 
> 
>  Sets the constraints that apply to all operations performed 
>  through this connection 
> 
>  Wouldn't it be more clear to state: 
> 
>  Sets the constraints that apply to all non search operations 
>  performed through this connection. 
>  - - - - - - - - - - - - - - - - - - - - 

The constraints (hop limit, bind handler, referrals, timeout, controls) apply
to all operations (including search operations). 
  

>  4.39.13 setOption 
> 
>  Seems to set only the search constraints options, but 
>  the first paragraph has a confusing sentence that 
>  talks about LDAPConstraints. 
> 
>  Was it your intention that the LDAPConstraints be 
>  the same object as LDAPSearchConstraints or 
>  that they be different objects? 
> 
>     "These options represent the default search constraints for the 
>     current connection. Some of these options are also propagated through 
>     the LDAPConstraints, which can be obtained from the connection object 
>     with the getSearchConstraints method." 
>  The above two sections 4.39.13 & 4.6.19 could be 
>  construed to indicate that the LDAPConstraints and the 
>  LDAPSearchConstraints objects for a connection are 
>  in fact the the same object, however, that fact that 
>  each has a separate set & get method seems to indicate 
>  they are different objects. 
> 
>  Could you please clarify this? 
> 

Yes this is intentional. Originally we had only LDAPSearchConstraints but it
did not make a lot of sense to use  "search" constraints for non-search
operations. We separated the interfaces such that LDAPSearchConstraints
extends LDAPConstraints and all properties set on LDAPConstraints are also
visible in LDAPSearchConstraints. 

But see 1.4 above. 
  

18. 
> 
>  4.39.1 LDAPv2.abandon 
> 
>  The RFC 2251 and the C api draft allow controls to be specified 
>  on an abandon operation.  In java it is allowed only using the default 
>  constraints object or search constraints object.  Should methods 
>  be defined that allow constraints to be specified on abandon? 

Strictly speaking this is true, but if we look at the properties in
LDAPConstraints, none of them are applicable to abandon(). This change is not
required. 
  

>  When calling abandon( int id), it is unclear whether LDAPConstraints 
>  or LDAPSearchConstraints should be used for the default 
>  constraints. 

LDAPSearchConstraints is only for search. 
  

19. 

  The JAVA LDAP API (draft-ietf-ldapext-ldap-java-api-11.txt) defines the following method for
  extended operations:


  "public LDAPExtendedOperation extendedOperation(LDAPExtendedOperation op) throws
  LDAPException"

  I would think that you would return an LDAPExtendedResponse object rather than an
  LDAPExtendedOperation object. I agree that one could reuse the LDAPExtendedOperation object
  (as it has the same set of fields) but then why bother defining a LDAPExtendedResponse object
  in the draft?


OK. 
  

20. 

   Section 4.7.11 LDAPConstraints.setTimeLimit
    
   LDAP Constraints applies to all operations, not just search operations.
    
   The first sentence should probably be changed from:
    
        Sets the maximum number of milliseconds to wait for any operation
        under these search constraints.
   To something like:
    
        Sets the maximum number of milliseconds the client waits for any operation
        under these constraints.
    
   Section 4.7.5 LDAPConstraints.getReferrals
    
       Change nor to or
    
       Specifies whether nor not ...
    
   -Steve


OK. 
  

21 
LDAPSortKey. 

  It is still listed in section 2.2

   >>> Rob Weltman  01-Sep-00 2:59:45 PM >>>
     Someone pointed out that LDAPSortKey is not used/referenced, so I removed it from the draft. 

     In the Netscape implementation, it is used by LDAPSortControl. The current API draft does not cover any particular controls.


OK 
  

22. 

  Re: LDAP_PARTIAL_RESULTS Result Code defined in
  section 4.16.6 of draft-ietf-ldapext-ldap-java-api-11.txt

  Section 4.16.6 instructs the reader to review RFC 2251 for
  a discussion of the meanings of the codes defined in that
  section.

  RFC 2251 does not discuss the meaning of the LDAP_PARTIAL_RESULTS
  result code. Should this be defined or referenced in this draft?

OK. 
  

23. 

  In the Bibliography, [3] refers to RFC 1960.
    
   Shouldn't it refer to RFC 2254 instead?


OK. 
  

24. 
  

   4.40.1
    
   In the explaination of bind operations that use mechanisms should the first
   Paragraph be changed from 
    
      Authenticates to the LDAP server (that the object is currently
      connected to) using the specified name and of a specified set of
      mechanisms. If none of the requested SASL mechanisms is available, an

       Authenticates to the LDAP server (that the object is currently
      connected to) using the specified name and ONE of a specified set of  <----
      mechanisms. If none of the requested SASL mechanisms is available, an


OK. 
  

   What does it mean -
    
      if the first version of the method (i.e. the one that specifies no mechanism)
      is called, the LDAP server will be interrogated for its
      supportedSaslMechanisms attribute of its root DSE.
    
   What does it do after the LDAP server is interrogated?  Does it use one
   of them, and if so how does the application know which one is used
   and how does it know what kind of credentials to supply?


Yes, if no mechanisms are specified, the mechanisms supported by the server
are processed until one is mutually agreed on. The callback handler is called
to obtain credentials. Are you thinking that the credentials to be returned
depend on the mechanism being negotiated? Let me think about that a little... 
  

25. 

   4.40.1 bind specifying a mechanism
    
   It would seem that if the mechanism is "simple"
   that the API should specify how the password
   is to be specified in the Hashtable object props
   so that it is consistent across implementations.
   Other mechanisms and associated Hashtable
   values are the subject of other I-Ds.
    
    
   My suggestions:
    
         props.put("password", new String("user-password-value");)


  Credentials are obtained from the callback handler. 
  

26. 
  

  Shouldn't the SASL bind mechanisms also support the ability
  for the application to specify an LDAPConstraints
  object so that call specific controls can be specified?


OK. 
  

27. 

  When using an explicit bind for referrals where sasl mechanisms 
  were used on the original LDAPConnection, the LDAPBind.bind()
  method will need access to the Hashtable parameter passed on the
  bind to get the credentials used.  A method needs to be
  supplied in LDAPConnection to get the Hashtable object with
  semantics similar to what is now used for getAuthenticationPassword()


  Does it need to be a public method? Can't it be a package scope
(implementation-defined) method? 
  

28. 

  I am trying to understand the encode/decode functions
   in the LDAPUrl class.
    
   I assume that the encode method turns unsafe characters
   (as defined by RFC1738, RFC 2255, & etc.) into characters
   of the form %HH and that decode turns those characters
   back into the raw unencoded characters.
    
   Question 1: The reference to decoding "+" into " "
   and encoding " " into "+" .  I could not find any reference
   to the need for doing this in the RFCs.  Could someone
   please tell me why someone might expect that this behavior?

  " " does not need to be encoded in LDAP URLs. 
  

   Question 2:  What kind of strings do the constructors of the
   LDAPUrl class expect.  Do the constructors expect the 
   strings to be already encoded?


  Yes. 
  

   Question 3:  Does the encode method take into account the field
   in the URL when doing the encoding (e.g. filters vs. base DN) which
   may have different reserved characters and thus slightly different
   encoding rules ? which boils down to the real question - does 
   the encode function expect a full correctly formatted URL
   or can one hand it just the base-DN, or just the filter and
   expect it to be correctly encoded?
    
   i.e., does the LDAPUrl constructor with individual parts expect 
   encoded strings and will the encode function do it?


  LDAPUrl.encode() expects to receive a string to be encoded. For all
practical purposes, it should be a DN or a filter string (and not a full LDAP
URL). After encoding, the DN and filter can be passed to the LDAPUrl
constructor. 
  

29. 

  4.16 LDAPException
    
   The LDAPException class has a method getMatchedDN() but has no way to set
   the matched DN in the object.  Shouldn't there be a constructor with MatchedDN
   as a parameter?

  Steve, 

   I wouldn't think so.  This is really meant to provide access to what a SERVER responds with, and thus I wouldn't know why a CLIENT would want to
   "setMatchedDN()".

   Regards,
   Tim Hahn

  I was thinking from the API perspective.  An implementation of the API would need to
   take the ber encoded packet and extract from it the matched DN, and then 
   generate the exception.  My point is that the API needs to be
   able to set the matchedDN data in the exception.  Are you suggesting that it
   should use a package method?  The only problem with a package method
   is that an extension written in a different package may also need to set 
   matchedDN when generating an exception, but wouldn't have any way
   to set the value.


  Is that realistic - that a class in some other package would create an
exception and put in its own matchedDN? 
  

30. 

  4.26 LDAPException
    
   I am trying to understand where the information in the
   constructor serverMessage comes from.  I am not
   aware of any message that is returned by the server with a
   referral result, except for the actual referral URLs.
    
   Do you intend that the class gets primed with the 
   referral URLs using the serverMessage parameter
   and if so how are the referrals delimited - otherwise
   can you elaborate on the meaning of this parameter
   and explain how the referral URLs are placed into the
   class.


  That is correct. The server returns the referral URLs in the message field.
I don't know if it is necessary to define the representation there (it is a
contract between the upper layer of an implementation and the BER decoding
layer - which is not defined in the I-D); clients query getURLs() to get the
URLs. 
  

31. 

  In draft-ietf-ldapext-ldap-c-api-04.txt section 11.6 Searching, it states:

  filter       A character string as described in [13], representing the
               search filter.  The value NULL can be passed to indicate
               that the filter "(objectclass=*)" which matches all entries
               is to be used.

  It might be helpful to note this behavior in sections 4.38.1 and 4.39.12 of
  draft-ietf-ldapext-ldap-java-api-11.txt. (Which would make those sections
  consistent with 4.38.8 of the same draft which states that (objectclass=*)
  is the default filter.)

  OK. 
  

32. 

  Also, in the Bibliograpy, [7] should be updated. (To draft-ietf-ldapext-ldap-c-api-04.txt)

  OK. 
  
 
--------------480A17C14EE6A0A3B94F7B2C--