/*
 * Copyright (c) 2015, 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
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.ssl;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Objects;
import javax.net.ssl.SSLException;

/*
 * RFC6961 defines the TLS extension,"status_request_v2" (type 0x5),
 * which allows the client to request that the server perform OCSP
 * on the client's behalf.
 *
 * The RFC defines an CertStatusReqItemV2 structure:
 *
 *      struct {
 *          CertificateStatusType status_type;
 *          uint16 request_length;
 *          select (status_type) {
 *              case ocsp: OCSPStatusRequest;
 *              case ocsp_multi: OCSPStatusRequest;
 *          } request;
 *      } CertificateStatusRequestItemV2;
 *
 *      enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType;
 */

final class CertStatusReqItemV2 {

    private final StatusRequestType statReqType;
    private final StatusRequest request;

    
Construct a CertStatusReqItemV2 object using a type value and empty ResponderId and Extension lists.
Params:
  • reqType – the type of request (e.g. ocsp). A null value is not allowed.
  • statReq – the StatusRequest object used to provide the encoding for this CertStatusReqItemV2. A null value is not allowed.
Throws:
/** * Construct a {@code CertStatusReqItemV2} object using a type value * and empty ResponderId and Extension lists. * * @param reqType the type of request (e.g. ocsp). A {@code null} value * is not allowed. * @param statReq the {@code StatusRequest} object used to provide the * encoding for this {@code CertStatusReqItemV2}. A {@code null} * value is not allowed. * * @throws IllegalArgumentException if the provided {@code StatusRequest} * does not match the type. * @throws NullPointerException if either the reqType or statReq arguments * are {@code null}. */
CertStatusReqItemV2(StatusRequestType reqType, StatusRequest statReq) { statReqType = Objects.requireNonNull(reqType, "Unallowed null value for status_type"); request = Objects.requireNonNull(statReq, "Unallowed null value for request"); // There is currently only one known status type (OCSP) // We can add more clauses to cover other types in the future if (statReqType.equals(StatusRequestType.OCSP) || statReqType.equals(StatusRequestType.OCSP_MULTI)) { if (!(statReq instanceof OCSPStatusRequest)) { throw new IllegalArgumentException("StatusRequest not " + "of type OCSPStatusRequest"); } } }
Construct a CertStatusReqItemV2 object from encoded bytes
Params:
  • requestBytes – the encoded bytes for the CertStatusReqItemV2
Throws:
/** * Construct a {@code CertStatusReqItemV2} object from encoded bytes * * @param requestBytes the encoded bytes for the {@code CertStatusReqItemV2} * * @throws IOException if any decoding errors take place * @throws IllegalArgumentException if the parsed reqType value is not a * supported status request type. */
CertStatusReqItemV2(byte[] reqItemBytes) throws IOException { ByteBuffer reqBuf = ByteBuffer.wrap(reqItemBytes); statReqType = StatusRequestType.get(reqBuf.get()); int requestLength = Short.toUnsignedInt(reqBuf.getShort()); if (requestLength == reqBuf.remaining()) { byte[] statReqBytes = new byte[requestLength]; reqBuf.get(statReqBytes); if (statReqType == StatusRequestType.OCSP || statReqType == StatusRequestType.OCSP_MULTI) { request = new OCSPStatusRequest(statReqBytes); } else { request = new UnknownStatusRequest(statReqBytes); } } else { throw new SSLException("Incorrect request_length: " + "Expected " + reqBuf.remaining() + ", got " + requestLength); } }
Construct an CertStatusReqItemV2 object from data read from a HandshakeInputStream
Params:
  • s – the HandshakeInputStream providing the encoded data
Throws:
/** * Construct an {@code CertStatusReqItemV2} object from data read from * a {@code HandshakeInputStream} * * @param s the {@code HandshakeInputStream} providing the encoded data * * @throws IOException if any decoding errors happen during object * construction. * @throws IllegalArgumentException if the parsed reqType value is not a * supported status request type. */
CertStatusReqItemV2(HandshakeInStream in) throws IOException { statReqType = StatusRequestType.get(in.getInt8()); int requestLength = in.getInt16(); if (statReqType == StatusRequestType.OCSP || statReqType == StatusRequestType.OCSP_MULTI) { request = new OCSPStatusRequest(in); } else { request = new UnknownStatusRequest(in, requestLength); } }
Return the length of this CertStatusReqItemV2 in its encoded form
Returns:the encoded length of this CertStatusReqItemV2
/** * Return the length of this {@code CertStatusReqItemV2} in its encoded form * * @return the encoded length of this {@code CertStatusReqItemV2} */
int length() { // The length is the the status type (1 byte) + the request length // field (2 bytes) + the StatusRequest data length. return request.length() + 3; }
Send the encoded CertStatusReqItemV2 through a HandshakeOutputStream
Params:
  • s – the HandshakeOutputStream used to send the encoded data
Throws:
  • IOException – if any errors occur during the encoding process
/** * Send the encoded {@code CertStatusReqItemV2} through a * {@code HandshakeOutputStream} * * @param s the {@code HandshakeOutputStream} used to send the encoded data * * @throws IOException if any errors occur during the encoding process */
void send(HandshakeOutStream s) throws IOException { s.putInt8(statReqType.id); s.putInt16(request.length()); request.send(s); }
Create a string representation of this CertStatusReqItemV2
Returns:the string representation of this CertStatusReqItemV2
/** * Create a string representation of this {@code CertStatusReqItemV2} * * @return the string representation of this {@code CertStatusReqItemV2} */
@Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("CertStatusReqItemV2: ").append(statReqType).append(", "); sb.append(request.toString()); return sb.toString(); }
Return the type field for this CertStatusReqItemV2
Returns:the StatusRequestType for this extension.
/** * Return the type field for this {@code CertStatusReqItemV2} * * @return the {@code StatusRequestType} for this extension. */
StatusRequestType getType() { return statReqType; }
Get the underlying StatusRequest for this CertStatusReqItemV2
Returns:the StatusRequest
/** * Get the underlying {@code StatusRequest} for this * {@code CertStatusReqItemV2} * * @return the {@code StatusRequest} */
StatusRequest getRequest() { return request; } }