Mark,

On 3/30/16 3:33 PM, Mark Thomas wrote:
> On 30/03/2016 20:27, ma...@apache.org wrote:
>> Author: markt
>> Date: Wed Mar 30 19:27:29 2016
>> New Revision: 1737154
>>
>> URL: http://svn.apache.org/viewvc?rev=1737154&view=rev
>> Log:
>> Add support for obtaining the certificate chain from a Java keystore
> 
> This needs a review by someone who knows C better than I do.

See below.

> The implementation is essentially a copy/paste of setCertificateRaw with
> what looked to be the right changes to remove the unnecessary private
> key code and to call the right OpenSSL method to set the chain.
> 
> It does work - in that SSL Labs sees the full chain - but the code may
> well be terrible. I wouldn't be surprised if it leaked memory.
> 
> Once this has been reviewed and fixed, I plan to do a tc-native release
> so we can up the minimum required version in 9.0.x and 8.5.x and ship
> the next releases with the necessary tc-native code to use this feature.
> 
> Mark
> 
> 
>>
>> Modified:
>>     tomcat/native/trunk/native/src/sslcontext.c
>>     tomcat/native/trunk/xdocs/miscellaneous/changelog.xml
>>
>> Modified: tomcat/native/trunk/native/src/sslcontext.c
>> URL: 
>> http://svn.apache.org/viewvc/tomcat/native/trunk/native/src/sslcontext.c?rev=1737154&r1=1737153&r2=1737154&view=diff
>> ==============================================================================
>> --- tomcat/native/trunk/native/src/sslcontext.c (original)
>> +++ tomcat/native/trunk/native/src/sslcontext.c Wed Mar 30 19:27:29 2016
>> @@ -1051,7 +1051,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
>>      certs = d2i_X509(NULL, &tmp, lengthOfCert);
>>      if (certs == NULL) {
>>          ERR_error_string(ERR_get_error(), err);
>> -        tcn_Throw(e, "Error reading certificat (%s)", err);
>> +        tcn_Throw(e, "Error reading certificate (%s)", err);
>>          rv = JNI_FALSE;
>>          goto cleanup;
>>      }
>> @@ -1119,6 +1119,50 @@ cleanup:
>>      free(cert);
>>      return rv;
>>  }
>> +
>> +TCN_IMPLEMENT_CALL(jboolean, SSLContext, 
>> addChainCertificateRaw)(TCN_STDARGS, jlong ctx,
>> +                                                                 jbyteArray 
>> javaCert)
>> +{
>> +    jsize lengthOfCert;
>> +    unsigned char* cert;
>> +    X509 * certs;
>> +    EVP_PKEY * evp;
>> +    const unsigned char *tmp;
>> +    BIO * bio;
>> +
>> +    tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
>> +    jboolean rv = JNI_TRUE;
>> +    char err[256];
>> +
>> +    /* we get the cert contents into a byte array */
>> +    jbyte* bufferPtr = (*e)->GetByteArrayElements(e, javaCert, NULL);
>> +    lengthOfCert = (*e)->GetArrayLength(e, javaCert);
>> +    cert = malloc(lengthOfCert);
>> +    memcpy(cert, bufferPtr, lengthOfCert);
>> +    (*e)->ReleaseByteArrayElements(e, javaCert, bufferPtr, 0);

Since bufferPtr is the byte array you want to use, you can probably just
use that directly for the call to d2i_x509(). I think the
malloc/memcpy/free is not necessary.

Obviously, don't call ReleaseByteArray until after calling d2i_509.

>> +
>> +    UNREFERENCED(o);
>> +    TCN_ASSERT(ctx != 0);
>> +
>> +    tmp = (const unsigned char *)cert;
>> +    certs = d2i_X509(NULL, &tmp, lengthOfCert);
>> +    if (certs == NULL) {
>> +        ERR_error_string(ERR_get_error(), err);
>> +        tcn_Throw(e, "Error reading certificate (%s)", err);
>> +        rv = JNI_FALSE;
>> +        goto cleanup;
>> +    }
>> +
>> +    if (SSL_CTX_add0_chain_cert(c->ctx, certs) <= 0) {
>> +        ERR_error_string(ERR_get_error(), err);
>> +        tcn_Throw(e, "Error setting certificate (%s)", err);
>> +        rv = JNI_FALSE;
>> +    }
>> +
>> +cleanup:
>> +    free(cert);
>> +    return rv;
>> +}

You could probably avoid the label/goto with a slight more complicated
conditional structure, but I don't see a particular reason to do so.

-chris

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to