You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by "Nitkalya (Ing) Wiriyanuparb" <de...@gmail.com> on 2018/01/23 02:57:18 UTC

Questions about JSSEUtil#getKeyManagers

Hi all,

I'm on Java 8 and Tomcat 8.5.26 (built from tag) moving from 7.0.41.

I have a little problem with how JSSEUtil#getKeyManagers creates key
managers. This essentially causes Tomcat to sometimes serves an incorrect
server certificate chain during ServerHello.
-Djavax.net.debug=all gave me a clue as it printed out multiple "matching
alias", so I believe it's because the key manager (and key store) returned
from that method doesn't contain only one key. From what I see, when
switching to in-memory key store getKeyManagers creates a new key store of
the configured type, calls setKeyEntry and expects the new key store to
have only this one key in it.

Note that we have our own implementation of the key store, but please bear
with me.

I'm also aware of this following bit of documentation and I suspect that
the second sentence is very much related to my problem here. I'm also sure
the certificateKeyAlias is set correctly and SSLHostConfigCertificate has
all the expected values when I checked in debug mode.

> The alias used for the server key and certificate in the keystore. If not
specified, the first key read from the keystore will be used. The order in
which keys are read from the keystore is implementation dependent.

We didn't have this problem in 7.0.41 because it's doing something less
complex and eventually just creates a JSSEKeyManager with the expected key
alias with the key store as a delegate – see
https://github.com/apache/tomcat70/blob/TOMCAT_7_0_41/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java#L563

But in 8.5,
https://github.com/apache/tomcat85/blob/TOMCAT_8_5_26/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java#L267
the identity comparison "ksUsed == ks" looks kind of weird to me as
KeyStore.getInstance (at least in Oracle Java 8) always returns a new
instance of KeyStore, so the checks will never be true (or will it?).

Ideally, I'd want to find a way to get into that if block so the end state
is like in 7.0.41.

As I mentioned, we have our own key store implementation and it always
loads all keys it's supposed to know about so reassigning "ksUsed =
KeyStore.getInstance..." doesn't make a difference for us – it actually
makes it worse as without it "ksUsed == ks" would have been true.

We technically can just modify or introduce a new key store implementation
to cater for Tomcat implementation – locally patching Tomcat to remove the
identity check would work for us as well.

Before doing that, am I missing something obvious? is reimplementing our
key store the way to go here?

Cheers,
Nitkalya

Re: Questions about JSSEUtil#getKeyManagers

Posted by "Nitkalya Wiriyanuparb (Ing)" <de...@gmail.com>.
On 24 Jan 2018, 10:19 PM +1300, Nitkalya Wiriyanuparb (Ing) <de...@gmail.com>, wrote:

>
> On 24 Jan 2018, 9:45 PM +1300, Mark Thomas <ma...@apache.org>, wrote:
> > On 23/01/18 02:57, Nitkalya (Ing) Wiriyanuparb wrote:
> > > Hi all,
> > >
> > > I'm on Java 8 and Tomcat 8.5.26 (built from tag) moving from 7.0.41.
> > >
> > > I have a little problem with how JSSEUtil#getKeyManagers creates key
> > > managers. This essentially causes Tomcat to sometimes serves an incorrect
> > > server certificate chain during ServerHello.
> > > -Djavax.net.debug=all gave me a clue as it printed out multiple "matching
> > > alias", so I believe it's because the key manager (and key store) returned
> > > from that method doesn't contain only one key. From what I see, when
> > > switching to in-memory key store getKeyManagers creates a new key store of
> > > the configured type, calls setKeyEntry and expects the new key store to
> > > have only this one key in it.
> > >
> > > Note that we have our own implementation of the key store, but please bear
> > > with me.
> > >
> > > I'm also aware of this following bit of documentation and I suspect that
> > > the second sentence is very much related to my problem here. I'm also sure
> > > the certificateKeyAlias is set correctly and SSLHostConfigCertificate has
> > > all the expected values when I checked in debug mode.
> > >
> > > > The alias used for the server key and certificate in the keystore. If not
> > > specified, the first key read from the keystore will be used. The order in
> > > which keys are read from the keystore is implementation dependent.
> > >
> > > We didn't have this problem in 7.0.41 because it's doing something less
> > > complex and eventually just creates a JSSEKeyManager with the expected key
> > > alias with the key store as a delegate – see
> > > https://github.com/apache/tomcat70/blob/TOMCAT_7_0_41/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java#L563
> > >
> > > But in 8.5,
> > > https://github.com/apache/tomcat85/blob/TOMCAT_8_5_26/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java#L267
> > > the identity comparison "ksUsed == ks" looks kind of weird to me as
> > > KeyStore.getInstance (at least in Oracle Java 8) always returns a new
> > > instance of KeyStore, so the checks will never be true (or will it?).
> >
> > Yes they will. As per the comment at line 255, non-PKCS#8 keystores will
> > use the original key store.
> >
> > > Ideally, I'd want to find a way to get into that if block so the end state
> > > is like in 7.0.41.
> > >
> > > As I mentioned, we have our own key store implementation and it always
> > > loads all keys it's supposed to know about so reassigning "ksUsed =
> > > KeyStore.getInstance..." doesn't make a difference for us – it actually
> > > makes it worse as without it "ksUsed == ks" would have been true.
> >
> > And there is the problem.
> >
> > Tomcat is jumping through quite a few hoops to handle various use cases:
> > - PEM encoded keys
> > - keystores with multiple keys each with their own password
> >
> > That last one is the cause of most of the trouble. Key stores allow this
> > but the KeyManagerFactory API doesn't. This is why we now always create
> > the in-memory key store. When we do this, we can't just use JKS for the
> > in-memory key store type as that creates issues like BZ 61557.
> >
> > > We technically can just modify or introduce a new key store implementation
> > > to cater for Tomcat implementation – locally patching Tomcat to remove the
> > > identity check would work for us as well.
> > >
> > > Before doing that, am I missing something obvious? is reimplementing our
> > > key store the way to go here?
> >
> > I don't think you are missing anything obvious. We could look at adding
> > (even more) configuration options to separately control the type and
> > provider for the in-memory key store (assuming using JKS here would work
> > for you) but I'm a little concerned about how complex that code is getting.
> >
> I guess that’s another option. JKS would work for us. We have our own implementation of in-memory key store that would also (almost) work if Tomcat let us pick a different key store type for the in-memory store. But that sounds a bit yucky as it's exposing an option for internal Tomcat implementation.
>
> > I think I'd look at modifying your key store implementation but if that
> > is a lot of work, we can explore some additional configuration options
> > in Tomcat.
> The current easiest workaround for us is patching Tomcat internally as mentioned (our application stack is pretty strict so we’re sure nothing will be using a different key store). But if the current Tomcat implementation is here to stay, I would prefer doing the right thing. I’ll discuss this with my team and try creating another key store type for Tomcat as well.

