Open Bug 216695 Opened 21 years ago Updated 2 years ago

SSL client auth fails if CA certificate is renewed in client but not in server

Categories

(NSS :: Libraries, defect, P3)

Tracking

(Not tracked)

People

(Reporter: julien.pierre, Unassigned)

References

(Depends on 1 open bug)

Details

Nelson ran into the following problem recently :

After getting the renewed intranet CA certificate, he could no longer login to
the IMAP server with SSL client auth.

Here is what's happening :

The IMAP SSL server is configured to request client auth. The acceptable CA
certificate is the old intranet CA, marked trusted for client auth.

When Nelson logged in, his SSL client (Mozilla) submitted a certificate chain
that included his leaf certificate as well as the new intranet CA certificate.

The new CA certificate is in all respects identical to the old one except for
the validity date and the signature. In particular the public key in the new
certificate is identical to the public key in the old certificate - this is the
classic renewal case.

Because of this, Nelson's leaf certificate can chain to either the new CA
certificate or the old CA certificate.

The problem is this :

When the IMAP server receives Nelson's certificate chain, it creates temporary
certificates for each certificate - the leaf cert and the new CA certificate.
Neither certificate exists in the server's certificate database. The
certificates chain to a known root, but the root is not trusted for client auth
by the server. Therefore Nelson's chain is rejected.

Here is what should be happening :
When verifying Nelson's certificate chain, the server should start from the
leaf, and then ask the question "what's the trusted issuer certificate for this
certificate" ?
Instead, it finds the newest issuer certificate, using the function
CERT_FindCertIssuer . Unfortunately, that new certificate is untrusted because
it came from Nelson's certificate chain.

The fix for this is most likely in the certificate verification code,
CERT_VerifyCertChain . The algorithm needs to be aware that there may be
multiple issuer certificates, rather than only one, and should try the different
options. It should pick the "most trusted" issuer. Of course this in itself is
somewhat ambiguous since it depends what the caller is trying to do, for
instance what usage(s) he is trying to verify the cert against.
CERT_VerifyCertChain doesn't know that. Only the top-level CERT_VerifyCert
function knows.

This is a case where multiple paths in the cert chain verification are possible
and where they should all be explored. We currently only pick one and it's
incorrect.

The temporary work around for this is that when a CA cert is renewed, all SSL
servers doing client auth need to be upgraded with the newest CA certificate and
trust it.
Note that the client can also workaround the problem by deleting the new
intermediate CA and not sending it in the SSL client auth handshake.
But it is easier to fix on the server side.
The problem is even more severe than previously thought. There are more issues
in the certificate chain verification code.

This problem happens in two cases :

1) Nelson has a cert issued on 8/8/2003

He uses Mozilla to log in to the IMAP SSL server which trusts the issuer valid
from 6/1/2001 until 6/1/2004 .

He can't login because Mozilla sent the new issuer cert with a validity date
from 8/7/2003 to 8/7/2004, which the server doesn't trust.

2) I log in with my cert, issued on 7/23/2003 .

I use Mozilla to log in to the IMAP SSL server which trusts the issuer valid
from 6/1/2001 until 6/1/2004 .

I can't login.

It turns out that Mozilla _also_ sent the newer issuer cert, even though my cert
doesn't chain to it - its issuing date doesn't fall within the new issuer
validity date of  8/7/2003 to 8/7/2004 !!!!

The server also wasn't able to correctly distinguish Mozilla's error - it also
thinks my cert chains to that new issuer cert, which isn't trusted, and chokes
because of lack of trust ...

This appears to be due to a bug in CERT_FindCertIssuer. Somehow that function
isn't making appropriate use of the certificate issuing date.
CERT_FindCertIssuer takes a subject cert, a usage, and a date of verification .
I suspect the date of verification is being incorrectly used when building the
chains, which results in the newer issuing cert incorrectly being picked ...
Depends on: 216829
Depends on: 216832
We discussed this in a meeting monday. It was suggested that the correct fix is
to install the new CA cert in the server.

This sounds good in theory, but I question how practical it is today.

If we don't make NSS smarter about cert chain validation, this is the burden
that CA and web server administrators are going to have to go through :

Either :
1) as soon as a new CA cert is issued, all servers that use it must pick up the
new CA cert from the CA and trust it.

While this is the right thing to do, there is no protocol for automatically
doing this, or any other standard facility built into netscape servers to do it.
This means in practice the CA administrator must track down every server that
uses the CA cert. This isn't practical. Even if a list is maintained, the
process of updating the cert will take a long time.

If a client gets the new CA cert before a server gets it and trusts it, we run
into this problem, where half the users can't login because they have the new CA
cert.

