src/java.base/share/classes/sun/security/ssl/CertStatusReqExtension.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.util.Objects;
       
    30 
       
    31 /*
       
    32  * RFC6066 defines the TLS extension,"status_request" (type 0x5),
       
    33  * which allows the client to request that the server perform OCSP
       
    34  * on the client's behalf.
       
    35  * The "extension data" field of this extension contains a
       
    36  * "CertificateStatusRequest" structure:
       
    37  *
       
    38  *      struct {
       
    39  *          CertificateStatusType status_type;
       
    40  *          select (status_type) {
       
    41  *              case ocsp: OCSPStatusRequest;
       
    42  *          } request;
       
    43  *      } CertificateStatusRequest;
       
    44  *
       
    45  *      enum { ocsp(1), (255) } CertificateStatusType;
       
    46  *
       
    47  *      struct {
       
    48  *          ResponderID responder_id_list<0..2^16-1>;
       
    49  *          Extensions  request_extensions;
       
    50  *      } OCSPStatusRequest;
       
    51  *
       
    52  *      opaque ResponderID<1..2^16-1>;
       
    53  *      opaque Extensions<0..2^16-1>;
       
    54  */
       
    55 
       
    56 final class CertStatusReqExtension extends HelloExtension {
       
    57 
       
    58     private final StatusRequestType statReqType;
       
    59     private final StatusRequest request;
       
    60 
       
    61 
       
    62     /**
       
    63      * Construct the default status request extension object.  The default
       
    64      * object results in a status_request extension where the extension
       
    65      * data segment is zero-length.  This is used primarily in ServerHello
       
    66      * messages where the server asserts it can do RFC 6066 status stapling.
       
    67      */
       
    68     CertStatusReqExtension() {
       
    69         super(ExtensionType.EXT_STATUS_REQUEST);
       
    70         statReqType = null;
       
    71         request = null;
       
    72     }
       
    73 
       
    74     /**
       
    75      * Construct the status request extension object given a request type
       
    76      *      and {@code StatusRequest} object.
       
    77      *
       
    78      * @param reqType a {@code StatusRequestExtType object correspoding
       
    79      *      to the underlying {@code StatusRequest} object.  A value of
       
    80      *      {@code null} is not allowed.
       
    81      * @param statReq the {@code StatusRequest} object used to provide the
       
    82      *      encoding for the TLS extension.  A value of {@code null} is not
       
    83      *      allowed.
       
    84      *
       
    85      * @throws IllegalArgumentException if the provided {@code StatusRequest}
       
    86      *      does not match the type.
       
    87      * @throws NullPointerException if either the {@code reqType} or
       
    88      *      {@code statReq} arguments are {@code null}.
       
    89      */
       
    90     CertStatusReqExtension(StatusRequestType reqType, StatusRequest statReq) {
       
    91         super(ExtensionType.EXT_STATUS_REQUEST);
       
    92 
       
    93         statReqType = Objects.requireNonNull(reqType,
       
    94                 "Unallowed null value for status_type");
       
    95         request = Objects.requireNonNull(statReq,
       
    96                 "Unallowed null value for request");
       
    97 
       
    98         // There is currently only one known status type (OCSP)
       
    99         // We can add more clauses to cover other types in the future
       
   100         if (statReqType == StatusRequestType.OCSP) {
       
   101             if (!(statReq instanceof OCSPStatusRequest)) {
       
   102                 throw new IllegalArgumentException("StatusRequest not " +
       
   103                         "of type OCSPStatusRequest");
       
   104             }
       
   105         }
       
   106     }
       
   107 
       
   108     /**
       
   109      * Construct the {@code CertStatusReqExtension} object from data read from
       
   110      *      a {@code HandshakeInputStream}
       
   111      *
       
   112      * @param s the {@code HandshakeInputStream} providing the encoded data
       
   113      * @param len the length of the extension data
       
   114      *
       
   115      * @throws IOException if any decoding errors happen during object
       
   116      *      construction.
       
   117      */
       
   118     CertStatusReqExtension(HandshakeInStream s, int len) throws IOException {
       
   119         super(ExtensionType.EXT_STATUS_REQUEST);
       
   120 
       
   121         if (len > 0) {
       
   122             // Obtain the status type (first byte)
       
   123             statReqType = StatusRequestType.get(s.getInt8());
       
   124             if (statReqType == StatusRequestType.OCSP) {
       
   125                 request = new OCSPStatusRequest(s);
       
   126             } else {
       
   127                 // This is a status_type we don't understand.  Create
       
   128                 // an UnknownStatusRequest in order to preserve the data
       
   129                 request = new UnknownStatusRequest(s, len - 1);
       
   130             }
       
   131         } else {
       
   132             // Treat this as a zero-length extension (i.e. from a ServerHello
       
   133             statReqType = null;
       
   134             request = null;
       
   135         }
       
   136     }
       
   137 
       
   138     /**
       
   139      * Return the length of the encoded extension, including extension type,
       
   140      *      extension length and status_type fields.
       
   141      *
       
   142      * @return the length in bytes, including the extension type and
       
   143      *      length fields.
       
   144      */
       
   145     @Override
       
   146     int length() {
       
   147         return (statReqType != null ? 5 + request.length() : 4);
       
   148     }
       
   149 
       
   150     /**
       
   151      * Send the encoded TLS extension through a {@code HandshakeOutputStream}
       
   152      *
       
   153      * @param s the {@code HandshakeOutputStream} used to send the encoded data
       
   154      *
       
   155      * @throws IOException tf any errors occur during the encoding process
       
   156      */
       
   157     @Override
       
   158     void send(HandshakeOutStream s) throws IOException {
       
   159         s.putInt16(type.id);
       
   160         s.putInt16(this.length() - 4);
       
   161 
       
   162         if (statReqType != null) {
       
   163             s.putInt8(statReqType.id);
       
   164             request.send(s);
       
   165         }
       
   166     }
       
   167 
       
   168     /**
       
   169      * Create a string representation of this {@code CertStatusReqExtension}
       
   170      *
       
   171      * @return the string representation of this {@code CertStatusReqExtension}
       
   172      */
       
   173     @Override
       
   174     public String toString() {
       
   175         StringBuilder sb = new StringBuilder("Extension ").append(type);
       
   176         if (statReqType != null) {
       
   177             sb.append(": ").append(statReqType).append(", ").append(request);
       
   178         }
       
   179 
       
   180         return sb.toString();
       
   181     }
       
   182 
       
   183     /**
       
   184      * Return the type field for this {@code CertStatusReqExtension}
       
   185      *
       
   186      * @return the {@code StatusRequestType} for this extension.  {@code null}
       
   187      *      will be returned if the default constructor is used to create
       
   188      *      a zero length status_request extension (found in ServerHello
       
   189      *      messages)
       
   190      */
       
   191     StatusRequestType getType() {
       
   192         return statReqType;
       
   193     }
       
   194 
       
   195     /**
       
   196      * Get the underlying {@code StatusRequest} for this
       
   197      *      {@code CertStatusReqExtension}
       
   198      *
       
   199      * @return the {@code StatusRequest} or {@code null} if the default
       
   200      * constructor was used to create this extension.
       
   201      */
       
   202     StatusRequest getRequest() {
       
   203         return request;
       
   204     }
       
   205 }