Just to close this thread with our solution. We've created another KeyStore type that basically delegates to our main or in-memory implementation based on how Tomcat loads it.

Cheers,
Ing

> >
> > Cheers,
> >
> > Mark
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> > For additional commands, e-mail: users-help@tomcat.apache.org
>
> Cheers,
> Ing

Re: Questions about JSSEUtil#getKeyManagers

Posted by "Nitkalya Wiriyanuparb (Ing)" <de...@gmail.com>.
On 24 Jan 2018, 9:45 PM +1300, Mark Thomas <ma...@apache.org>, wrote:
> On 23/01/18 02:57, Nitkalya (Ing) Wiriyanuparb wrote:
> > Hi all,
> >
> > I'm on Java 8 and Tomcat 8.5.26 (built from tag) moving from 7.0.41.
> >
> > I have a little problem with how JSSEUtil#getKeyManagers creates key
> > managers. This essentially causes Tomcat to sometimes serves an incorrect
> > server certificate chain during ServerHello.
> > -Djavax.net.debug=all gave me a clue as it printed out multiple "matching
> > alias", so I believe it's because the key manager (and key store) returned
> > from that method doesn't contain only one key. From what I see, when
> > switching to in-memory key store getKeyManagers creates a new key store of
> > the configured type, calls setKeyEntry and expects the new key store to
> > have only this one key in it.
> >
> > Note that we have our own implementation of the key store, but please bear
> > with me.
> >
> > I'm also aware of this following bit of documentation and I suspect that
> > the second sentence is very much related to my problem here. I'm also sure
> > the certificateKeyAlias is set correctly and SSLHostConfigCertificate has
> > all the expected values when I checked in debug mode.
> >
> > > The alias used for the server key and certificate in the keystore. If not
> > specified, the first key read from the keystore will be used. The order in
> > which keys are read from the keystore is implementation dependent.
> >
> > We didn't have this problem in 7.0.41 because it's doing something less
> > complex and eventually just creates a JSSEKeyManager with the expected key
> > alias with the key store as a delegate – see
> > https://github.com/apache/tomcat70/blob/TOMCAT_7_0_41/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java#L563
> >
> > But in 8.5,
> > https://github.com/apache/tomcat85/blob/TOMCAT_8_5_26/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java#L267
> > the identity comparison "ksUsed == ks" looks kind of weird to me as
> > KeyStore.getInstance (at least in Oracle Java 8) always returns a new
> > instance of KeyStore, so the checks will never be true (or will it?).
>
> Yes they will. As per the comment at line 255, non-PKCS#8 keystores will
> use the original key store.
>
> > Ideally, I'd want to find a way to get into that if block so the end state
> > is like in 7.0.41.
> >
> > As I mentioned, we have our own key store implementation and it always
> > loads all keys it's supposed to know about so reassigning "ksUsed =
> > KeyStore.getInstance..." doesn't make a difference for us – it actually
> > makes it worse as without it "ksUsed == ks" would have been true.
>
> And there is the problem.
>
> Tomcat is jumping through quite a few hoops to handle various use cases:
> - PEM encoded keys
> - keystores with multiple keys each with their own password
>
> That last one is the cause of most of the trouble. Key stores allow this
> but the KeyManagerFactory API doesn't. This is why we now always create
> the in-memory key store. When we do this, we can't just use JKS for the
> in-memory key store type as that creates issues like BZ 61557.
>
> > We technically can just modify or introduce a new key store implementation
> > to cater for Tomcat implementation – locally patching Tomcat to remove the
> > identity check would work for us as well.
> >
> > Before doing that, am I missing something obvious? is reimplementing our
> > key store the way to go here?
>
> I don't think you are missing anything obvious. We could look at adding
> (even more) configuration options to separately control the type and
> provider for the in-memory key store (assuming using JKS here would work
> for you) but I'm a little concerned about how complex that code is getting.
>
I guess that’s another option. JKS would work for us. We have our own implementation of in-memory key store that would also (almost) work if Tomcat let us pick a different key store type for the in-memory store. But that sounds a bit yucky as it's exposing an option for internal Tomcat implementation.