2) when the new CA cert is issued, it is only given to the servers and not the
clients who request new certs. This would have to be done through ACLs. The CA
would hold off giving the new CA cert to clients until it is reasonably certain
that the servers have been updated with the CA cert.

All it takes is one S/MIME message "accidentally" signed with the newest CA cert
and disseminated to a mailing list to get back to case 1), where the users will
no longer be able to login.

Neither solution looks satisfactory to me.
I prefer #3 where :

3) we patch NSS to transparently handle this case.

Servers pick up the new NSS with this patch.
Whenever the CA administrator renews the CA cert (and that doesn't mean only
this time, for this particular deployment), he has plenty of time to notify the
servers that use the CA cert - basically, up until the overlap period of the two
CA certs is over.

This would mean, in this case, that there would be until 6/1/2004 to update the
CA cert on all the servers, and nothing would break in between.
The problem I encountered, which lead to this bug report, was caused 
because a new CA cert was issued for a CA, well in advance of the 
expiration of the CA's present cert, and the CA began to ship that new CA 
cert to users who get new client auth certs immediately after it was 
issued.  

I think the new CA cert should have been distributed to servers BEFORE it 
was distributed to new clients.  I'd suggest that the new CA cert not be
distributed to clients until at least several weeks after the new cert is 
issued.

As for distributing new intermediate CA certs, there is a mime type for 
distributing CA certs.  web browsers should be able to visit a web page
with a simple URL to get the new cert.  A multipart MIME email message
should suffice to distribute the new CA cert to email users.  I don't 
know whether our current and future standalone email clients (e.g. 
thunderbird) properly handle those MIME types.  We should ensure that 
they do.
Nelson :

In other words, you would advocate the second option I listed in comment 3.

Distributing certs to browsers is not a problem, it happens fairly transparently.

What I pointed out is that no good means exists today for a server to
automatically fetch and trust the new CA cert. Some sort of subscription model
would be needed. Nothing like that exists in CMS / NES and other servers, AFAIK.
Steve, please correct me if I'm wrong on this.

Unless we find some solution to this problem, what's going to keep happening is
the status quo - some users will be able to log in to a server, while other
won't, just because there is a new CA cert out there. Most users will have no
clue why. It will continue to be a very complicated problem to diagnose, since
the server administrators may not be aware that a new CA cert has been issued,
and they have no way of telling from any server log that a new CA cert is being
sent by their users. From a supportability point of view, this situation is a
nightmare.

On the other hand, if we do 3), and nobody installs the new CA cert, the server
will continue to work for all users when the old CA expires, and then stop
working for everybody at once after that date. That is a lot easier of a problem
to diagnose and fix.
I'd like to make one correction to Julien's description of the problem.  He 
says:

  It turns out that Mozilla _also_ sent the newer issuer cert, even though my
  cert doesn't chain to it - its issuing date doesn't fall within the new
  issuer validity date of  8/7/2003 to 8/7/2004 !!!!

This implementation is actually correct.  There is no requirement that the 
validity period of a certificate falls completely within the validity period 
of the (current) issuing certificate.

The relying party (the server) should either trust the newer cert (it's trust 
database has been updated), or should find the older certificate in the 
database and use that.  I believe this is Julien's suggested change to the NSS 
verification code.

Notice that allowing validity times to extend outside of the issuer's validity 
period makes trust database updates easier.  The server administrator should 
simply delete the old version of the trusted certificate, and install the new 
one.
Terry, that's true, I wasn't aware when I originally wrote the bug that this
chain was indeed valid and a full overlap of the validity of certs in the chain
wasn't required.

The problem still remains that the server rejected a valid chain in this case,
even though it should have been able to handle it by matching the leaf to its
trusted cert in the DB by virtue of the signature.

If we aren't going to fix the NSS code, another workaround exists for the CA,
which is to issue a new CA cert that is not yet valid. That CA cert can then be
disseminated to servers and marked trusted, in addition to the current one (and
not as a replacement in this case).

If clients get ahold of the new CA cert, it won't harm anything, since the
clients won't send the new CA cert until it actually becomes valid. Unless the
clients configure their system's date in the future, they would continue to be
able to login to all servers, whether those servers had the new CA cert or not.

However this isn't a true workaround for the problem, but rather modifying the
problem, since originally both the old and new CA cert had overlapping periods
starting immediately at the time of issuance of the new cert.
QA Contact: bishakhabanerjee → jason.m.reid
Assignee: wtchang → nobody
QA Contact: jason.m.reid → libraries
Priority: -- → P3
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.