Newer
Older
import dk.gov.oiosi.common.OutVariable;
import dk.gov.oiosi.common.cache.ICache;
import dk.gov.oiosi.configuration.CacheFactory;
import dk.gov.oiosi.security.CertificateIssuerSubject;
import dk.gov.oiosi.security.CertificateSubject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.jce.provider.AnnotatedException;
import org.bouncycastle.x509.extension.X509ExtensionUtil;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
private static final Log log = LogFactory.getLog(CertificateUtil.class);
public CertificateUtil() {
}
public List<URL> getOcspUrls(X509Certificate cert) throws Exception {
List<URL> urls = new ArrayList<>();
AuthorityInformationAccess authInfoAccess = null;
try {
ASN1Primitive auth_info_acc = getExtensionValue(cert, Extension.authorityInfoAccess.getId());
if (auth_info_acc != null) {
authInfoAccess = AuthorityInformationAccess.getInstance(auth_info_acc);
}
} catch (AnnotatedException ae) {
// throw new Exception();
// ErrorBundle msg = new
// ErrorBundle(RESOURCE_NAME,"CertPathReviewer.crlAuthInfoAccError");
// addError(msg,index);
}
if (authInfoAccess != null) {
AccessDescription[] ads = authInfoAccess.getAccessDescriptions();
for (AccessDescription ad : ads) {
if (ad.getAccessMethod().equals(AccessDescription.id_ad_ocsp)) {
GeneralName name = ad.getAccessLocation();
if (name.getTagNo() == GeneralName.uniformResourceIdentifier) {
String url = ((DERIA5String) name.getName()).getString();
urls.add(new URL(url));
}
}
}
}
return urls;
}
public List<URL> getIssuerUrls(X509Certificate cert) throws Exception {
List<URL> urls = new ArrayList<>();
AuthorityInformationAccess authInfoAccess = null;
try {
ASN1Primitive auth_info_acc = getExtensionValue(cert, Extension.authorityInfoAccess.getId());
if (auth_info_acc != null) {
authInfoAccess = AuthorityInformationAccess.getInstance(auth_info_acc);
}
} catch (AnnotatedException ae) {
// throw new Exception();
// ErrorBundle msg = new
// ErrorBundle(RESOURCE_NAME,"CertPathReviewer.crlAuthInfoAccError");
// addError(msg,index);
}
if (authInfoAccess != null) {
AccessDescription[] ads = authInfoAccess.getAccessDescriptions();
for (AccessDescription ad : ads) {
if (ad.getAccessMethod().equals(AccessDescription.id_ad_caIssuers)) {
GeneralName name = ad.getAccessLocation();
if (name.getTagNo() == GeneralName.uniformResourceIdentifier) {
String url = ((DERIA5String) name.getName()).getString();
urls.add(new URL(url));
}
}
}
}
return urls;
}
public List<URL> getCrlURLs(X509Certificate cert) {
List<URL> urls = new ArrayList<>();
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Retrieves the raw ASN1 data of the CRL Dist Points X509 extension
byte[] cdp = cert.getExtensionValue(X509Extension.cRLDistributionPoints.getId());
if (cdp != null) {
try {
// Wraps the raw data in a container class
CRLDistPoint crldp = CRLDistPoint.getInstance(X509ExtensionUtil.fromExtensionValue(cdp));
DistributionPoint[] distPoints = crldp.getDistributionPoints();
for (DistributionPoint dp : distPoints) {
// Only use the "General name" data in the distribution point entry.
GeneralNames gns = (GeneralNames) dp.getDistributionPoint().getName();
DERIA5String uri;
for (GeneralName name : gns.getNames()) {
// Only retrieve URLs
if (name.getTagNo() == GeneralName.uniformResourceIdentifier) {
uri = (DERIA5String) name.getName();
urls.add(new URL(uri.getString()));
}
}
}
} catch (IOException e) {
// Could not retrieve the CRLDistPoint object. Just return empty url list.
/*
* Hmm... So there is no possibility to see what happened when
* certificate is checked against CRL - such error is just hidden.
*
* TODO DLK: Think at least about logging such exception, throwing exception is preferred.
*/
log.error("Unable to find CRL URL for cert=[" + cert.getSubjectDN().getName() + "]: " + e.getMessage(), e);
}
}
return urls;
}
/**
* Get the url to the issuing certificate.
*
* @param cert A Oces2 certificate
* @return The url for the issuing certificate, if exist.
*/
public URL getIssuerUrl(X509Certificate cert) {
try {
List<URL> list = this.getIssuerUrls(cert);
if (list.size() == 1) {
// the url must be located on the 1. index
return list.get(0);
}
} catch (Exception e) {
log.warn("Error fetching certificate: " + e.getMessage(), e);
}
return null;
}
/**
* Extract the value of the given extension, if it exists.
*
* @param ext The extension object.
* @param oid The object identifier to obtain.
* @return ASN1Primitive.
* @throws Exception if the extension cannot be read.
*/
protected static ASN1Primitive getExtensionValue(java.security.cert.X509Extension ext, String oid) throws Exception {
byte[] bytes = ext.getExtensionValue(oid);
if (bytes == null) {
return null;
}
return getObject(oid, bytes);
}
private static ASN1Primitive getObject(String oid, byte[] ext) throws Exception {
try {
aIn = new ASN1InputStream(ext);
ASN1OctetString octetString = (ASN1OctetString) aIn.readObject();
return aIn.readObject();
} catch (Exception e) {
throw new Exception("exception processing extension=" + oid + ": " + e.getMessage(), e);
} finally {
if (aIn != null) {
aIn.close();
}
}
}
public X509Certificate downloadIssuerCert(X509Certificate certificate) {
ICache<CertificateSubject, X509Certificate> cache = CacheFactory.getInstance().getCertificateCache();
CertificateIssuerSubject certificateIssuerSubject = new CertificateIssuerSubject(certificate);
X509Certificate downloadedX509Certificate = null;
OutVariable<X509Certificate> issuerCertificateOutVariable = new OutVariable<>();
if (cache.tryGetValue(certificateIssuerSubject, issuerCertificateOutVariable)) {
// certificate already retrieved - using the cached version
downloadedX509Certificate = issuerCertificateOutVariable.getVariable();
} else {
// download the certificate, and add it to the cache.
InputStream inputStream = null;
// CertificateUtil certificateUtil = new CertificateUtil();
URL issuerCertificateURL = getIssuerUrl(certificate);
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
if (issuerCertificateURL != null) {
// url is not null - try to download the certificate
try {
inputStream = issuerCertificateURL.openStream();
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
downloadedX509Certificate = (X509Certificate) certificateFactory.generateCertificate(inputStream);
cache.add(certificateIssuerSubject, downloadedX509Certificate);
} catch (IOException e) {
log.warn("Error reading from url " + issuerCertificateURL + " input stream: " + e.getMessage(), e);
} catch (CertificateException e) {
log.warn("Error creating certificate from url " + issuerCertificateURL + " input stream: " + e.getMessage(), e);
} catch (Exception e) {
log.warn("Unexpected error during downloading certificate from url " + issuerCertificateURL + " input stream: " + e.getMessage(), e);
} finally {
// remember to close the input stream.
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.warn("Error closing InputStream: " + e.getMessage(), e);
}
}
}
}
}
return downloadedX509Certificate;
}