Skip to content

Commit

Permalink
8328638: Fallback option for POST-only OCSP requests
Browse files Browse the repository at this point in the history
8329213: Better validation for com.sun.security.ocsp.useget option

Reviewed-by: serb
Backport-of: 614db2ea9e10346475eef34629eab54878aa482d
  • Loading branch information
shipilev committed Apr 5, 2024
1 parent 31ba7e0 commit 533fac6
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Locale;
import java.util.Properties;
import sun.security.util.Debug;

/**
* A convenience class for retrieving the string value of a system
Expand Down Expand Up @@ -159,4 +161,37 @@ public Properties run() {
);
}
}

/**
* Convenience method for fetching System property values that are booleans.
*
* @param prop the name of the System property
* @param def a default value
* @param dbg a Debug object, if null no debug messages will be sent
*
* @return a boolean value corresponding to the value in the System property.
* If the property value is neither "true" or "false", the default value
* will be returned.
*/
public static boolean privilegedGetBooleanProp(String prop, boolean def, Debug dbg) {
String rawPropVal = privilegedGetProperty(prop, "");
if ("".equals(rawPropVal)) {
return def;
}

String lower = rawPropVal.toLowerCase(Locale.ROOT);
if ("true".equals(lower)) {
return true;
} else if ("false".equals(lower)) {
return false;
} else {
if (dbg != null) {
dbg.println("Warning: Unexpected value for " + prop +
": " + rawPropVal +
". Using default value: " + def);
}
return def;
}
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -44,6 +44,7 @@
import java.util.Map;

import sun.security.action.GetIntegerAction;
import sun.security.action.GetPropertyAction;
import sun.security.util.Debug;
import sun.security.util.Event;
import sun.security.util.IOUtils;
Expand Down Expand Up @@ -79,6 +80,28 @@ public final class OCSP {
*/
private static final int CONNECT_TIMEOUT = initializeTimeout();

/**
* Boolean value indicating whether OCSP client can use GET for OCSP
* requests. There is an ambiguity in RFC recommendations.
*
* RFC 5019 says a stronger thing, "MUST":
* "When sending requests that are less than or equal to 255 bytes in
* total (after encoding) including the scheme and delimiters (http://),
* server name and base64-encoded OCSPRequest structure, clients MUST
* use the GET method (to enable OCSP response caching)."
*
* RFC 6960 says a weaker thing, "MAY":
* "HTTP-based OCSP requests can use either the GET or the POST method to
* submit their requests. To enable HTTP caching, small requests (that
* after encoding are less than 255 bytes) MAY be submitted using GET."
*
* For performance reasons, we default to stronger behavior. But this
* option also allows to fallback to weaker behavior in case of compatibility
* problems.
*/
private static final boolean USE_GET = initializeBoolean(
"com.sun.security.ocsp.useget", true);

/**
* Initialize the timeout length by getting the OCSP timeout
* system property. If the property has not been set, or if its
Expand All @@ -96,6 +119,15 @@ private static int initializeTimeout() {
return tmp * 1000;
}

private static boolean initializeBoolean(String prop, boolean def) {
boolean value =
GetPropertyAction.privilegedGetBooleanProp(prop, def, debug);
if (debug != null) {
debug.println(prop + " set to " + value);
}
return value;
}

private OCSP() {}


Expand Down Expand Up @@ -244,7 +276,7 @@ public static byte[] getOCSPBytes(List<CertId> certIds, URI responderURI,
encodedGetReq.append(URLEncoder.encode(
Base64.getEncoder().encodeToString(bytes), "UTF-8"));

if (encodedGetReq.length() <= 255) {
if (USE_GET && encodedGetReq.length() <= 255) {
url = new URL(encodedGetReq.toString());
con = (HttpURLConnection)url.openConnection();
con.setDoOutput(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -23,14 +23,16 @@

/**
* @test
* @bug 8179503
* @bug 8179503 8328638
* @summary Java should support GET OCSP calls
* @library /javax/net/ssl/templates /java/security/testlibrary
* @build SimpleOCSPServer
* @modules java.base/sun.security.util
* java.base/sun.security.provider.certpath
* java.base/sun.security.x509
* @run main/othervm GetAndPostTests
* @run main/othervm -Dcom.sun.security.ocsp.useget=false GetAndPostTests
* @run main/othervm -Dcom.sun.security.ocsp.useget=foo GetAndPostTests
*/

import java.io.ByteArrayInputStream;
Expand Down
11 changes: 10 additions & 1 deletion test/jdk/java/security/testlibrary/SimpleOCSPServer.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -704,6 +704,9 @@ public CRLReason getRevocationReason() {
* responses.
*/
private class OcspHandler implements Runnable {
private final boolean USE_GET =
!System.getProperty("com.sun.security.ocsp.useget", "").equals("false");

private final Socket sock;
InetSocketAddress peerSockAddr;

Expand Down Expand Up @@ -876,6 +879,12 @@ private LocalOcspRequest parseHttpOcspPost(InputStream inStream)
// Okay, make sure we got what we needed from the header, then
// read the remaining OCSP Request bytes
if (properContentType && length >= 0) {
if (USE_GET && length <= 255) {
// Received a small POST request. Check that our client code properly
// handled the relevant flag. We expect small GET requests, unless
// explicitly disabled.
throw new IOException("Should have received small GET, not POST.");
}
byte[] ocspBytes = new byte[length];
inStream.read(ocspBytes);
return new LocalOcspRequest(ocspBytes);
Expand Down
Loading

1 comment on commit 533fac6

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.