1 13 14 package org.ejbca.core.protocol.ocsp; 15 16 import java.io.ByteArrayInputStream ; 17 import java.io.ByteArrayOutputStream ; 18 import java.io.FileInputStream ; 19 import java.io.FileNotFoundException ; 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.io.OutputStream ; 23 import java.net.HttpURLConnection ; 24 import java.net.URL ; 25 import java.net.URLConnection ; 26 import java.security.GeneralSecurityException ; 27 import java.security.KeyStore ; 28 import java.security.KeyStoreException ; 29 import java.security.NoSuchAlgorithmException ; 30 import java.security.NoSuchProviderException ; 31 import java.security.PublicKey ; 32 import java.security.SignatureException ; 33 import java.security.cert.Certificate ; 34 import java.security.cert.CertificateException ; 35 import java.security.cert.X509Certificate ; 36 import java.util.Enumeration ; 37 import java.util.Hashtable ; 38 39 import javax.net.ssl.HostnameVerifier; 40 import javax.net.ssl.HttpsURLConnection; 41 import javax.net.ssl.KeyManagerFactory; 42 import javax.net.ssl.SSLContext; 43 import javax.net.ssl.SSLSession; 44 import javax.net.ssl.SSLSocketFactory; 45 import javax.net.ssl.TrustManagerFactory; 46 47 import org.bouncycastle.asn1.ASN1InputStream; 48 import org.bouncycastle.asn1.ASN1OctetString; 49 import org.bouncycastle.asn1.DEROctetString; 50 import org.bouncycastle.asn1.x509.X509Extension; 51 import org.bouncycastle.asn1.x509.X509Extensions; 52 import org.bouncycastle.ocsp.BasicOCSPResp; 53 import org.bouncycastle.ocsp.CertificateID; 54 import org.bouncycastle.ocsp.OCSPException; 55 import org.bouncycastle.ocsp.OCSPReq; 56 import org.bouncycastle.ocsp.OCSPReqGenerator; 57 import org.bouncycastle.ocsp.OCSPResp; 58 import org.bouncycastle.ocsp.RespID; 59 import org.ejbca.util.CertTools; 60 import org.ejbca.util.KeyTools; 61 62 76 public class OCSPUnidClient { 77 78 private String httpReqPath = null; 79 private KeyStore ks = null; 80 private String passphrase = null; 81 82 88 public OCSPUnidClient(KeyStore keystore, String pwd, String ocspurl) { 89 this.httpReqPath = ocspurl; 90 this.passphrase = pwd; 91 this.ks = keystore; 92 CertTools.installBCProvider(); 93 } 94 95 107 public OCSPUnidClient(String ksfilename, String pwd, String ocspurl) throws KeyStoreException , NoSuchProviderException , NoSuchAlgorithmException , CertificateException , FileNotFoundException , IOException { 108 this.httpReqPath = ocspurl; 109 this.passphrase = pwd; 110 if (ksfilename != null) { 111 ks = KeyStore.getInstance("PKCS12", "BC"); 112 ks.load(new FileInputStream (ksfilename), pwd.toCharArray()); 113 } 114 CertTools.installBCProvider(); 115 } 116 117 124 public OCSPUnidResponse lookup(X509Certificate cert, X509Certificate cacert, boolean getfnr) throws OCSPException, IOException , GeneralSecurityException { 125 if (httpReqPath == null) { 127 httpReqPath = CertTools.getAuthorityInformationAccessOcspUrl(cert); 128 if (httpReqPath == null) { 130 OCSPUnidResponse ret = new OCSPUnidResponse(); 131 ret.setErrorCode(OCSPUnidResponse.ERROR_NO_OCSP_URI); 132 return ret; 133 } 134 } 135 OCSPReqGenerator gen = new OCSPReqGenerator(); 137 CertificateID certId = new CertificateID(CertificateID.HASH_SHA1, cacert, cert.getSerialNumber()); 138 gen.addRequest(certId); 147 if (getfnr && (ks != null)) { 149 Hashtable exts = new Hashtable (); 150 X509Extension ext = new X509Extension(false, new DEROctetString(new FnrFromUnidExtension("1"))); 151 exts.put(FnrFromUnidExtension.FnrFromUnidOid, ext); 152 gen.setRequestExtensions(new X509Extensions(exts)); 153 } 154 OCSPReq req = gen.generate(); 155 156 OCSPUnidResponse ret = sendOCSPPost(req.getEncoded(), cacert); 158 return ret; 159 } 160 161 165 private OCSPUnidResponse sendOCSPPost(byte[] ocspPackage, X509Certificate cacert) throws IOException , OCSPException, GeneralSecurityException { 166 URL url = new URL (httpReqPath); 168 HttpURLConnection con = (HttpURLConnection )getUrlConnection(url); 169 con.setDoOutput(true); 171 con.setRequestMethod("POST"); 172 173 con.setRequestProperty("Content-Type", "application/ocsp-request"); 175 OutputStream os = null; 176 try { 177 os = con.getOutputStream(); 178 os.write(ocspPackage); 179 } finally { 180 if (os != null) os.close(); 181 } 182 OCSPUnidResponse ret = new OCSPUnidResponse(); 183 ret.setHttpReturnCode(con.getResponseCode()); 184 if (ret.getHttpReturnCode() != 200) { 185 if (ret.getHttpReturnCode() == 401) { 186 ret.setErrorCode(OCSPUnidResponse.ERROR_UNAUTHORIZED); 187 } else { 188 ret.setErrorCode(OCSPUnidResponse.ERROR_UNKNOWN); 189 } 190 return ret; 191 } 192 ByteArrayOutputStream baos = null; 193 InputStream in = null; 194 byte[] respBytes = null; 195 try { 196 baos = new ByteArrayOutputStream (); 197 in = con.getInputStream(); 199 int b = in.read(); 200 while (b != -1) { 201 baos.write(b); 202 b = in.read(); 203 } 204 baos.flush(); 205 in.close(); 206 respBytes = baos.toByteArray(); 207 } finally { 208 if (baos != null) baos.close(); 209 if (in != null) in.close(); 210 } 211 if (respBytes == null) { 212 ret.setErrorCode(OCSPUnidResponse.ERROR_NO_RESPONSE); 213 return ret; 214 } 215 OCSPResp response = new OCSPResp(new ByteArrayInputStream (respBytes)); 216 BasicOCSPResp brep = (BasicOCSPResp) response.getResponseObject(); 217 X509Certificate [] chain = brep.getCerts("BC"); 218 PublicKey signerPub = chain[0].getPublicKey(); 219 RespID respId = new RespID(signerPub); 220 if (!brep.getResponderId().equals(respId)) { 221 ret.setErrorCode(OCSPUnidResponse.ERROR_INVALID_SIGNERID); 223 } 224 boolean verify = brep.verify(signerPub, "BC"); 225 if (!verify) { 226 ret.setErrorCode(OCSPUnidResponse.ERROR_INVALID_SIGNATURE); 227 return ret; 228 } 229 try { 231 chain[0].verify(cacert.getPublicKey()); 232 } catch (SignatureException e) { 233 ret.setErrorCode(OCSPUnidResponse.ERROR_INVALID_SIGNERCERT); 234 return ret; 235 } 236 ret.setResp(response); 237 String fnr = getFnr(brep); 238 if (fnr != null) { 239 ret.setFnr(fnr); 240 } 241 return ret; 242 } 243 244 private String getFnr(BasicOCSPResp brep) throws IOException { 245 byte[] fnrrep = brep.getExtensionValue(FnrFromUnidExtension.FnrFromUnidOid.getId()); 246 if (fnrrep == null) { 247 return null; 248 } 249 ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream (fnrrep)); 250 ASN1OctetString octs = (ASN1OctetString) aIn.readObject(); 251 aIn = new ASN1InputStream(new ByteArrayInputStream (octs.getOctets())); 252 FnrFromUnidExtension fnrobj = FnrFromUnidExtension.getInstance(aIn.readObject()); 253 return fnrobj.getFnr(); 254 } 255 256 private SSLSocketFactory getSSLFactory() throws GeneralSecurityException , IOException { 257 258 SSLContext ctx = SSLContext.getInstance("TLS"); 259 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 260 261 kmf.init(ks, passphrase.toCharArray()); 263 264 KeyStore trustks = KeyStore.getInstance("jks"); 266 trustks.load(null, "foo123".toCharArray()); 267 Enumeration en = ks.aliases(); 269 String alias = null; 270 while ( (alias==null || ks.isCertificateEntry(alias)) && en.hasMoreElements() ) 272 alias = (String )en.nextElement(); 273 Certificate [] certs = KeyTools.getCertChain(ks, alias); 274 if (certs == null) { 275 throw new IOException ("Can not find a certificate entry in PKCS12 keystore for alias "+alias); 276 } 277 trustks.setCertificateEntry("trusted", certs[certs.length-1]); 278 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 279 tmf.init(trustks); 280 281 ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 282 283 return ctx.getSocketFactory(); 284 } 285 286 293 private URLConnection getUrlConnection(URL url) throws IOException , GeneralSecurityException { 294 URLConnection orgcon = url.openConnection(); 295 if (orgcon instanceof HttpsURLConnection) { 296 HttpsURLConnection con = (HttpsURLConnection) orgcon; 297 con.setHostnameVerifier(new SimpleVerifier()); 298 con.setSSLSocketFactory(getSSLFactory()); 299 } 300 return orgcon; 301 } 302 303 class SimpleVerifier implements HostnameVerifier { 304 public boolean verify(String hostname, SSLSession session) { 305 return true; 306 } 307 } 308 309 } 310 | Popular Tags |