Tim,

On 4/14/14, 10:45 PM, Tim Whittington wrote:
> 
> On 15/04/2014, at 1:14 pm, schu...@apache.org wrote:
> 
>> Author: schultz
>> Date: Tue Apr 15 01:14:40 2014
>> New Revision: 1587379
>>
>> URL: http://svn.apache.org/r1587379
>> Log:
>> Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56027
>> Add more nuanced support for entering/requiring FIPS mode when using APR 
>> connector.
>>
>> Modified:
>>  tomcat/trunk/java/org/apache/catalina/core/AprLifecycleListener.java
>>  tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties
>>  tomcat/trunk/java/org/apache/tomcat/jni/SSL.java
>>  tomcat/trunk/webapps/docs/config/listeners.xml
>>
>> Modified: 
>> tomcat/trunk/java/org/apache/catalina/core/AprLifecycleListener.java
>> URL: 
>> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/AprLifecycleListener.java?rev=1587379&r1=1587378&r2=1587379&view=diff
>> ==============================================================================
>> --- tomcat/trunk/java/org/apache/catalina/core/AprLifecycleListener.java 
>> (original)
>> +++ tomcat/trunk/java/org/apache/catalina/core/AprLifecycleListener.java Tue 
>> Apr 15 01:14:40 2014
>> @@ -70,6 +70,18 @@ public class AprLifecycleListener
>>   protected static boolean aprInitialized = false;
>>   protected static boolean aprAvailable = false;
>>   protected static boolean fipsModeActive = false;
>> +    /**
>> +     * FIPS_mode documentation states that the return value will be
>> +     * whatever value was originally passed-in to FIPS_mode_set().
>> +     * FIPS_mode_set docs say the argument should be non-zero to enter
>> +     * FIPS mode, and that upon success, the return value will be the
>> +     * same as the argument passed-in. Docs also highly recommend
>> +     * that the value "1" be used "to avoid compatibility issues".
>> +     * In order to avoid the argument and check-value from getting out
>> +     * of sync for some reason, we are using the class constant
>> +     * FIPS_ON here.
>> +     */
>> +    private static final int FIPS_ON = 1;
> 
> 
> This looks like it belongs in SSL (as one of the valid return values of 
> SSL.fipsModeGet).

Fair enough.

> Also, does FIPS_mode() always return 1 if FIPS mode is enabled at boot (I see 
> there’s no adaptation of the return code in the TCN imll).

FIPS_mode() is documented to return whatever was passed to it before.
There is no other information that I could find available. I'm willing
to bet that everyone always uses "1" since the API basically says "use 1".

