Issue 5655 - add option for setting minimum TLS/SSL protocol
Summary: add option for setting minimum TLS/SSL protocol
Status: VERIFIED FIXED
Alias: None
Product: OpenLDAP
Classification: Unclassified
Component: slapd (show other issues)
Version: unspecified
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: OpenLDAP project
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-08-13 22:43 UTC by guenther@sendmail.com
Modified: 2014-08-01 21:04 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description guenther@sendmail.com 2008-08-13 22:43:36 UTC
Full_Name: Philip Guenther
Version: 
OS: Linux
URL: ftp://ftp.openldap.org/incoming/guenther-080813.patch
Submission from: (NULL) (64.58.1.252)


It's time for SSL version 2.0 to die: it has numerous weaknesses and has been
superseded by SSL version 3.0 and TLS version 1.0 for *years*.  Indeed, the LDAP
Start_Tls extended operation is defined by reference to the TLS standard.

(It could be argued that a client that sends an SSLv2-compatible handshake after
doing Start_Tls is non-compliant, or at least non-interoperable, as servers are
only required to support true TLS handshakes.)

As a first step, here's a patch against the CVS trunk that adds the ability to
set the minimum TLS/SSL protocol from the C API (LDAP_OPT_X_TLS_PROTOCOL_MIN),
the ldap.conf (TLS_PROTOCOL_MIN), and the slapd config
(TLSProtocolMin/olcTLSProtocolMin).  Possible settings are:
C API ldap_[sg]et_option()             ldap.conf/slapd config
-----------------------------------------------------------
LDAP_OPT_X_TLS_PROTOCOL_SSLv2          SSLv2
LDAP_OPT_X_TLS_PROTOCOL_SSLv3          SSLv3
LDAP_OPT_X_TLS_PROTOCOL_TLSv1_0        TLSv1 OR TLSv1.0

(1.0, because TLSv1.1 is already published, even though OpenSSL doesn't support
it yet)

This option is set up to specify a minimum version instead of permitting
arbitrary control of which versions are supported because the SSL/TLS version
negotiation assumes that both ends support a contiguous range.  If one end has a
gap in what it supports (e.g., SSLv2 and TLSv1, but not SSLv3), then it'll fail
to handshake with another one that has the missing version as its highest
supported version, even though they both support a lower version.  Simply
setting just the lower-bound prevents the specification of such a
'silly-state'.

(for example: "openssl s_client -no_ssl3" will fail to handshake with "openssl
s_server -no_tls1", even though they both support SSLv2.  Ditto if you flip the
ends.)

Comment 1 Howard Chu 2008-08-13 23:38:16 UTC
guenther+ldapdev@sendmail.com wrote:
> Full_Name: Philip Guenther
> Version:
> OS: Linux
> URL: ftp://ftp.openldap.org/incoming/guenther-080813.patch
> Submission from: (NULL) (64.58.1.252)
>
>
> It's time for SSL version 2.0 to die: it has numerous weaknesses and has been
> superseded by SSL version 3.0 and TLS version 1.0 for *years*.  Indeed, the LDAP
> Start_Tls extended operation is defined by reference to the TLS standard.
>
> (It could be argued that a client that sends an SSLv2-compatible handshake after
> doing Start_Tls is non-compliant, or at least non-interoperable, as servers are
> only required to support true TLS handshakes.)
>
> As a first step, here's a patch against the CVS trunk that adds the ability to
> set the minimum TLS/SSL protocol from the C API (LDAP_OPT_X_TLS_PROTOCOL_MIN),
> the ldap.conf (TLS_PROTOCOL_MIN), and the slapd config
> (TLSProtocolMin/olcTLSProtocolMin).  Possible settings are:
> C API ldap_[sg]et_option()             ldap.conf/slapd config
> -----------------------------------------------------------
> LDAP_OPT_X_TLS_PROTOCOL_SSLv2          SSLv2
> LDAP_OPT_X_TLS_PROTOCOL_SSLv3          SSLv3
> LDAP_OPT_X_TLS_PROTOCOL_TLSv1_0        TLSv1 OR TLSv1.0

Using an option flag for each protocol version seems excessive; it will be a 
recurring maintenance burden because each new option flag reflects an API 
change. (GnuTLS claims to already support TLSv1.2.)

This should use a single option flag and a numeric or bitfield argument for 
selecting protocols instead. Since we're talking about minimum settings, it 
should likely just be an increasing range of numbers.

I note that the on-the-wire protocol version is just a 16 bit integer; we 
could define protocol names that correspond directly to these values.

> (1.0, because TLSv1.1 is already published, even though OpenSSL doesn't support
> it yet)

