be.fedict.trust.ocsp.OnlineOcspRepository.java Source code

Java tutorial

Introduction

Here is the source code for be.fedict.trust.ocsp.OnlineOcspRepository.java

Source

/*
 * Java Trust Project.
 * Copyright (C) 2009 FedICT.
 * Copyright (C) 2014 e-Contract.be BVBA.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, see 
 * http://www.gnu.org/licenses/.
 */

package be.fedict.trust.ocsp;

import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.security.cert.X509Certificate;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.DefaultHttpClient;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.cert.ocsp.CertificateID;
import org.bouncycastle.cert.ocsp.OCSPReq;
import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
import org.bouncycastle.cert.ocsp.OCSPResp;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;

import be.fedict.trust.Credentials;
import be.fedict.trust.NetworkConfig;
import org.apache.http.util.EntityUtils;

/**
 * Online OCSP repository. This implementation will contact the OCSP Responder
 * to retrieve the OCSP response.
 * 
 * @author Frank Cornelis
 * 
 */
public class OnlineOcspRepository implements OcspRepository {

    private static final Log LOG = LogFactory.getLog(OnlineOcspRepository.class);

    private final NetworkConfig networkConfig;

    private Credentials credentials;

    /**
     * Main construtor.
     * 
     * @param networkConfig
     *            the optional network configuration used during OCSP Responder
     *            communication.
     */
    public OnlineOcspRepository(NetworkConfig networkConfig) {
        this.networkConfig = networkConfig;
    }

    /**
     * Default constructor.
     */
    public OnlineOcspRepository() {
        this(null);
    }

    /**
     * Sets the credentials to use to access protected OCSP services.
     * 
     * @param credentials
     */
    public void setCredentials(Credentials credentials) {
        this.credentials = credentials;
    }

    @Override
    public OCSPResp findOcspResponse(URI ocspUri, X509Certificate certificate, X509Certificate issuerCertificate,
            Date validationDate) {
        OCSPResp ocspResp = null;
        try {
            ocspResp = getOcspResponse(ocspUri, certificate, issuerCertificate);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return ocspResp;
    }

    private OCSPResp getOcspResponse(URI ocspUri, X509Certificate certificate, X509Certificate issuerCertificate)
            throws Exception {
        LOG.debug("OCSP URI: " + ocspUri);
        OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder();
        DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder()
                .setProvider(BouncyCastleProvider.PROVIDER_NAME).build();
        CertificateID certId = new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1),
                new JcaX509CertificateHolder(issuerCertificate), certificate.getSerialNumber());
        ocspReqBuilder.addRequest(certId);

        OCSPReq ocspReq = ocspReqBuilder.build();
        byte[] ocspReqData = ocspReq.getEncoded();

        HttpPost httpPost = new HttpPost(ocspUri.toString());
        ContentType contentType = ContentType.create("application/ocsp-request");
        HttpEntity requestEntity = new ByteArrayEntity(ocspReqData, contentType);
        httpPost.addHeader("User-Agent", "jTrust OCSP Client");
        httpPost.setEntity(requestEntity);

        DefaultHttpClient httpClient = new DefaultHttpClient();
        if (null != this.networkConfig) {
            HttpHost proxy = new HttpHost(this.networkConfig.getProxyHost(), this.networkConfig.getProxyPort());
            httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
        }
        if (null != this.credentials) {
            this.credentials.init(httpClient.getCredentialsProvider());
        }

        HttpResponse httpResponse;
        int responseCode;
        try {
            httpResponse = httpClient.execute(httpPost);
            StatusLine statusLine = httpResponse.getStatusLine();
            responseCode = statusLine.getStatusCode();
        } catch (ConnectException e) {
            LOG.debug("OCSP responder is down");
            return null;
        }

        if (HttpURLConnection.HTTP_OK != responseCode) {
            LOG.error("HTTP response code: " + responseCode);
            return null;
        }

        Header responseContentTypeHeader = httpResponse.getFirstHeader("Content-Type");
        if (null == responseContentTypeHeader) {
            LOG.error("no Content-Type response header");
            return null;
        }
        String resultContentType = responseContentTypeHeader.getValue();
        if (!"application/ocsp-response".equals(resultContentType)) {
            LOG.error("result content type not application/ocsp-response");
            LOG.error("actual content-type: " + resultContentType);
            if ("text/html".equals(resultContentType)) {
                LOG.error("content: " + EntityUtils.toString(httpResponse.getEntity()));
            }
            return null;
        }

        Header responseContentLengthHeader = httpResponse.getFirstHeader("Content-Length");
        if (null != responseContentLengthHeader) {
            String resultContentLength = responseContentLengthHeader.getValue();
            if ("0".equals(resultContentLength)) {
                LOG.debug("no content returned");
                return null;
            }
        }

        HttpEntity httpEntity = httpResponse.getEntity();
        OCSPResp ocspResp = new OCSPResp(httpEntity.getContent());
        LOG.debug("OCSP response size: " + ocspResp.getEncoded().length + " bytes");
        httpPost.releaseConnection();
        return ocspResp;
    }
}