We really ought to have a way to allow clients to make libldap use StartTLS without having to code their own calls into libldap for that purpose. I think it would be useful to allow specifying StartTLS in the extension field of the LDAP URL. Then at least it can be configured into ldap.conf forgotten about.
The code for ldap_initialize() should look for the URL extension field, and act on it if StartTLS / 1.3.6.1.4.1.1466.20037 is present.
Any comments?
On Sun, Oct 05, 2008 at 07:35:16PM -0700, Howard Chu wrote:
We really ought to have a way to allow clients to make libldap use StartTLS without having to code their own calls into libldap for that purpose. I think it would be useful to allow specifying StartTLS in the extension field of the LDAP URL. Then at least it can be configured into ldap.conf forgotten about.
The code for ldap_initialize() should look for the URL extension field, and act on it if StartTLS / 1.3.6.1.4.1.1466.20037 is present.
Any comments?
Not that I have any word in LDAP development, but this sounds *very* useful :-)
Volker
Volker Lendecke wrote:
On Sun, Oct 05, 2008 at 07:35:16PM -0700, Howard Chu wrote:
We really ought to have a way to allow clients to make libldap use StartTLS without having to code their own calls into libldap for that purpose. I think it would be useful to allow specifying StartTLS in the extension field of the LDAP URL. Then at least it can be configured into ldap.conf forgotten about.
The code for ldap_initialize() should look for the URL extension field, and act on it if StartTLS / 1.3.6.1.4.1.1466.20037 is present.
Any comments?
Not that I have any word in LDAP development, but this sounds *very* useful :-)
Yes I also find it useful. Not sure whether it should be within ldap_initialize() or just in the client apps though.
The first could be problematic if client applications just read the LDAP URI from some configuration file and pass it as is to ldap_initialize() and after that call ldap_start_tls() a second time based on different configuration parameters.
Ciao, Michael.
Michael Ströder wrote:
Yes I also find it useful. Not sure whether it should be within ldap_initialize() or just in the client apps though.
The first could be problematic if client applications just read the LDAP URI from some configuration file and pass it as is to ldap_initialize() and after that call ldap_start_tls() a second time based on different configuration parameters.
I don't see a big issue here: first of all, if the app is correctly documented, one would only use this extension if needed. Moreover, ldap_initialize can record that StartTLS was already requested because of the extension, and avoid requesting it twice.
p.
Ing. Pierangelo Masarati OpenLDAP Core Team
SysNet s.r.l. via Dossi, 8 - 27100 Pavia - ITALIA http://www.sys-net.it ----------------------------------- Office: +39 02 23998309 Mobile: +39 333 4963172 Fax: +39 0382 476497 Email: ando@sys-net.it -----------------------------------
Pierangelo Masarati wrote:
Michael Ströder wrote:
Yes I also find it useful. Not sure whether it should be within ldap_initialize() or just in the client apps though.
The first could be problematic if client applications just read the LDAP URI from some configuration file and pass it as is to ldap_initialize() and after that call ldap_start_tls() a second time based on different configuration parameters.
I don't see a big issue here: first of all, if the app is correctly documented, one would only use this extension if needed.
In simple cases there might not be any problem.
Moreover, ldap_initialize can record that StartTLS was already requested because of the extension, and avoid requesting it twice.
What does "avoid requesting it twice" mean? Return an error code or simply ignore it? Note that a client might wanna take note of whether ldap_start_tls() was successfully called by itself or not.
Ciao, Michael.
On Mon, 6 Oct 2008, Michael Ströder wrote:
Pierangelo Masarati wrote:
Michael Ströder wrote:
Yes I also find it useful. Not sure whether it should be within ldap_initialize() or just in the client apps though.
In ldap_initialize(), please. IMO, the proposal solves two problems:
1) it lets you use StartTLS with applications without the application author having to add code (and an option, probably) to do so
2) it lets you naturally request StartTLS on a per-URI basis
The former is only obtained if this is done from the library.
The first could be problematic if client applications just read the LDAP URI from some configuration file and pass it as is to ldap_initialize() and after that call ldap_start_tls() a second time based on different configuration parameters.
Seem, like a non-problem to me: if the app has an "ldap-tls" option, you would document that the user should not turn that option on if using the starttls URI extension or vice versa.
(All of Sendmail's products that use LDAP have such an option, plus logic to only use ldap_start_tls_s() on plain ldap:// URIs and not ldaps:// or ldapi:// URIs, but I think putting this in the URI is the Right Thing and see no long-term problems with supporting this.)
Moreover, ldap_initialize can record that StartTLS was already requested because of the extension, and avoid requesting it twice.
What does "avoid requesting it twice" mean? Return an error code or simply ignore it? Note that a client might wanna take note of whether ldap_start_tls() was successfully called by itself or not.
Such apps have a problem already, as they have to exclude ldaps:// URIs from that. This is just like an ldaps URI, except instead of starting with "ldaps", it ends with "starttlsOIDgoop".
Philip Guenther
Philip Guenther wrote:
On Mon, 6 Oct 2008, Michael Ströder wrote:
Pierangelo Masarati wrote:
Michael Ströder wrote:
Yes I also find it useful. Not sure whether it should be within ldap_initialize() or just in the client apps though.
In ldap_initialize(), please. IMO, the proposal solves two problems:
it lets you use StartTLS with applications without the application author having to add code (and an option, probably) to do so
it lets you naturally request StartTLS on a per-URI basis
The former is only obtained if this is done from the library.
I can see the advantages, especially since I have somthing like this in web2ldap's LDAP URL handling.
The first could be problematic if client applications just read the LDAP URI from some configuration file and pass it as is to ldap_initialize() and after that call ldap_start_tls() a second time based on different configuration parameters.
Seem, like a non-problem to me: if the app has an "ldap-tls" option, you would document that the user should not turn that option on if using the starttls URI extension or vice versa.
(All of Sendmail's products that use LDAP have such an option, plus logic to only use ldap_start_tls_s() on plain ldap:// URIs and not ldaps:// or ldapi:// URIs, but I think putting this in the URI is the Right Thing and see no long-term problems with supporting this.)
It's slightly different: From my understanding up to now ldap_initialize() itself did not send out a LDAP PDU. So the error handling of applications might not be prepared for ldap_initialize() causing a real error. This is an incompatible API change.
Such apps have a problem already, as they have to exclude ldaps:// URIs from that. This is just like an ldaps URI, except instead of starting with "ldaps", it ends with "starttlsOIDgoop".
It's not the same since calling ldap_start_tls() sends out the first LDAP PDU which might lead to another error.
Ciao, Michael.
On Mon, 6 Oct 2008, Michael Ströder wrote: ...
It's slightly different: From my understanding up to now ldap_initialize() itself did not send out a LDAP PDU. So the error handling of applications might not be prepared for ldap_initialize() causing a real error. This is an incompatible API change.
Ah, I think we're picturing slightly different proposals. I'm picturing it operating similar to how ldaps:// URIs work currently, where TLS is negotiated automatically when the connection is actually opened. My comment about the working being done in ldap_initialize() instead of the client app was more about the recognizing of the extension in the URI and marking that URI as needing TLS. I agree that ldap_initialize() should behave as it currently does, setting up the handle but not opening any connections.
Hmm, StartTLS implies/requires protocol version 3. It seems unfortunate that ldap_initialize() wasn't made to default to version 3. Lacking a change to that, what should happen if you use one of these URIs without setting the version to 3? a) error, because you're insane for not setting it already b) ignore, because things shouldn't just break c) automatically change version, because confusing people is fun.
Philip Guenther
Philip Guenther wrote:
I agree that ldap_initialize() should behave as it currently does, setting up the handle but not opening any connections.
So this would need ldap_initialize() to defer calling ldap_start_tls(). I don't think that's what Pierangelo has in mind.
Hmm, StartTLS implies/requires protocol version 3. It seems unfortunate that ldap_initialize() wasn't made to default to version 3. Lacking a change to that, what should happen if you use one of these URIs without setting the version to 3?
Another valid point.
Well, I've changed the default for the protocol_version in python-ldap to VERSION3 and no-one ever complained...
c) automatically change version, because confusing people is fun.
On some X.500 servers one can configure different charsets if LDAPv2 is used...
Ciao, Michael.
Michael Ströder wrote:
Philip Guenther wrote:
I agree that ldap_initialize() should behave as it currently does, setting up the handle but not opening any connections.
So this would need ldap_initialize() to defer calling ldap_start_tls(). I don't think that's what Pierangelo has in mind.
But that might actually be the simplest approach. ldap_initialize() can parse the URL and set a flag in the LDAP* handle noting that StartTLS was requested. On the next request, we can check to see if this flag is set and the current request is not a StartTLS exop. If so, perform the exop first. Then clear the flag and carry on.
Hmm, StartTLS implies/requires protocol version 3. It seems unfortunate that ldap_initialize() wasn't made to default to version 3. Lacking a change to that, what should happen if you use one of these URIs without setting the version to 3?
The same thing that happens now if you try to call ldap_start_tls_s() without setting the version to 3 (error).
Another valid point.
Well, I've changed the default for the protocol_version in python-ldap to VERSION3 and no-one ever complained...
c) automatically change version, because confusing people is fun.
On some X.500 servers one can configure different charsets if LDAPv2 is used...
Ah, the joy of T.61 just never dies...
Ciao, Michael.
On Mon, 6 Oct 2008, Howard Chu wrote:
Michael Ströder wrote:
Philip Guenther wrote:
I agree that ldap_initialize() should behave as it currently does, setting up the handle but not opening any connections.
So this would need ldap_initialize() to defer calling ldap_start_tls(). I don't think that's what Pierangelo has in mind.
But that might actually be the simplest approach. ldap_initialize() can parse the URL and set a flag in the LDAP* handle noting that StartTLS was requested.
In the LDAP handle? You mean in the LDAPURLDesc for that URI? I would expect ldap_initialize(&ld, "ldap://server.example.com/????!1.3.6.1.4.1.1466.20037," "ldap://127.0.0.1/,ldapi://");
to automatically negotiate TLS when connecting to server.example.com, but not when connecting to 127.0.0.1 or the UNIX domain socket.
(Hopefully I haven't mangled the syntax from the RFC too badly...)
Philip
Philip Guenther wrote:
On Mon, 6 Oct 2008, Howard Chu wrote:
Michael Ströder wrote:
Philip Guenther wrote:
I agree that ldap_initialize() should behave as it currently does, setting up the handle but not opening any connections.
So this would need ldap_initialize() to defer calling ldap_start_tls(). I don't think that's what Pierangelo has in mind.
But that might actually be the simplest approach. ldap_initialize() can parse the URL and set a flag in the LDAP* handle noting that StartTLS was requested.
In the LDAP handle? You mean in the LDAPURLDesc for that URI? I would expect ldap_initialize(&ld, "ldap://server.example.com/????!1.3.6.1.4.1.1466.20037," "ldap://127.0.0.1/,ldapi://");
to automatically negotiate TLS when connecting to server.example.com, but not when connecting to 127.0.0.1 or the UNIX domain socket.
Right. The actual place to insert this code is in ldap_new_connection(). Working on it now...
Michael Ströder writes:
Philip Guenther wrote:
I agree that ldap_initialize() should behave as it currently does, setting up the handle but not opening any connections.
So this would need ldap_initialize() to defer calling ldap_start_tls(). I don't think that's what Pierangelo has in mind.
Currently an application can do ldap_initialize() early, and at some later time start doing the actual LDAP operations. An ldap_initialize() which connects the server will mean such applications should be changed defer ldap_initialize() until they're ready to start using the connection, to avoid server idletimeout.
So it looks better to me to just set a flag which says "do startTLS when the connection is opened".
On another note, why doesn't ldap.conf have a StartTLS option? Maybe taking a list of ldap schemes for which to enable TLS.
(If it gets that, a StartTLS URL extension should likely have a way to turn off StartTLS. And command line option -Z0 or something could do the same.)
Similarly, why not a SASL on/off option? It's a bit annoying to have an option (-x) which I almost always have to use, but cannot configure.
Michael Ströder wrote:
Pierangelo Masarati wrote:
Michael Ströder wrote:
Yes I also find it useful. Not sure whether it should be within ldap_initialize() or just in the client apps though.
The first could be problematic if client applications just read the LDAP URI from some configuration file and pass it as is to ldap_initialize() and after that call ldap_start_tls() a second time based on different configuration parameters.
I don't see a big issue here: first of all, if the app is correctly documented, one would only use this extension if needed.
In simple cases there might not be any problem.
Moreover, ldap_initialize can record that StartTLS was already requested because of the extension, and avoid requesting it twice.
What does "avoid requesting it twice" mean? Return an error code or simply ignore it? Note that a client might wanna take note of whether ldap_start_tls() was successfully called by itself or not.
Correct. Here the choice is:
1) just ignore the second call, as it would violate RFC 4513
2) return an error
I vote in favor of (1).
If a client needs to explicitly know whether its own call succeeded, then this would need to be documented, and we fall back in the case I mentioned earlier.
The point of having an URL extension is to allow TLS starting by clients who don't know about Start TLS. Those that know about it usually are smart and flexible enough to be dealt with somehow.
p.
Ing. Pierangelo Masarati OpenLDAP Core Team
SysNet s.r.l. via Dossi, 8 - 27100 Pavia - ITALIA http://www.sys-net.it ----------------------------------- Office: +39 02 23998309 Mobile: +39 333 4963172 Fax: +39 0382 476497 Email: ando@sys-net.it -----------------------------------
Pierangelo Masarati wrote:
Michael Ströder wrote:
Pierangelo Masarati wrote:
Moreover, ldap_initialize can record that StartTLS was already requested because of the extension, and avoid requesting it twice.
What does "avoid requesting it twice" mean? Return an error code or simply ignore it? Note that a client might wanna take note of whether ldap_start_tls() was successfully called by itself or not.
Correct. Here the choice is:
- just ignore the second call, as it would violate RFC 4513
More specific: IMO the error code of the first call should be returned.
Ciao, Michael.
Michael Ströder wrote:
Pierangelo Masarati wrote:
Michael Ströder wrote:
Pierangelo Masarati wrote:
Moreover, ldap_initialize can record that StartTLS was already requested because of the extension, and avoid requesting it twice.
What does "avoid requesting it twice" mean? Return an error code or simply ignore it? Note that a client might wanna take note of whether ldap_start_tls() was successfully called by itself or not.
Correct. Here the choice is:
- just ignore the second call, as it would violate RFC 4513
More specific: IMO the error code of the first call should be returned.
Well, that would probably need to be returned by ldap_initialize(), so if the client continues after ldap_initialize() failed it deserves screwing up :) I think your request makes sense, and should be taken into account.
p.
Ing. Pierangelo Masarati OpenLDAP Core Team
SysNet s.r.l. via Dossi, 8 - 27100 Pavia - ITALIA http://www.sys-net.it ----------------------------------- Office: +39 02 23998309 Mobile: +39 333 4963172 Fax: +39 0382 476497 Email: ando@sys-net.it -----------------------------------