-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 2 Michael Ströder 2008-08-13 23:44:39 UTC
guenther+ldapdev@sendmail.com wrote:
> It's time for SSL version 2.0 to die:

Yupp!

> As a first step, here's a patch against the CVS trunk that adds the ability to
> set the minimum TLS/SSL protocol from the C API (LDAP_OPT_X_TLS_PROTOCOL_MIN),
> the ldap.conf (TLS_PROTOCOL_MIN), and the slapd config
> (TLSProtocolMin/olcTLSProtocolMin).  Possible settings are:
> C API ldap_[sg]et_option()             ldap.conf/slapd config
> -----------------------------------------------------------
> LDAP_OPT_X_TLS_PROTOCOL_SSLv2          SSLv2
> LDAP_OPT_X_TLS_PROTOCOL_SSLv3          SSLv3
> LDAP_OPT_X_TLS_PROTOCOL_TLSv1_0        TLSv1 OR TLSv1.0

 From my understanding this is what LDAP_OPT_X_TLS_CIPHER_SUITE is for, 
isn't it? It's directly passed to OpenSSL and can also be used to enable 
or disable SSLv2, SSLv3 and TLSv1 besides choosing the ciphers itself.

Apache HTTP server does it also that way. See:
http://httpd.apache.org/docs/2.2/mod/mod_ssl.html#sslciphersuite

This patch could be necessary if different SSL implementations can be 
used which have different parameters for this. Still you would have to 
set other implementation-specific parameters...

Ciao, Michael.

Comment 3 guenther@sendmail.com 2008-08-14 00:02:17 UTC
On Thu, 14 Aug 2008, Michael Ströder wrote:
...
> From my understanding this is what LDAP_OPT_X_TLS_CIPHER_SUITE is for, 
> isn't it? It's directly passed to OpenSSL and can also be used to enable 
> or disable SSLv2, SSLv3 and TLSv1 besides choosing the ciphers itself.

Nope.  The cipher suite list and protocol versions supported are 
orthogonal: even if you include "!SSLv2" in your cipher suite, openssl 
will still send an SSLv2-compatible handshake.  Ditto on the server side: 
when OpenSSL announced a vulnerability in the server SSLv2 handshake code, 
I looked at whether specifying "!SSLv2" in the cipher spec would protect 
the server as a workaround.  Nope: only setting the SSL_OP_NO_SSLv2 option 
or using a SSLv3-only or TLSv1-only method would do it.


> Apache HTTP server does it also that way. See:
> http://httpd.apache.org/docs/2.2/mod/mod_ssl.html#sslciphersuite

They also have the "SSLProtocol" directive, further down on that page.  


Philip Guenther

Comment 4 guenther@sendmail.com 2008-08-14 00:19:09 UTC
On Wed, 13 Aug 2008, Howard Chu wrote:
> This should use a single option flag and a numeric or bitfield argument 
> for selecting protocols instead. Since we're talking about minimum 
> settings, it should likely just be an increasing range of numbers.
>
> I note that the on-the-wire protocol version is just a 16 bit integer; 
> we could define protocol names that correspond directly to these values.

OpenSSL's API for this is a bitfield with symbolic names, so there would 
still need to be a maintained mapping from whatever schema OpenLDAP 
provided to that bit set.

I guess an alternative would be to directly expose the 
SSL_CTX_set_options() API: TLS_OPTIONS would take a number and pass it 
directly to that call.  Of course, the admin would have to read the .h 
file and do some math to figure out what to set, and there's no guarantee 
that OpenSSL won't change those values across a version change...


Philip Guenther

Comment 5 Howard Chu 2008-08-14 00:44:41 UTC
Philip Guenther wrote:
> On Wed, 13 Aug 2008, Howard Chu wrote:
>> This should use a single option flag and a numeric or bitfield argument
>> for selecting protocols instead. Since we're talking about minimum
>> settings, it should likely just be an increasing range of numbers.
>>
>> I note that the on-the-wire protocol version is just a 16 bit integer;
>> we could define protocol names that correspond directly to these values.
>
> OpenSSL's API for this is a bitfield with symbolic names, so there would
> still need to be a maintained mapping from whatever schema OpenLDAP
> provided to that bit set.

Yes, but there's no forward compatibility impact from this. I.e., if we have 
to map numbers to bitfields, we can just have a default case: if the number is 
higher than any we recognize, just disable all the bits we know about and 
assume the TLS library is smart enough to do something useful with whatever is 
left.

