src/java.base/share/classes/sun/security/ssl/CertStatusReqItemV2.java
changeset 50768 68fa3d4026ea
parent 50767 356eaea05bf0
child 50769 1bf8f9840705
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
     1 /*
       
     2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.security.ssl;
       
    27 
       
    28 import java.io.IOException;
       
    29 import java.nio.ByteBuffer;
       
    30 import java.util.Objects;
       
    31 import javax.net.ssl.SSLException;
       
    32 
       
    33 /*
       
    34  * RFC6961 defines the TLS extension,"status_request_v2" (type 0x5),
       
    35  * which allows the client to request that the server perform OCSP
       
    36  * on the client's behalf.
       
    37  *
       
    38  * The RFC defines an CertStatusReqItemV2 structure:
       
    39  *
       
    40  *      struct {
       
    41  *          CertificateStatusType status_type;
       
    42  *          uint16 request_length;
       
    43  *          select (status_type) {
       
    44  *              case ocsp: OCSPStatusRequest;
       
    45  *              case ocsp_multi: OCSPStatusRequest;
       
    46  *          } request;
       
    47  *      } CertificateStatusRequestItemV2;
       
    48  *
       
    49  *      enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType;
       
    50  */
       
    51 
       
    52 final class CertStatusReqItemV2 {
       
    53 
       
    54     private final StatusRequestType statReqType;
       
    55     private final StatusRequest request;
       
    56 
       
    57     /**
       
    58      * Construct a {@code CertStatusReqItemV2} object using a type value
       
    59      *      and empty ResponderId and Extension lists.
       
    60      *
       
    61      * @param reqType the type of request (e.g. ocsp).  A {@code null} value
       
    62      *      is not allowed.
       
    63      * @param statReq the {@code StatusRequest} object used to provide the
       
    64      *      encoding for this {@code CertStatusReqItemV2}.  A {@code null}
       
    65      *      value is not allowed.
       
    66      *
       
    67      * @throws IllegalArgumentException if the provided {@code StatusRequest}
       
    68      *      does not match the type.
       
    69      * @throws NullPointerException if either the reqType or statReq arguments
       
    70      *      are {@code null}.
       
    71      */
       
    72     CertStatusReqItemV2(StatusRequestType reqType, StatusRequest statReq) {
       
    73         statReqType = Objects.requireNonNull(reqType,
       
    74                 "Unallowed null value for status_type");
       
    75         request = Objects.requireNonNull(statReq,
       
    76                 "Unallowed null value for request");
       
    77 
       
    78         // There is currently only one known status type (OCSP)
       
    79         // We can add more clauses to cover other types in the future
       
    80         if (statReqType.equals(StatusRequestType.OCSP) ||
       
    81                 statReqType.equals(StatusRequestType.OCSP_MULTI)) {
       
    82             if (!(statReq instanceof OCSPStatusRequest)) {
       
    83                 throw new IllegalArgumentException("StatusRequest not " +
       
    84                         "of type OCSPStatusRequest");
       
    85             }
       
    86         }
       
    87     }
       
    88 
       
    89     /**
       
    90      * Construct a {@code CertStatusReqItemV2} object from encoded bytes
       
    91      *
       
    92      * @param requestBytes the encoded bytes for the {@code CertStatusReqItemV2}
       
    93      *
       
    94      * @throws IOException if any decoding errors take place
       
    95      * @throws IllegalArgumentException if the parsed reqType value is not a
       
    96      *      supported status request type.
       
    97      */
       
    98     CertStatusReqItemV2(byte[] reqItemBytes) throws IOException {
       
    99         ByteBuffer reqBuf = ByteBuffer.wrap(reqItemBytes);
       
   100         statReqType = StatusRequestType.get(reqBuf.get());
       
   101         int requestLength = Short.toUnsignedInt(reqBuf.getShort());
       
   102 
       
   103         if (requestLength == reqBuf.remaining()) {
       
   104             byte[] statReqBytes = new byte[requestLength];
       
   105             reqBuf.get(statReqBytes);
       
   106             if (statReqType == StatusRequestType.OCSP ||
       
   107                     statReqType == StatusRequestType.OCSP_MULTI) {
       
   108                 request = new OCSPStatusRequest(statReqBytes);
       
   109             } else {
       
   110                 request = new UnknownStatusRequest(statReqBytes);
       
   111             }
       
   112         } else {
       
   113             throw new SSLException("Incorrect request_length: " +
       
   114                     "Expected " + reqBuf.remaining() + ", got " +
       
   115                     requestLength);
       
   116         }
       
   117     }
       
   118 
       
   119     /**
       
   120      * Construct an {@code CertStatusReqItemV2} object from data read from
       
   121      * a {@code HandshakeInputStream}
       
   122      *
       
   123      * @param s the {@code HandshakeInputStream} providing the encoded data
       
   124      *
       
   125      * @throws IOException if any decoding errors happen during object
       
   126      *      construction.
       
   127      * @throws IllegalArgumentException if the parsed reqType value is not a
       
   128      *      supported status request type.
       
   129      */
       
   130     CertStatusReqItemV2(HandshakeInStream in) throws IOException {
       
   131         statReqType = StatusRequestType.get(in.getInt8());
       
   132         int requestLength = in.getInt16();
       
   133 
       
   134         if (statReqType == StatusRequestType.OCSP ||
       
   135                 statReqType == StatusRequestType.OCSP_MULTI) {
       
   136             request = new OCSPStatusRequest(in);
       
   137         } else {
       
   138             request = new UnknownStatusRequest(in, requestLength);
       
   139         }
       
   140     }
       
   141 
       
   142     /**
       
   143      * Return the length of this {@code CertStatusReqItemV2} in its encoded form
       
   144      *
       
   145      * @return the encoded length of this {@code CertStatusReqItemV2}
       
   146      */
       
   147     int length() {
       
   148         // The length is the status type (1 byte) + the request length
       
   149         // field (2 bytes) + the StatusRequest data length.
       
   150         return request.length() + 3;
       
   151     }
       
   152 
       
   153     /**
       
   154      * Send the encoded {@code CertStatusReqItemV2} through a
       
   155      *      {@code HandshakeOutputStream}
       
   156      *
       
   157      * @param s the {@code HandshakeOutputStream} used to send the encoded data
       
   158      *
       
   159      * @throws IOException if any errors occur during the encoding process
       
   160      */
       
   161     void send(HandshakeOutStream s) throws IOException {
       
   162         s.putInt8(statReqType.id);
       
   163         s.putInt16(request.length());
       
   164         request.send(s);
       
   165     }
       
   166 
       
   167     /**
       
   168      * Create a string representation of this {@code CertStatusReqItemV2}
       
   169      *
       
   170      * @return the string representation of this {@code CertStatusReqItemV2}
       
   171      */
       
   172     @Override
       
   173     public String toString() {
       
   174         StringBuilder sb = new StringBuilder();
       
   175         sb.append("CertStatusReqItemV2: ").append(statReqType).append(", ");
       
   176         sb.append(request.toString());
       
   177 
       
   178         return sb.toString();
       
   179     }
       
   180 
       
   181     /**
       
   182      * Return the type field for this {@code CertStatusReqItemV2}
       
   183      *
       
   184      * @return the {@code StatusRequestType} for this extension.
       
   185      */
       
   186     StatusRequestType getType() {
       
   187         return statReqType;
       
   188     }
       
   189 
       
   190     /**
       
   191      * Get the underlying {@code StatusRequest} for this
       
   192      *      {@code CertStatusReqItemV2}
       
   193      *
       
   194      * @return the {@code StatusRequest}
       
   195      */
       
   196     StatusRequest getRequest() {
       
   197         return request;
       
   198     }
       
   199 }