      1 /*
      2  * Copyright (c) 2000, 2021, 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 java.security.cert;
     27
     28 import java.io.InvalidObjectException;
     29 import java.io.IOException;
     30 import java.io.ObjectInputStream;
     31 import java.security.GeneralSecurityException;
     32
     33 /**
     34  * An exception indicating one of a variety of problems encountered when
     35  * validating a certification path.
     36  * <p>
     37  * A {@code CertPathValidatorException} provides support for wrapping
     38  * exceptions. The {@link #getCause getCause} method returns the throwable,
     39  * if any, that caused this exception to be thrown.
     40  * <p>
     41  * A {@code CertPathValidatorException} may also include the
     42  * certification path that was being validated when the exception was thrown,
     43  * the index of the certificate in the certification path that caused the
     44  * exception to be thrown, and the reason that caused the failure. Use the
     45  * {@link #getCertPath getCertPath}, {@link #getIndex getIndex}, and
     46  * {@link #getReason getReason} methods to retrieve this information.
     47  *
     48  * <p>
     49  * <b>Concurrent Access</b>
     50  * <p>
     51  * Unless otherwise specified, the methods defined in this class are not
     52  * thread-safe. Multiple threads that need to access a single
     53  * object concurrently should synchronize amongst themselves and
     54  * provide the necessary locking. Multiple threads each manipulating
     55  * separate objects need not synchronize.
     56  *
     57  * @see CertPathValidator
     58  *
     59  * @since       1.4
     60  * @author      Yassir Elley
     61  */
     62 public class CertPathValidatorException extends GeneralSecurityException {
     63
     64     @java.io.Serial
     65     private static final long serialVersionUID = -3083180014971893139L;
     66
     67     /**
     68      * @serial the index of the certificate in the certification path
     69      * that caused the exception to be thrown
     70      */
     71     private int index = -1;
     72
     73     /**
     74      * @serial the {@code CertPath} that was being validated when
     75      * the exception was thrown
     76      */
     77     private CertPath certPath;
     78
     79     /**
     80      * @serial the reason the validation failed
     81      */
     82     private Reason reason = BasicReason.UNSPECIFIED;
     83
     84     /**
     85      * Creates a {@code CertPathValidatorException} with
     86      * no detail message.
     87      */
     88     public CertPathValidatorException() {
     89         this(null, null);
     90     }
     91
     92     /**
     93      * Creates a {@code CertPathValidatorException} with the given
     94      * detail message. A detail message is a {@code String} that
     95      * describes this particular exception.
     96      *
     97      * @param msg the detail message
     98      */
     99     public CertPathValidatorException(String msg) {
    100         this(msg, null);
    101     }
    102
    103     /**
    104      * Creates a {@code CertPathValidatorException} that wraps the
    105      * specified throwable. This allows any exception to be converted into a
    106      * {@code CertPathValidatorException}, while retaining information
    107      * about the wrapped exception, which may be useful for debugging. The
    108      * detail message is set to ({@code cause==null ? null : cause.toString()})
    109      * (which typically contains the class and detail message of
    110      * cause).
    111      *
    112      * @param cause the cause (which is saved for later retrieval by the
    113      * {@link #getCause getCause()} method). (A {@code null} value is
    114      * permitted, and indicates that the cause is nonexistent or unknown.)
    115      */
    116     public CertPathValidatorException(Throwable cause) {
    117         this((cause == null ? null : cause.toString()), cause);
    118     }
    119
    120     /**
    121      * Creates a {@code CertPathValidatorException} with the specified
    122      * detail message and cause.
    123      *
    124      * @param msg the detail message
    125      * @param cause the cause (which is saved for later retrieval by the
    126      * {@link #getCause getCause()} method). (A {@code null} value is
    127      * permitted, and indicates that the cause is nonexistent or unknown.)
    128      */
    129     public CertPathValidatorException(String msg, Throwable cause) {
    130         this(msg, cause, null, -1);
    131     }
    132
    133     /**
    134      * Creates a {@code CertPathValidatorException} with the specified
    135      * detail message, cause, certification path, and index.
    136      *
    137      * @param msg the detail message (or {@code null} if none)
    138      * @param cause the cause (or {@code null} if none)
    139      * @param certPath the certification path that was in the process of
    140      * being validated when the error was encountered
    141      * @param index the index of the certificate in the certification path
    142      * that caused the error (or -1 if not applicable). Note that
    143      * the list of certificates in a {@code CertPath} is zero based.
    144      * @throws IndexOutOfBoundsException if the index is out of range
    145      * {@code (index < -1 || (certPath != null && index >=
    146      * certPath.getCertificates().size()) }
    147      * @throws IllegalArgumentException if {@code certPath} is
    148      * {@code null} and {@code index} is not -1
    149      */
    150     public CertPathValidatorException(String msg, Throwable cause,
    151             CertPath certPath, int index) {
    152         this(msg, cause, certPath, index, BasicReason.UNSPECIFIED);
    153     }
    154
    155     /**
    156      * Creates a {@code CertPathValidatorException} with the specified
    157      * detail message, cause, certification path, index, and reason.
    158      *
    159      * @param msg the detail message (or {@code null} if none)
    160      * @param cause the cause (or {@code null} if none)
    161      * @param certPath the certification path that was in the process of
    162      * being validated when the error was encountered
    163      * @param index the index of the certificate in the certification path
    164      * that caused the error (or -1 if not applicable). Note that
    165      * the list of certificates in a {@code CertPath} is zero based.
    166      * @param reason the reason the validation failed
    167      * @throws IndexOutOfBoundsException if the index is out of range
    168      * {@code (index < -1 || (certPath != null && index >=
    169      * certPath.getCertificates().size()) }
    170      * @throws IllegalArgumentException if {@code certPath} is
    171      * {@code null} and {@code index} is not -1
    172      * @throws NullPointerException if {@code reason} is {@code null}
    173      *
    174      * @since 1.7
    175      */
    176     public CertPathValidatorException(String msg, Throwable cause,
    177             CertPath certPath, int index, Reason reason) {
    178         super(msg, cause);
    179         if (certPath == null && index != -1) {
    180             throw new IllegalArgumentException();
    181         }
    182         if (index < -1 ||
    183             (certPath != null && index >= certPath.getCertificates().size())) {
    184             throw new IndexOutOfBoundsException();
    185         }
    186         if (reason == null) {
    187             throw new NullPointerException("reason can't be null");
    188         }
    189         this.certPath = certPath;
    190         this.index = index;
    191         this.reason = reason;
    192     }
    193
    194     /**
    195      * Returns the certification path that was being validated when
    196      * the exception was thrown.
    197      *
    198      * @return the {@code CertPath} that was being validated when
    199      * the exception was thrown (or {@code null} if not specified)
    200      */
    201     public CertPath getCertPath() {
    202         return this.certPath;
    203     }
    204
    205     /**
    206      * Returns the index of the certificate in the certification path
    207      * that caused the exception to be thrown. Note that the list of
    208      * certificates in a {@code CertPath} is zero based. If no
    209      * index has been set, -1 is returned.
    210      *
    211      * @return the index that has been set, or -1 if none has been set
    212      */
    213     public int getIndex() {
    214         return this.index;
    215     }
    216
    217     /**
    218      * Returns the reason that the validation failed. The reason is
    219      * associated with the index of the certificate returned by
    220      * {@link #getIndex}.
    221      *
    222      * @return the reason that the validation failed, or
    223      *    {@code BasicReason.UNSPECIFIED} if a reason has not been
    224      *    specified
    225      *
    226      * @since 1.7
    227      */
    228     public Reason getReason() {
    229         return this.reason;
    230     }
    231
    232     /**
    233      * Restores the state of this object from the stream.
    234      *
    235      * @param  stream the {@code ObjectInputStream} from which data is read
    236      * @throws IOException if an I/O error occurs
    237      * @throws ClassNotFoundException if a serialized class cannot be loaded
    238      */
    239     @java.io.Serial
    240     private void readObject(ObjectInputStream stream)
    241         throws ClassNotFoundException, IOException {
    242         stream.defaultReadObject();
    243         if (reason == null) {
    244             reason = BasicReason.UNSPECIFIED;
    245         }
    246         if (certPath == null && index != -1) {
    247             throw new InvalidObjectException("certpath is null and index != -1");
    248         }
    249         if (index < -1 ||
    250             (certPath != null && index >= certPath.getCertificates().size())) {
    251             throw new InvalidObjectException("index out of range");
    252         }
    253     }
    254
    255     /**
    256      * The reason the validation algorithm failed.
    257      *
    258      * @since 1.7
    259      */
    260     public static interface Reason extends java.io.Serializable { }
    261
    262
    263     /**
    264      * The BasicReason enumerates the potential reasons that a certification
    265      * path of any type may be invalid.
    266      *
    267      * @since 1.7
    268      */
    269     public static enum BasicReason implements Reason {
    270         /**
    271          * Unspecified reason.
    272          */
    273         UNSPECIFIED,
    274
    275         /**
    276          * The certificate is expired.
    277          */
    278         EXPIRED,
    279
    280         /**
    281          * The certificate is not yet valid.
    282          */
    283         NOT_YET_VALID,
    284
    285         /**
    286          * The certificate is revoked.
    287          */
    288         REVOKED,
    289
    290         /**
    291          * The revocation status of the certificate could not be determined.
    292          */
    293         UNDETERMINED_REVOCATION_STATUS,
    294
    295         /**
    296          * The signature is invalid.
    297          */
    298         INVALID_SIGNATURE,
    299
    300         /**
    301          * The public key or the signature algorithm has been constrained.
    302          */
    303         ALGORITHM_CONSTRAINED
    304     }
    305 }
    --- EOF ---