> I guess an alternative would be to directly expose the
> SSL_CTX_set_options() API: TLS_OPTIONS would take a number and pass it
> directly to that call.  Of course, the admin would have to read the .h
> file and do some math to figure out what to set, and there's no guarantee
> that OpenSSL won't change those values across a version change...

I think at this point we need to get away from using implementation-specific 
values. Back when OpenSSL was the only game in town I wouldn't have worried 
too much about it, but now it's becoming more of an issue.

-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 6 guenther@sendmail.com 2008-08-14 01:54:07 UTC
On Wed, 13 Aug 2008, Howard Chu wrote:
> Philip Guenther wrote:
...
> > OpenSSL's API for this is a bitfield with symbolic names, so there 
> > would still need to be a maintained mapping from whatever schema 
> > OpenLDAP provided to that bit set.
> 
> Yes, but there's no forward compatibility impact from this. I.e., if we 
> have to map numbers to bitfields, we can just have a default case: if 
> the number is higher than any we recognize, just disable all the bits we 
> know about and assume the TLS library is smart enough to do something 
> useful with whatever is left.

Hmm, with a warning in the docs "if you set this option to a value beyond 
the range understood by your version of OpenLDAP or the underlying SSL 
library, it may enforce a lower minimum or fail completely".


So instead of writing
	TLS_PROTOCOL_MIN TLSv1.0
they would write
	TLS_PROTOCOL_MIN 3,1

etc?  I guess that's acceptable to me, albeit a little user unfriendly.


> > I guess an alternative would be to directly expose the
> > SSL_CTX_set_options() API: TLS_OPTIONS would take a number and pass it
> > directly to that call.  Of course, the admin would have to read the .h
> > file and do some math to figure out what to set, and there's no guarantee
> > that OpenSSL won't change those values across a version change...
>
> I think at this point we need to get away from using implementation-specific
> values. Back when OpenSSL was the only game in town I wouldn't have worried
> too much about it, but now it's becoming more of an issue.

I guess I shouldn't have left out the "<joke>" brackets around that.


Philip

Comment 7 Michael Ströder 2008-08-14 10:56:09 UTC
Philip Guenther wrote:
> On Thu, 14 Aug 2008, Michael Ströder wrote:
> ...
>> From my understanding this is what LDAP_OPT_X_TLS_CIPHER_SUITE is for, 
>> isn't it? It's directly passed to OpenSSL and can also be used to enable 
>> or disable SSLv2, SSLv3 and TLSv1 besides choosing the ciphers itself.
> 
> Nope.  The cipher suite list and protocol versions supported are 
> orthogonal: even if you include "!SSLv2" in your cipher suite, openssl 
> will still send an SSLv2-compatible handshake.  Ditto on the server side: 
> when OpenSSL announced a vulnerability in the server SSLv2 handshake code, 
> I looked at whether specifying "!SSLv2" in the cipher spec would protect 
> the server as a workaround.  Nope: only setting the SSL_OP_NO_SSLv2 option 
> or using a SSLv3-only or TLSv1-only method would do it.

Ok.

>> Apache HTTP server does it also that way. See:
>> http://httpd.apache.org/docs/2.2/mod/mod_ssl.html#sslciphersuite
> 
> They also have the "SSLProtocol" directive, further down on that page.  

Then I'd vote for doing it exactly like this with one option (space- or 
comma-separated list of protocols).

Ciao, Michael.

Comment 8 guenther@sendmail.com 2008-08-15 06:09:16 UTC
On Thu, 14 Aug 2008, Michael Ströder wrote:
> Philip Guenther wrote:
...
> > They also have the "SSLProtocol" directive, further down on that page.  
> 
> Then I'd vote for doing it exactly like this with one option (space- or
> comma-separated list of protocols).

As I mentioned in the ITS, I think treating the various protocol versions 
as independently choosable is a Bad Thing, as it permits broken settings 
with no corresponding gain.

That said, it's more important to me that *some* option gets in so that I 
(and Sendmail) don't have to maintain forever a patch to add it.  If 
someone 'official' will make a decision and simply state what the option 
should look like in its three forms (C API, ldap.conf, slapd config), I'll 
munge the patch to match.


Philip Guenther

Comment 9 guenther@sendmail.com 2008-08-19 18:00:10 UTC
On Fri, 15 Aug 2008, Philip Guenther wrote:
...
> That said, it's more important to me that *some* option gets in so that I 
> (and Sendmail) don't have to maintain forever a patch to add it.  If 
> someone 'official' will make a decision and simply state what the option 
> should look like in its three forms (C API, ldap.conf, slapd config), I'll 
> munge the patch to match.

Any opinions?

ldap.conf:
TLS_PROTOCOL_MIN <major>,<minor>