> I think I'd look at modifying your key store implementation but if that
> is a lot of work, we can explore some additional configuration options
> in Tomcat.
The current easiest workaround for us is patching Tomcat internally as mentioned (our application stack is pretty strict so we’re sure nothing will be using a different key store). But if the current Tomcat implementation is here to stay, I would prefer doing the right thing. I’ll discuss this with my team and try creating another key store type for Tomcat as well.
>
> Cheers,
>
> Mark
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org

Cheers,
Ing

Re: Questions about JSSEUtil#getKeyManagers

Posted by Mark Thomas <ma...@apache.org>.
On 23/01/18 02:57, Nitkalya (Ing) Wiriyanuparb wrote:
> Hi all,
> 
> I'm on Java 8 and Tomcat 8.5.26 (built from tag) moving from 7.0.41.
> 
> I have a little problem with how JSSEUtil#getKeyManagers creates key
> managers. This essentially causes Tomcat to sometimes serves an incorrect
> server certificate chain during ServerHello.
> -Djavax.net.debug=all gave me a clue as it printed out multiple "matching
> alias", so I believe it's because the key manager (and key store) returned
> from that method doesn't contain only one key. From what I see, when
> switching to in-memory key store getKeyManagers creates a new key store of
> the configured type, calls setKeyEntry and expects the new key store to
> have only this one key in it.
> 
> Note that we have our own implementation of the key store, but please bear
> with me.
> 
> I'm also aware of this following bit of documentation and I suspect that
> the second sentence is very much related to my problem here. I'm also sure
> the certificateKeyAlias is set correctly and SSLHostConfigCertificate has
> all the expected values when I checked in debug mode.
> 
>> The alias used for the server key and certificate in the keystore. If not
> specified, the first key read from the keystore will be used. The order in
> which keys are read from the keystore is implementation dependent.
> 
> We didn't have this problem in 7.0.41 because it's doing something less
> complex and eventually just creates a JSSEKeyManager with the expected key
> alias with the key store as a delegate – see
> https://github.com/apache/tomcat70/blob/TOMCAT_7_0_41/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java#L563
> 
> But in 8.5,
> https://github.com/apache/tomcat85/blob/TOMCAT_8_5_26/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java#L267
> the identity comparison "ksUsed == ks" looks kind of weird to me as
> KeyStore.getInstance (at least in Oracle Java 8) always returns a new
> instance of KeyStore, so the checks will never be true (or will it?).

Yes they will. As per the comment at line 255, non-PKCS#8 keystores will
use the original key store.

> Ideally, I'd want to find a way to get into that if block so the end state
> is like in 7.0.41.
> 
> As I mentioned, we have our own key store implementation and it always
> loads all keys it's supposed to know about so reassigning "ksUsed =
> KeyStore.getInstance..." doesn't make a difference for us – it actually
> makes it worse as without it "ksUsed == ks" would have been true.

And there is the problem.

Tomcat is jumping through quite a few hoops to handle various use cases:
- PEM encoded keys
- keystores with multiple keys each with their own password

That last one is the cause of most of the trouble. Key stores allow this
but the KeyManagerFactory API doesn't. This is why we now always create
the in-memory key store. When we do this, we can't just use JKS for the
in-memory key store type as that creates issues like BZ 61557.

> We technically can just modify or introduce a new key store implementation
> to cater for Tomcat implementation – locally patching Tomcat to remove the
> identity check would work for us as well.
> 
> Before doing that, am I missing something obvious? is reimplementing our
> key store the way to go here?

I don't think you are missing anything obvious. We could look at adding
(even more) configuration options to separately control the type and
provider for the in-memory key store (assuming using JKS here would work
for you) but I'm a little concerned about how complex that code is getting.

I think I'd look at modifying your key store implementation but if that
is a lot of work, we can explore some additional configuration options
in Tomcat.

Cheers,

Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org