Hi,

I'm back from vacation (and of course something went wrong in production
during my absence...)

As far as I can see we have had a race condition between two certificate
issuance operations.

Setting:
1 User A requested a certificate via a "Basic Request"
2 User B requested a certificate via a "Server Request"
3 both requests were approved
4 Certificate A was issued
5 Issuance of certificate B failed; the CA complains that the public
  key has already been used.

I assume that 4 and 5 were happening simultaneously, causing a race
condition. What happened was that the certificate issuance fetched
the request, determined the (likely) serial number of the next
certificate (by looking at the serial file) and wrote the request
to a file with this number.
If this happens in two distinct instances before the first certificate
is issues, the first request file is overwritten with the second.

Let's have a look at the code (0.9.2 branch):

lib/functions/crypto-utils.lib:

sub crypto_write_tmp_csr
{
    our ($errno, $errval, $tools);
    my $csr = $_[0];

    my $tmpdir = getRequired ('TempDir');
    my $ser    = crypto_get_next_cert_serial ();

    ##// Let's save the request body to a temp file
    if (not $tools->saveFile( FILENAME => "$tmpdir/${ser}.req",
                              DATA     => $csr->getParsed()->{BODY}."\n"
)) ...

and

sub crypto_create_cert
{
    our ($errno, $errval, $tools, $cryptoShell);
...
    my $ser         = crypto_get_next_cert_serial ();
...
    if ($days or $notafter or $notbefore) {
        ## Issue the Certificate with individual lifetime
        if ( not $token->issueCert(
                         REQFILE     => "$tmpdir/${ser}.req",
...


If I am not mistaken, it is dangerous to write the request file
to a file that is based on the assumed number of the next certificate,
this extends the time frame in which a race condition with OpenSSL
cert issuance can happen.
At least the request file should be written to a unique temp file
here.

With the existing implementation it is very hard to avoid race
conditions, because the OpenSSL index.txt and serial files are
actually used by OpenCA. So there is little we can do in 0.9.2, I think.

I have had a look at the code in CVS HEAD and it seems to me that
the same or a similar problem is still there, but I think we can
improve the situation here:

Always write temporary request files to true temporary files unrelated
to the assumed serial number (0.9.2 and HEAD)

openssl.txt is already cleared before issuance, but this might
still lead to race conditions when issuing to certs with identical
DN. (HEAD)
serial is read and written by OpenSSL and might also lead to race
conditions.

How about the following approach:

Before each cert issuance do the following:
1 write request file to a unique temp file
2 create an empty unique temp file (index.txt dummy)
3a set a mutex
3b get the next serial number from the *database*
3c create a unique temp file (serial dummy) and write the expected
   serial number to the file
4 copy the required openssl config file to a temp file and change
  the 'database' entry to the file created in 2 and the 'serial'
  entry to the file created in 3.
5 issue the certificate with the temporary config file
6 clear the mutex

I don't think we can do without the mutex without possibly creating
'holes' in the serial number sequence (if issuance for one certificate
fails but succeeds for a second that is processed simultaneously).
If we are ready to accept holes in the sequence, we can use a (database)
sequence for the serial number instead of the mutex. This is obviously
not an issue for CAs that use "concealed" (i. e. random) serial numbers.

Ideas, comments?

Anything we can do in this regard for 0.9.2?

cu

Martin




-------------------------------------------------------
This SF.Net email is sponsored by the 'Do More With Dual!' webinar happening
July 14 at 8am PDT/11am EDT. We invite you to explore the latest in dual
core and dual graphics technology at this free one hour event hosted by HP,
AMD, and NVIDIA.  To register visit http://www.hp.com/go/dualwebinar
_______________________________________________
OpenCA-Devel mailing list
OpenCA-Devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openca-devel

Reply via email to