C:
struct ldap_tls_protocol { unsigned char major, minor; } val;
val.major = 3; val.minor=0;
ldap_set_option(ld, LDAP_OPT_TLS_PROTOCOL_MIN, &val);

?


(I'm running out of time to get _something_ into Sendmail's local copy, at 
which point I'll just commit something there and have to leave you guys to 
hack whatever you get around into the official repository.)


Philip Guenther

Comment 10 Howard Chu 2008-08-19 21:22:41 UTC
guenther@sendmail.com wrote:
> On Fri, 15 Aug 2008, Philip Guenther wrote:
> ...
>> That said, it's more important to me that *some* option gets in so that I
>> (and Sendmail) don't have to maintain forever a patch to add it.  If
>> someone 'official' will make a decision and simply state what the option
>> should look like in its three forms (C API, ldap.conf, slapd config), I'll
>> munge the patch to match.
>
> Any opinions?
>
> ldap.conf:
> TLS_PROTOCOL_MIN<major>,<minor>

Let's use US convention <major>.<minor>...

> C:
> struct ldap_tls_protocol { unsigned char major, minor; } val;
> val.major = 3; val.minor=0;
> ldap_set_option(ld, LDAP_OPT_TLS_PROTOCOL_MIN,&val);

I would just use an int, and have the caller OR in the appropriate values. You 
could also define a few macros for the currently known versions.

What are the values for TLS1.1, 1.2, etc?
>
> ?
>
>
> (I'm running out of time to get _something_ into Sendmail's local copy, at
> which point I'll just commit something there and have to leave you guys to
> hack whatever you get around into the official repository.)
>
>
> Philip Guenther
>
>
>


-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 11 guenther@sendmail.com 2008-08-19 22:03:40 UTC
On Tue, 19 Aug 2008, Howard Chu wrote:
> guenther@sendmail.com wrote:
...
> > TLS_PROTOCOL_MIN<major>,<minor>
> 
> Let's use US convention <major>.<minor>...

Ok.

> > C:
> > struct ldap_tls_protocol { unsigned char major, minor; } val;
> > val.major = 3; val.minor=0;
> > ldap_set_option(ld, LDAP_OPT_TLS_PROTOCOL_MIN,&val);
> 
> I would just use an int, and have the caller OR in the appropriate 
> values.

So: 
	/* force TLS 1.0 or later */
	ldap_set_option(ld, LDAP_OPT_TLS_PROTOCOL_MIN, (3 << 8) + 1);


> You could also define a few macros for the currently known versions.

Preferences on the format of those macros?

#define LDAP_OPT_X_TLS_PROTOCOL_SSLv2		(2 << 8)
#define LDAP_OPT_X_TLS_PROTOCOL_SSLv3		(3 << 8)
#define LDAP_OPT_X_TLS_PROTOCOL_TLSv1_0		((3 << 8) + 1)
#define LDAP_OPT_X_TLS_PROTOCOL_TLSv1_1		((3 << 8) + 2)
#define LDAP_OPT_X_TLS_PROTOCOL_TLSv1_2		((3 << 8) + 3)

?

> What are the values for TLS1.1, 1.2, etc?

So far, TLS 1.x == SSL version 3.(x+1).


Philip Guenther

Comment 12 Howard Chu 2008-08-19 23:11:37 UTC
Philip Guenther wrote:
> On Tue, 19 Aug 2008, Howard Chu wrote:
>> guenther@sendmail.com wrote:
> ...
>>> TLS_PROTOCOL_MIN<major>,<minor>
>> Let's use US convention<major>.<minor>...
>
> Ok.
>
>>> C:
>>> struct ldap_tls_protocol { unsigned char major, minor; } val;
>>> val.major = 3; val.minor=0;
>>> ldap_set_option(ld, LDAP_OPT_TLS_PROTOCOL_MIN,&val);
>> I would just use an int, and have the caller OR in the appropriate
>> values.
>
> So:
> 	/* force TLS 1.0 or later */
> 	ldap_set_option(ld, LDAP_OPT_TLS_PROTOCOL_MIN, (3<<  8) + 1);

The set_option interface requires a pointer. So
	min = (3<<8)+1;
	ldap_set_option(ld, LDAP_OPT_X_TLS_PROTOCOL_MIN, &min);

