001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2008 Sun Microsystems, Inc.
025 *      Portions Copyright 2014-2015 ForgeRock AS
026 */
027package org.opends.server.util;
028
029
030
031import java.security.cert.CertificateException;
032import org.forgerock.i18n.slf4j.LocalizedLogger;
033import java.security.cert.CertificateExpiredException;
034import java.security.cert.CertificateNotYetValidException;
035import java.security.cert.X509Certificate;
036import java.util.Date;
037import javax.net.ssl.X509TrustManager;
038
039
040
041import static org.opends.messages.UtilityMessages.*;
042
043
044/**
045 * This class implements an X.509 trust manager that will be used to wrap an
046 * existing trust manager and makes it possible to reject a presented
047 * certificate if that certificate is outside the validity window.
048 */
049@org.opends.server.types.PublicAPI(
050     stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
051     mayInstantiate=true,
052     mayExtend=false,
053     mayInvoke=true)
054public final class ExpirationCheckTrustManager
055       implements X509TrustManager
056{
057
058  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
059
060  /** The trust manager that is wrapped by this trust manager. */
061  private X509TrustManager trustManager;
062
063
064
065  /**
066   * Creates a new instance of this trust manager that will wrap the provided
067   * trust manager.
068   *
069   * @param  trustManager  The trust manager to be wrapped by this trust
070   *                       manager.
071   */
072  public ExpirationCheckTrustManager(X509TrustManager trustManager)
073  {
074    this.trustManager = trustManager;
075  }
076
077
078
079  /**
080   * Determines whether to trust the peer based on the provided certificate
081   * chain.  In this case, the peer will only be trusted if all certificates in
082   * the chain are within the validity window and the parent trust manager also
083   * accepts the certificate.
084   *
085   * @param  chain     The peer certificate chain.
086   * @param  authType  The authentication type based on the client certificate.
087   *
088   * @throws  CertificateException  If the client certificate chain is not
089   *                                trusted.
090   */
091  public void checkClientTrusted(X509Certificate[] chain, String authType)
092         throws CertificateException
093  {
094    Date currentDate = new Date();
095    for (X509Certificate c : chain)
096    {
097      try
098      {
099        c.checkValidity(currentDate);
100      }
101      catch (CertificateExpiredException cee)
102      {
103        logger.error(ERR_EXPCHECK_TRUSTMGR_CLIENT_CERT_EXPIRED,
104            c.getSubjectDN().getName(), c.getNotAfter());
105        throw cee;
106      }
107      catch (CertificateNotYetValidException cnyve)
108      {
109        logger.error(ERR_EXPCHECK_TRUSTMGR_CLIENT_CERT_NOT_YET_VALID,
110            c.getSubjectDN().getName(), c.getNotBefore());
111        throw cnyve;
112      }
113    }
114
115    trustManager.checkClientTrusted(chain, authType);
116  }
117
118
119
120  /**
121   * Determines whether to trust the peer based on the provided certificate
122   * chain.  In this case, the peer will only be trusted if all certificates in
123   * the chain are within the validity window and the parent trust manager also
124   * accepts the certificate.
125   *
126   * @param  chain     The peer certificate chain.
127   * @param  authType  The key exchange algorithm used.
128   *
129   * @throws  CertificateException  If the server certificate chain is not
130   *                                trusted.
131   */
132  public void checkServerTrusted(X509Certificate[] chain, String authType)
133         throws CertificateException
134  {
135    Date currentDate = new Date();
136    for (X509Certificate c : chain)
137    {
138      try
139      {
140        c.checkValidity(currentDate);
141      }
142      catch (CertificateExpiredException cee)
143      {
144        logger.error(ERR_EXPCHECK_TRUSTMGR_SERVER_CERT_EXPIRED,
145            c.getSubjectDN().getName(), c.getNotAfter());
146        throw cee;
147      }
148      catch (CertificateNotYetValidException cnyve)
149      {
150        logger.error(ERR_EXPCHECK_TRUSTMGR_SERVER_CERT_NOT_YET_VALID,
151            c.getSubjectDN().getName(), c.getNotBefore());
152        throw cnyve;
153      }
154    }
155
156    trustManager.checkServerTrusted(chain, authType);
157  }
158
159
160
161  /**
162   * Retrieves the set of CA certificates which are trusted for authenticating
163   * peers.  This will be taken from the parent trust manager.
164   *
165   * @return  A non-null (possibly empty) array of acceptable CA issuer
166   *          certificates.
167   */
168  public X509Certificate[] getAcceptedIssuers()
169  {
170    return trustManager.getAcceptedIssuers();
171  }
172}
173