>>   protected static final Object lock = new Object();
>>
>> @@ -110,7 +122,7 @@ public class AprLifecycleListener
>>                   }
>>               }
>>               // Failure to initialize FIPS mode is fatal
>> -                if ("on".equalsIgnoreCase(FIPSMode) && !isFIPSModeActive()) 
>> {
>> +                if (!(null == FIPSMode || "off".equalsIgnoreCase(FIPSMode)) 
>> && !isFIPSModeActive()) {
>>                   Error e = new Error(
>>                           sm.getString("aprListener.initializeFIPSFailed"));
>>                   // Log here, because thrown error might be not logged
>> @@ -252,13 +264,59 @@ public class AprLifecycleListener
>>       method = clazz.getMethod(methodName, paramTypes);
>>       method.invoke(null, paramValues);
>>
>> -        if("on".equalsIgnoreCase(FIPSMode)) {
>> +        final boolean enterFipsMode;
>> +
>> +        if("on".equalsIgnoreCase(FIPSMode)
>> +           || "require".equalsIgnoreCase(FIPSMode)) {
>> +            // FIPS_mode documentation states that the return value will be
>> +            // whatever value was originally passed-in to FIPS_mode_set().
>> +            // FIPS_mode_set docs say the argument should be non-zero to 
>> enter
>> +            // FIPS mode, and that upon success, the return value will be 
>> the
>> +            // same as the argument passed-in. Docs also highly recommend
>> +            // that the value "1" be used "to avoid compatibility issues".
>> +            // In order to avoid the argument and check-value from getting 
>> out
>> +            // of sync for some reason, we are using the class constant
>> +            // FIPS_ON here.
>> +            final int fipsModeState = SSL.fipsModeGet();
> 
> 
> I don’t think this needs to be documented twice, and maybe not at all?
> Aren’t we already handling the FIPS_* ‘peculiarities' in TCN so that 
> SSL.fipsModeGet() has a sane 0/1 return code?

No. Other code could call FIPS_mode_set() and thus the return value
might be different. Yes, this is documented identically in multiple
places. I didn't want anyone to say "oh, having a constant for (int)1 is
stupid: let's just use 1 and be done with it" without actually reading
why there is a constant being used there.

>> +
>> +            if(log.isDebugEnabled())
>> +                log.debug(sm.getString("aprListener.currentFIPSMode",
>> +                                       Integer.valueOf(fipsModeState)));
>> +
>> +            // Return values: 0=Not in FIPS mode, 1=In FIPS mode,
>> +            // exception if FIPS totally unavailable
>> +            enterFipsMode = 1 != fipsModeState;
>> +
>> +            if("on".equalsIgnoreCase(FIPSMode)) {
>> +                if(!enterFipsMode)
>> +                    
>> log.info(sm.getString("aprListener.skipFIPSInitialization"));
>> +            } else if("require".equalsIgnoreCase(FIPSMode)) {
>> +                if(enterFipsMode) {
>> +                    String message = 
>> sm.getString("aprListener.alreadyInFIPSMode");
>> +                    log.error(message);
>> +                    throw new IllegalStateException(message);
>> +                }
>> +            }
>> +        }
>> +        else if("enter".equalsIgnoreCase(FIPSMode)) {
>> +            enterFipsMode = true;
>> +        } else
>> +            enterFipsMode = false;
>> +
>> +        if(enterFipsMode) {
>>           log.info(sm.getString("aprListener.initializingFIPS"));
>>
>> -            int result = SSL.fipsModeSet(1);
>> +            // FIPS_mode_set docs say the argument should be non-zero to 
>> enter
>> +            // FIPS mode, and that upon success, the return value will be 
>> the
>> +            // same as the argument passed-in. Docs also highly recommend
>> +            // that the value "1" be used "to avoid compatibility issues".
>> +            // In order to avoid the argument and check-value from getting 
>> out
>> +            // of sync for some reason, we are using the class constant
>> +            // FIPS_ON here.
> 
> 
> Again, these docs look like they belong on SSL.fipsModeSet or in the TCN 
> implementation of that.

This can't be in TCN because the Java code needs the constant value. I
suppose I could call a function in tcnative to get the value of "1" but
that seems a bit of overkill and I'd have to wait for yet another
tcnative release to get this out there.

>> +            final int result = SSL.fipsModeSet(FIPS_ON);
>>
>> -            // success is defined as return value = 1
>> -            if(1 == result) {
>> +            // success is defined as return value = last argument to 
>> FIPS_mode_set()
>> +            if(FIPS_ON == result) {
>>               fipsModeActive = true;
>>
>>               log.info(sm.getString("aprListener.initializeFIPSSuccess"));
>>
>> Modified: tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties
>> URL: 
>> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties?rev=1587379&r1=1587378&r2=1587379&view=diff
>> ==============================================================================
>> --- tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties 
>> (original)
>> +++ tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties Tue 
>> Apr 15 01:14:40 2014
>> @@ -57,6 +57,9 @@ aprListener.aprDestroy=Failed shutdown o
>> aprListener.sslInit=Failed to initialize the SSLEngine.
>> aprListener.tcnValid=Loaded APR based Apache Tomcat Native library {0} using 
>> APR version {1}.
>> aprListener.flags=APR capabilities: IPv6 [{0}], sendfile [{1}], accept 
>> filters [{2}], random [{3}].
>> +aprListener.currentFIPSMode=Current FIPS mode: {0}
>> +aprListener.skipFIPSInitialization=Already in FIPS mode; skipping FIPS 
>> initialization.
>> +aprListener.alreadyInFIPSMode=AprLifecycleListener requested to force 
>> entering FIPS mode, but FIPS mode was already enabled.
>> aprListener.initializingFIPS=Initializing FIPS mode...
>> aprListener.initializeFIPSSuccess=Successfully entered FIPS mode
>> aprListener.initializeFIPSFailed=Failed to enter FIPS mode
>>
>> Modified: tomcat/trunk/java/org/apache/tomcat/jni/SSL.java
>> URL: 
>> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/jni/SSL.java?rev=1587379&r1=1587378&r2=1587379&view=diff
>> ==============================================================================
>> --- tomcat/trunk/java/org/apache/tomcat/jni/SSL.java (original)
>> +++ tomcat/trunk/java/org/apache/tomcat/jni/SSL.java Tue Apr 15 01:14:40 2014
>> @@ -230,6 +230,14 @@ public final class SSL {
>>   public static native int initialize(String engine);
>>
>>   /**
>> +     * Get the status of FIPS Mode.
>> +     *
>> +     * @return 0 If OpenSSL is not in FIPS mode, 1 if OpenSSL is in FIPS 
>> Mode.
>> +     * @throws Exception If tcnative was not compiled with FIPS Mode 
>> available.
>> +     */
>> +    public static native int fipsModeGet();
>> +
>> +    /**
>>    * Enable/Disable FIPS Mode.
>>    *
>>    * @param mode 1 - enable, 0 - disable
>>
>> Modified: tomcat/trunk/webapps/docs/config/listeners.xml
>> URL: 
>> http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/listeners.xml?rev=1587379&r1=1587378&r2=1587379&view=diff
>> ==============================================================================
>> --- tomcat/trunk/webapps/docs/config/listeners.xml (original)
>> +++ tomcat/trunk/webapps/docs/config/listeners.xml Tue Apr 15 01:14:40 2014
>> @@ -112,12 +112,22 @@
>>     </attribute>
>>
>>     <attribute name="FIPSMode" required="false">
>> -        <p>Set to <code>on</code> to instruct OpenSSL to go into FIPS mode.
>> +        <p>Set to <code>on</code> to request that OpenSSL be in FIPS mode
>> +        (if OpenSSL is already in FIPS mode, it will remain in FIPS mode).
>> +        Set to <code>enter</code> to force OpenSSL to enter FIPS mode (an 
>> error
>> +        will occur if OpenSSL is already in FIPS mode).
>> +        Set to <code>require</code> to require that OpenSSL <i>already</i> 
>> be
>> +        in FIPS mode (an error will occur if OpenSSL is not already in FIPS
>> +        mode).
>>       FIPS mode <em>requires you to have a FIPS-capable OpenSSL library which
>>       you must build yourself</em>.
>> -        FIPS mode also requires Tomcat native library version 1.1.23 or 
>> later,
>> -        which <em>must be built against the FIPS-compatible OpenSSL</em> 
>> library.
>> -        If this attribute is "on", <b>SSLEngine</b> must be enabled as well.
>> +        <code>FIPSMode="on"</code> or <code>FIPSMode="require"</code> 
>> requires
>> +        Tomcat native library version 1.1.30 or later, while
>> +        <code>FIPSMode="enter"</code> can probably be done with Tomcat 
>> native
>> +        library version 1.2.23 or later -- either of which <em>must be built
>> +        against the FIPS-compatible OpenSSL</em> library.
>> +        If this attribute is set to any of the above values, 
>> <b>SSLEngine</b>
>> +        must be enabled as well for any effect.
>>       The default value is <code>off</code>.</p>
>>     </attribute>
>>
>>
> 
> 
> Why the ‘enter’ and ‘require’ options?

Please read the enhancement request where I've described the reasoning
behind this.

> I can understand ‘on’ == ‘I want FIPS mode’, but I don’t get how
> ‘require’ == ‘I require FIPS mode turned on before Tomcat starts’
> affects Tomcat, and I don’t get how ‘enter’ == ‘Try FIPS mode or fail
> if already set’ is useful.
> 
> Also, it seems inconsistent given the above that ‘off’ does nothing
> if TCN is already in FIPS mode at startup?

I can change that if you feel it is important.

> Current behaviour would appear to be ‘on’ == ‘make sure it’s on *with
> bug’, ‘off’ == ‘don’t really care, will take whatever’?

Correct.

> Would on/off still be sufficient, or do we need the four ‘require’,
> ‘support’, ‘not supported’, ‘initiate’ options ala transactions?

I like being able to ensure that FIPS mode was already enabled.

-chris

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to