All,

I was preparing a 6.0 patch for
https://issues.apache.org/bugzilla/show_bug.cgi?id=53481 (Add support
for OpenSSL SSLHonorCipherOrder) and I found a missing method SSL.hasOp
that is used in trunk and 7.0.

The javadoc for SSL.hasOp says:

    /**
     * Return true if SSL_OP_ if defined.
     * <p>
     * Currently used for testing weather the
     * SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION is supported by OpenSSL.
     * <p>
     * @param op SSL_OP to test.
     * @return true if SSL_OP is supported by OpenSSL library.
     */
    public static native boolean hasOp(int op);

Reading that, I would expect that the native method would check to see
if the OpenSSL implementation supported a particular setting. The
javadoc says that it's used to check
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, but not that it does not
support other checks.

Here's the implementation of the native method:

TCN_IMPLEMENT_CALL(jboolean, SSL, hasOp)(TCN_STDARGS, jint op)
{
#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
    if (op & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
        return JNI_TRUE;
#endif
    return JNI_FALSE;
}

That very obviously only works specifically for the
SSL_OP_ALOW_UNSAFE_LEGACY_RENEGOTIATION flag.

I'm glad I found this because I'm using the same method to check for
SSL_OP_CIPHER_SERVER_PREFERENCE -- and that call is always going to
return FALSE, so this feature doesn't actually work :(

Looking at the OpenSSL API (wow, I really miss javadoc), it doesn't
appear that there's any function that can sniff the capabilities of the
engine and check to see whether a particular option is supported.
Instead, the technique of using #ifdefs to conditionally include code
that will return TRUE seems to be the only alternative.

My addition of this feature now requires an update to tcnative :(

Since I'm going to be adding this, shall I try to add any particular
subset of SSL options that can be checked? I'm actually wondering if
checking for SSL_OP_CIPHER_SERVER_PREFERENCE is worth it, since lack of
support from the OpenSSL library is highly unlikely.

At any rate, the list of supported options appears to be documented here:
http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html#NOTES

There are only 26 documented options to check.

I'm also wondering if it wouldn't be a good idea to future-proof the
implementation of that method by having it throw an exception if you try
to check the support-status of an option that isn't known to the code.
Something like this:

TCN_IMPLEMENT_CALL(jboolean, SSL, hasOp)(TCN_STDARGS, jint op)
{
    int support = 0;

#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
    if (op & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) {
      support |= (op & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
      op ^= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
    }
#endif
#ifdef SSL_OP_FOO
    if (op & SSL_OP_FOO) {
      support |= (op & SSL_OP_FOO);
      op ^= SSL_OP_FOO; // Clear FOO
    }
#endif
#ifdef SSL_OP_BAR
    if (op & SSL_OP_BAR) {
      support |= (op & SSL_OP_BAR);
      op ^= SSL_OP_BAR; // Clear FOO
    }
#endif

    if(op) {
      char message[]
      tcn_Throw(e, 'Unsupported OpenSSL option to check: %#08lx', op);
    }

    return support == op ? JNI_TRUE : JNI_FALSE;
}

This is able to test option bitmasks that contain more than one option:
it will return true if all of them are supported and false if any one of
them is not supported. An exception will be thrown if you try to test
for an option that hasn't been coded into tcnative.

Thoughts?

-chris

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to