>
>
>> You could also define a few macros for the currently known versions.
>
> Preferences on the format of those macros?
>
> #define LDAP_OPT_X_TLS_PROTOCOL_SSLv2		(2<<  8)
> #define LDAP_OPT_X_TLS_PROTOCOL_SSLv3		(3<<  8)
> #define LDAP_OPT_X_TLS_PROTOCOL_TLSv1_0		((3<<  8) + 1)
> #define LDAP_OPT_X_TLS_PROTOCOL_TLSv1_1		((3<<  8) + 2)
> #define LDAP_OPT_X_TLS_PROTOCOL_TLSv1_2		((3<<  8) + 3)
>
> ?
>
Drop the 'v' and I think it'll be fine

-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 13 guenther@sendmail.com 2008-08-21 04:17:31 UTC
I have an updated patch, but can't post it: ftp.openldap.org's incoming is 
full:

ftp> cd incoming
250 CWD command successful.
ftp> put guenther-080820.patch
local: guenther-080820.patch remote: guenther-080820.patch
150 Opening BINARY mode data connection for 'guenther-080820.patch'.
100% |**************************************************|  9215       00:00
452 Error writing file: No space left on device.
9215 bytes sent in 0.13 seconds (66.79 KB/s)
ftp>


(Once we get a patch that looks good, I'll follow it with a patch for the 
docs.)

Comment 14 guenther@sendmail.com 2008-08-27 20:15:20 UTC
On Wed, 20 Aug 2008, Philip Guenther wrote:
> I have an updated patch, but can't post it: ftp.openldap.org's incoming is 
> full:

Still full...

Comment 15 Kurt Zeilenga 2008-12-05 05:39:42 UTC
if this hasn't yet been uploaded, I note that FTP incoming is presently not
full.
Comment 16 guenther@sendmail.com 2008-12-05 06:53:23 UTC
I could have sworn I had uploaded the revised version of the patch back in 
August after some cleaning by Kurt, but have no way of confirming it.  So 
I've uploaded it again as guenther-20081204.patch.

Comment 17 Howard Chu 2009-01-24 02:35:24 UTC
guenther@sendmail.com wrote:
> I could have sworn I had uploaded the revised version of the patch back in
> August after some cleaning by Kurt, but have no way of confirming it.  So
> I've uploaded it again as guenther-20081204.patch.

Thanks, patch looks good, committed to HEAD. Have you got a manpage update, by 
the way?

-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 18 Howard Chu 2009-01-24 02:35:50 UTC
changed notes
changed state Open to Test
moved from Incoming to Software Enhancements
Comment 19 Quanah Gibson-Mount 2009-01-26 23:27:53 UTC
changed notes
changed state Test to Release
Comment 20 Quanah Gibson-Mount 2009-02-15 02:08:44 UTC
changed notes
changed state Release to Closed
Comment 21 guenther@sendmail.com 2009-03-19 18:27:40 UTC
On Fri, 23 Jan 2009, Howard Chu wrote:
> guenther@sendmail.com wrote:
> > I could have sworn I had uploaded the revised version of the patch back in
> > August after some cleaning by Kurt, but have no way of confirming it.  So
> > I've uploaded it again as guenther-20081204.patch.
> 
> Thanks, patch looks good, committed to HEAD. Have you got a manpage 
> update, by the way?

Here's the chunk for ldap.conf(5), diffed against the trunk.  None of the 
LDAP_OPT_X_TLS* options appear to be documented, so I didn't add anything 
to ldap_get_option(3).

Philip


Index: doc/man/man5/ldap.conf.5
===================================================================
RCS file: /data/cvs/openldap/pkg/ldap/doc/man/man5/ldap.conf.5,v
retrieving revision 1.50
diff -u -r1.50 ldap.conf.5
--- doc/man/man5/ldap.conf.5	26 Jan 2009 01:54:32 -0000	1.50
+++ doc/man/man5/ldap.conf.5	19 Mar 2009 18:22:00 -0000
@@ -336,6 +336,19 @@
 	gnutls-cli -l
 .fi
 .TP
+.B TLS_PROTOCOL_MIN <major>[.<minor>]
+Specifies minimum SSL protocol version that will be negoiated.
+If the server doesn't support at least that version,
+the SSL handshake will fail.
+To require TLS 1.x or higher, set this option to 3.(x+1),
+e.g.,
+.B TLS_PROTOCOL_MIN 3.2
+would require TLS 1.1.
+Specifying a minimum that is higher than that supported by the
+OpenLDAP implementation will result it in requiring the
+highest level that it does support.
+This parameter is currently ignored with GNUtls.
+.TP
 .B TLS_RANDFILE <filename>
 Specifies the file to obtain random bits from when /dev/[u]random is
 not available. Generally set to the name of the EGD/PRNGD socket.

Comment 22 OpenLDAP project 2014-08-01 21:04:53 UTC
Added to HEAD
Added to RE24