From be4bdf254e38f31d33a4f5bb8ceda07f29de3ab9 Mon Sep 17 00:00:00 2001 From: zhouyang Date: Tue, 25 Apr 2023 16:50:09 +0800 Subject: [PATCH] The new sun/security/provider/certpath/OCSP/OCSPNoContentLength appears to be failing due to a SocketException occurring when the client CertPathValidator tries to perform a OCSP lookup on the certificate. Added parseHttpOcspGet --- .../testlibrary/SimpleOCSPServer.java | 92 +++++++++++++++---- 1 file changed, 75 insertions(+), 17 deletions(-) diff --git a/jdk/test/java/security/testlibrary/SimpleOCSPServer.java b/jdk/test/java/security/testlibrary/SimpleOCSPServer.java index 4901e6f26..d9f07c2f3 100644 --- a/jdk/test/java/security/testlibrary/SimpleOCSPServer.java +++ b/jdk/test/java/security/testlibrary/SimpleOCSPServer.java @@ -324,12 +324,13 @@ public class SimpleOCSPServer { * @return the hexdump of the byte array */ private static String dumpHexBytes(byte[] data) { - return dumpHexBytes(data, 16, "\n", " "); + return dumpHexBytes(data, data.length, 16, "\n", " "); } /** * - * @param data the array of bytes to dump to stdout. + * @param data the array of bytes to dump to stdout + * @param dataLen the length of the data to be displayed * @param itemsPerLine the number of bytes to display per line * if the {@code lineDelim} character is blank then all bytes will be * printed on a single line. @@ -338,11 +339,11 @@ public class SimpleOCSPServer { * * @return The hexdump of the byte array */ - private static String dumpHexBytes(byte[] data, int itemsPerLine, - String lineDelim, String itemDelim) { + private static String dumpHexBytes(byte[] data, int dataLen, + int itemsPerLine, String lineDelim, String itemDelim) { StringBuilder sb = new StringBuilder(); if (data != null) { - for (int i = 0; i < data.length; i++) { + for (int i = 0; i < dataLen; i++) { if (i % itemsPerLine == 0 && i != 0) { sb.append(lineDelim); } @@ -492,6 +493,7 @@ public class SimpleOCSPServer { throws NoSuchAlgorithmException { if (!started) { sigAlgId = AlgorithmId.get(algName); + log("Signature algorithm set to " + sigAlgId.getName()); } } @@ -708,20 +710,23 @@ public class SimpleOCSPServer { peerSockAddr = (InetSocketAddress)ocspSocket.getRemoteSocketAddress(); log("Received incoming connection from " + peerSockAddr); + + // Read in the first line which will be the request line. + // This will be tokenized so we know if we are dealing with + // a GET or POST. String[] headerTokens = readLine(in).split(" "); LocalOcspRequest ocspReq = null; LocalOcspResponse ocspResp = null; ResponseStatus respStat = ResponseStatus.INTERNAL_ERROR; try { if (headerTokens[0] != null) { - switch (headerTokens[0]) { + switch (headerTokens[0].toUpperCase()) { case "POST": ocspReq = parseHttpOcspPost(in); break; case "GET": - // req = parseHttpOcspGet(in); - // TODO implement the GET parsing - throw new IOException("GET method unsupported"); + ocspReq = parseHttpOcspGet(headerTokens, in); + break; default: respStat = ResponseStatus.MALFORMED_REQUEST; throw new IOException("Not a GET or POST"); @@ -754,6 +759,9 @@ public class SimpleOCSPServer { ocspResp = new LocalOcspResponse(respStat); } sendResponse(out, ocspResp); + out.flush(); + + log("Closing " + ocspSocket); } catch (IOException | CertificateException exc) { err(exc); } @@ -843,6 +851,47 @@ public class SimpleOCSPServer { } } + /** + * Parse the incoming HTTP GET of an OCSP Request. + * + * @param headerTokens the individual String tokens from the first + * line of the HTTP GET. + * @param inStream the input stream from the socket bound to this + * {@code OcspHandler}. + * + * @return the OCSP Request as a {@code LocalOcspRequest} + * + * @throws IOException if there are network related issues or problems + * occur during parsing of the OCSP request. + * @throws CertificateException if one or more of the certificates in + * the OCSP request cannot be read/parsed. + */ + private LocalOcspRequest parseHttpOcspGet(String[] headerTokens, + InputStream inStream) throws IOException, CertificateException { + // Before we process the remainder of the GET URL, we should drain + // the InputStream of any other header data. We (for now) won't + // use it, but will display the contents if logging is enabled. + boolean endOfHeader = false; + while (!endOfHeader) { + String[] lineTokens = readLine(inStream).split(":", 2); + // We expect to see a type and value pair delimited by a colon. + if (lineTokens[0].isEmpty()) { + endOfHeader = true; + } else if (lineTokens.length == 2) { + log(String.format("ReqHdr: %s: %s", lineTokens[0].trim(), + lineTokens[1].trim())); + } else { + // A colon wasn't found and token 0 should be the whole line + log("ReqHdr: " + lineTokens[0].trim()); + } + } + + // We have already established headerTokens[0] to be "GET". + // We need to strip any leading "/" off before decoding. + return new LocalOcspRequest(URLDecoder.decode(headerTokens[1] + .replaceAll("/", ""), "UTF-8")); + } + /** * Read a line of text that is CRLF-delimited. * @@ -1154,10 +1203,14 @@ public class SimpleOCSPServer { sb.append("CertId, Algorithm = "); sb.append(cid.getHashAlgorithm()).append("\n"); sb.append("\tIssuer Name Hash: "); - sb.append(dumpHexBytes(cid.getIssuerNameHash(), 256, "", "")); + byte[] cidHashBuf = cid.getIssuerNameHash(); + sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length, + 256, "", "")); sb.append("\n"); sb.append("\tIssuer Key Hash: "); - sb.append(dumpHexBytes(cid.getIssuerKeyHash(), 256, "", "")); + cidHashBuf = cid.getIssuerKeyHash(); + sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length, + 256, "", "")); sb.append("\n"); sb.append("\tSerial Number: ").append(cid.getSerialNumber()); if (!extensions.isEmpty()) { @@ -1328,13 +1381,14 @@ public class SimpleOCSPServer { basicORItemStream.write(tbsResponseBytes); try { - sigAlgId.derEncode(basicORItemStream); - // Create the signature - Signature sig = Signature.getInstance(sigAlgId.getName()); - sig.initSign(signerKey); + Signature sig = SignatureUtil.fromKey( + sigAlgId.getName(), signerKey, (Provider)null); sig.update(tbsResponseBytes); signature = sig.sign(); + // Rewrite signAlg, RSASSA-PSS needs some parameters. + sigAlgId = SignatureUtil.fromSignature(sig, signerKey); + sigAlgId.encode(basicORItemStream); basicORItemStream.putBitString(signature); } catch (GeneralSecurityException exc) { err(exc); @@ -1496,10 +1550,14 @@ public class SimpleOCSPServer { sb.append("CertId, Algorithm = "); sb.append(certId.getHashAlgorithm()).append("\n"); sb.append("\tIssuer Name Hash: "); - sb.append(dumpHexBytes(certId.getIssuerNameHash(), 256, "", "")); + byte[] cidHashBuf = certId.getIssuerNameHash(); + sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length, + 256, "", "")); sb.append("\n"); sb.append("\tIssuer Key Hash: "); - sb.append(dumpHexBytes(certId.getIssuerKeyHash(), 256, "", "")); + cidHashBuf = certId.getIssuerKeyHash(); + sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length, + 256, "", "")); sb.append("\n"); sb.append("\tSerial Number: ").append(certId.getSerialNumber()); sb.append("\n"); -- Gitee