1 13 14 package org.ejbca.ui.web.pub; 15 16 import java.io.IOException ; 17 import java.io.PrintStream ; 18 import java.io.PrintWriter ; 19 import java.math.BigInteger ; 20 import java.net.URLEncoder ; 21 import java.security.cert.Certificate ; 22 import java.security.cert.X509CRL ; 23 import java.security.cert.X509Certificate ; 24 import java.util.Collection ; 25 import java.util.Date ; 26 import java.util.Iterator ; 27 28 import javax.ejb.EJBException ; 29 import javax.servlet.ServletConfig ; 30 import javax.servlet.ServletException ; 31 import javax.servlet.http.HttpServlet ; 32 import javax.servlet.http.HttpServletRequest ; 33 import javax.servlet.http.HttpServletResponse ; 34 35 import org.apache.commons.lang.StringUtils; 36 import org.apache.log4j.Logger; 37 import org.ejbca.core.ejb.ServiceLocator; 38 import org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionLocal; 39 import org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionLocalHome; 40 import org.ejbca.core.ejb.ca.sign.ISignSessionLocal; 41 import org.ejbca.core.ejb.ca.sign.ISignSessionLocalHome; 42 import org.ejbca.core.ejb.ca.store.ICertificateStoreSessionLocal; 43 import org.ejbca.core.ejb.ca.store.ICertificateStoreSessionLocalHome; 44 import org.ejbca.core.model.ca.caadmin.CAInfo; 45 import org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAServiceInfo; 46 import org.ejbca.core.model.ca.caadmin.extendedcaservices.OCSPCAServiceInfo; 47 import org.ejbca.core.model.ca.crl.RevokedCertInfo; 48 import org.ejbca.core.model.log.Admin; 49 import org.ejbca.ui.web.RequestHelper; 50 import org.ejbca.util.Base64; 51 import org.ejbca.util.CertTools; 52 53 73 public class CertDistServlet extends HttpServlet { 74 75 private static Logger log = Logger.getLogger(CertDistServlet.class); 76 77 private static final String COMMAND_PROPERTY_NAME = "cmd"; 78 private static final String COMMAND_CRL = "crl"; 79 private static final String COMMAND_REVOKED = "revoked"; 80 private static final String COMMAND_CERT = "lastcert"; 81 private static final String COMMAND_LISTCERT = "listcerts"; 82 private static final String COMMAND_NSCACERT = "nscacert"; 83 private static final String COMMAND_IECACERT = "iecacert"; 84 private static final String COMMAND_CACERT = "cacert"; 85 private static final String COMMAND_NSOCSPCERT = "nsocspcert"; 86 private static final String COMMAND_IEOCSPCERT = "ieocspcert"; 87 private static final String COMMAND_OCSPCERT = "ocspcert"; 88 89 private static final String SUBJECT_PROPERTY = "subject"; 90 private static final String CAID_PROPERTY = "caid"; 91 private static final String ISSUER_PROPERTY = "issuer"; 92 private static final String SERNO_PROPERTY = "serno"; 93 private static final String LEVEL_PROPERTY = "level"; 94 private static final String MOZILLA_PROPERTY = "moz"; 95 private static final String FORMAT_PROPERTY = "format"; 96 97 private ICertificateStoreSessionLocal storesession = null; 98 private ISignSessionLocal signsession = null; 99 private ICAAdminSessionLocal casession = null; 100 101 private synchronized ISignSessionLocal getSignSession(){ 102 if(signsession == null){ 103 try { 104 ISignSessionLocalHome signhome = (ISignSessionLocalHome)ServiceLocator.getInstance().getLocalHome(ISignSessionLocalHome.COMP_NAME); 105 signsession = signhome.create(); 106 }catch(Exception e){ 107 throw new EJBException (e); 108 } 109 } 110 return signsession; 111 } 112 private synchronized ICertificateStoreSessionLocal getStoreSession(){ 113 if(storesession == null){ 114 try { 115 ICertificateStoreSessionLocalHome storehome = (ICertificateStoreSessionLocalHome)ServiceLocator.getInstance().getLocalHome(ICertificateStoreSessionLocalHome.COMP_NAME); 116 storesession = storehome.create(); 117 }catch(Exception e){ 118 throw new EJBException (e); 119 } 120 } 121 return storesession; 122 } 123 private synchronized ICAAdminSessionLocal getCASession(){ 124 if(casession == null){ 125 try { 126 ICAAdminSessionLocalHome cahome = (ICAAdminSessionLocalHome)ServiceLocator.getInstance().getLocalHome(ICAAdminSessionLocalHome.COMP_NAME); 127 casession = cahome.create(); 128 }catch(Exception e){ 129 throw new EJBException (e); 130 } 131 } 132 return casession; 133 } 134 141 public void init(ServletConfig config) throws ServletException { 142 super.init(config); 143 } 144 145 154 public void doPost(HttpServletRequest req, HttpServletResponse res) 155 throws IOException , ServletException { 156 log.debug(">doPost()"); 157 doGet(req, res); 158 log.debug("<doPost()"); 159 } 161 170 public void doGet(HttpServletRequest req, HttpServletResponse res) throws java.io.IOException , ServletException { 171 log.debug(">doGet()"); 172 173 String command; 174 String remoteAddr = req.getRemoteAddr(); 176 Admin administrator = new Admin(Admin.TYPE_PUBLIC_WEB_USER, remoteAddr); 177 178 RequestHelper.setDefaultCharacterEncoding(req); 179 String issuerdn = null; 180 if(req.getParameter(ISSUER_PROPERTY) != null){ 181 issuerdn = java.net.URLDecoder.decode(req.getParameter(ISSUER_PROPERTY),"UTF-8"); 182 issuerdn = CertTools.stringToBCDNString(issuerdn); 183 } 184 185 int caid = 0; 186 if(req.getParameter(CAID_PROPERTY) != null){ 187 caid = Integer.parseInt(req.getParameter(CAID_PROPERTY)); 188 } 189 String format = req.getParameter(FORMAT_PROPERTY); 191 command = req.getParameter(COMMAND_PROPERTY_NAME); 192 if (command == null) 193 command = ""; 194 if (command.equalsIgnoreCase(COMMAND_CRL) && issuerdn != null) { 195 try { 196 ICertificateStoreSessionLocal store = getStoreSession(); 197 byte[] crl = store.getLastCRL(administrator, issuerdn); 198 X509CRL x509crl = CertTools.getCRLfromByteArray(crl); 199 String dn = CertTools.getIssuerDN(x509crl); 200 ServletUtils.removeCacheHeaders(res); 202 String moz = req.getParameter(MOZILLA_PROPERTY); 203 String filename = CertTools.getPartFromDN(dn,"CN")+".crl"; 204 if ((moz == null) || !moz.equalsIgnoreCase("y")) { 205 res.setHeader("Content-disposition", "attachment; filename=\"" + filename+"\""); 206 } 207 res.setContentType("application/x-x509-crl"); 208 if (StringUtils.equals(format, "PEM")) { 209 RequestHelper.sendNewB64File(Base64.encode(crl, true), res, filename, RequestHelper.BEGIN_CRL_WITH_NL, RequestHelper.END_CRL_WITH_NL); 210 } else { 211 res.setContentLength(crl.length); 212 res.getOutputStream().write(crl); 213 } 214 log.debug("Sent latest CRL to client at " + remoteAddr); 215 } catch (Exception e) { 216 log.debug("Error sending latest CRL to " + remoteAddr+": ", e); 217 res.sendError(HttpServletResponse.SC_NOT_FOUND, "Error getting latest CRL."); 218 return; 219 } 220 } else if (command.equalsIgnoreCase(COMMAND_CERT) || command.equalsIgnoreCase(COMMAND_LISTCERT)) { 221 String dn = java.net.URLDecoder.decode(req.getParameter(SUBJECT_PROPERTY),"UTF-8"); 222 if (dn == null) { 223 log.debug("Bad request, no 'subject' arg to 'lastcert' or 'listcert' command."); 224 res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Usage command=lastcert/listcert?subject=<subjectdn>."); 225 return; 226 } 227 try { 228 log.debug("Looking for certificates for '"+dn+"'."); 229 ICertificateStoreSessionLocal store = getStoreSession(); 230 Collection certcoll = store.findCertificatesBySubject(administrator, dn); 231 Object [] certs = certcoll.toArray(); 232 int latestcertno = -1; 233 if (command.equalsIgnoreCase(COMMAND_CERT)) { 234 long maxdate = 0; 235 for (int i=0;i<certs.length;i++) { 236 if (i == 0) { 237 maxdate = ((X509Certificate )certs[i]).getNotBefore().getTime(); 238 latestcertno = 0; 239 } 240 else if ( ((X509Certificate )certs[i]).getNotBefore().getTime() > maxdate ) { 241 maxdate = ((X509Certificate )certs[i]).getNotBefore().getTime(); 242 latestcertno = i; 243 } 244 } 245 if (latestcertno > -1) { 246 byte[] cert = ((X509Certificate )certs[latestcertno]).getEncoded(); 247 String filename = CertTools.getPartFromDN(dn,"CN")+".cer"; 248 ServletUtils.removeCacheHeaders(res); 250 res.setHeader("Content-disposition", "attachment; filename=\"" + filename+"\""); 251 res.setContentType("application/octet-stream"); 252 if (StringUtils.equals(format, "PEM")) { 253 RequestHelper.sendNewB64File(Base64.encode(cert, true), res, filename, RequestHelper.BEGIN_CERTIFICATE_WITH_NL, RequestHelper.END_CERTIFICATE_WITH_NL); 254 } else { 255 res.setContentLength(cert.length); 256 res.getOutputStream().write(cert); 257 } 258 log.debug("Sent latest certificate for '"+dn+"' to client at " + remoteAddr); 259 260 } else { 261 log.debug("No certificate found for '"+dn+"'."); 262 res.sendError(HttpServletResponse.SC_NOT_FOUND, "No certificate found for requested subject '"+dn+"'."); 263 } 264 } 265 if (command.equalsIgnoreCase(COMMAND_LISTCERT)) { 266 res.setContentType("text/html"); 267 PrintWriter pout = new PrintWriter (res.getOutputStream()); 268 printHtmlHeader("Certificates for "+dn, pout); 269 for (int i=0;i<certs.length;i++) { 270 Date notBefore = ((X509Certificate )certs[i]).getNotBefore(); 271 Date notAfter = ((X509Certificate )certs[i]).getNotAfter(); 272 String subject = CertTools.getSubjectDN((X509Certificate )certs[i]); 273 String issuer = CertTools.getIssuerDN((X509Certificate )certs[i]); 274 BigInteger serno = ((X509Certificate )certs[i]).getSerialNumber(); 275 pout.println("<pre>Subject:"+subject); 276 pout.println("Issuer:"+issuer); 277 pout.println("NotBefore:"+notBefore.toString()); 278 pout.println("NotAfter:"+notAfter.toString()); 279 pout.println("Serial number:"+serno.toString()); 280 pout.println("</pre>"); 281 pout.println("<a HREF=\"certdist?cmd=revoked&issuer="+URLEncoder.encode(issuer, "UTF-8")+"&serno="+serno.toString()+"\">Check if certificate is revoked</a>"); 282 pout.println("<hr>"); 283 284 } 285 if (certs.length == 0) { 286 pout.println("No certificates exists for '"+dn+"'."); 287 } 288 printHtmlFooter(pout); 289 pout.close(); 290 } 291 } catch (Exception e) { 292 log.debug("Error getting certificates for '"+dn+"' for "+remoteAddr+": ", e); 293 res.sendError(HttpServletResponse.SC_NOT_FOUND, "Error getting certificates."); 294 return; 295 } 296 } else if ((command.equalsIgnoreCase(COMMAND_NSCACERT) || command.equalsIgnoreCase(COMMAND_IECACERT) || command.equalsIgnoreCase(COMMAND_CACERT)) && ( issuerdn != null || caid != 0)) { 297 String lev = req.getParameter(LEVEL_PROPERTY); 298 int level = 0; 299 boolean pkcs7 = false; 300 if (lev != null) 301 level = Integer.parseInt(lev); 302 else 303 pkcs7 = true; 304 try { 306 ISignSessionLocal ss = getSignSession(); 307 Certificate [] chain = null; 308 if(caid != 0) { 309 chain = (Certificate []) ss.getCertificateChain(administrator, caid).toArray(new Certificate [0]); 310 } 311 else { 312 chain = (Certificate []) ss.getCertificateChain(administrator, issuerdn.hashCode()).toArray(new Certificate [0]); 313 } 314 if (chain.length < level) { 316 PrintStream ps = new PrintStream (res.getOutputStream()); 317 ps.println("No CA certificate of level "+level+" exist."); 318 log.debug("No CA certificate of level "+level+" exist."); 319 return; 320 } 321 X509Certificate cacert = (X509Certificate )chain[level]; 322 String filename=CertTools.getPartFromDN(CertTools.getSubjectDN(cacert), "CN"); 323 if (filename == null) 324 filename = "ca"; 325 byte[] enccert = null; 326 if (pkcs7) 327 enccert = ss.createPKCS7(administrator, cacert, true); 328 else 329 enccert = cacert.getEncoded(); 330 if (command.equalsIgnoreCase(COMMAND_NSCACERT)) { 331 res.setContentType("application/x-x509-ca-cert"); 332 res.setContentLength(enccert.length); 333 res.getOutputStream().write(enccert); 334 log.debug("Sent CA cert to NS client, len="+enccert.length+"."); 335 } else if (command.equalsIgnoreCase(COMMAND_IECACERT)) { 336 ServletUtils.removeCacheHeaders(res); 338 if (pkcs7) 339 res.setHeader("Content-disposition", "attachment; filename=\""+filename+".p7c\""); 340 else 341 res.setHeader("Content-disposition", "attachment; filename=\""+filename+".crt\""); 342 res.setContentType("application/octet-stream"); 343 res.setContentLength(enccert.length); 344 res.getOutputStream().write(enccert); 345 log.debug("Sent CA cert to IE client, len="+enccert.length+"."); 346 } else if (command.equalsIgnoreCase(COMMAND_CACERT)) { 347 byte[] b64cert = Base64.encode(enccert); 348 String out; 349 if (pkcs7) 350 out = "-----BEGIN PKCS7-----\n"; 351 else 352 out = "-----BEGIN CERTIFICATE-----\n"; 353 out += new String (b64cert); 354 if (pkcs7) 355 out += "\n-----END PKCS7-----\n"; 356 else 357 out += "\n-----END CERTIFICATE-----\n"; 358 ServletUtils.removeCacheHeaders(res); 360 res.setHeader("Content-disposition", "attachment; filename=\""+filename+".pem\""); 361 res.setContentType("application/octet-stream"); 362 res.setContentLength(out.length()); 363 res.getOutputStream().write(out.getBytes()); 364 log.debug("Sent CA cert to client, len="+out.length()+"."); 365 } else { 366 res.setContentType("text/plain"); 367 res.getOutputStream().println("Commands="+COMMAND_NSCACERT+" || "+COMMAND_IECACERT+" || "+COMMAND_CACERT); 368 return; 369 } 370 } catch (Exception e) { 371 log.debug("Error getting CA certificates: ", e); 372 res.sendError(HttpServletResponse.SC_NOT_FOUND, "Error getting CA certificates."); 373 return; 374 } 375 } else if ((command.equalsIgnoreCase(COMMAND_NSOCSPCERT) || command.equalsIgnoreCase(COMMAND_IEOCSPCERT) || command.equalsIgnoreCase(COMMAND_OCSPCERT)) && ( issuerdn != null || caid != 0)) { 376 try { 377 ICAAdminSessionLocal casession = getCASession(); 378 CAInfo cainfo = null; 379 if(caid != 0) { 380 cainfo = casession.getCAInfo(administrator, caid); 381 } else { 382 int id = issuerdn.hashCode(); 383 cainfo = casession.getCAInfo(administrator, id); 384 } 385 X509Certificate ocspcert = null; 386 Iterator iter = cainfo.getExtendedCAServiceInfos().iterator(); 387 while(iter.hasNext()){ 388 ExtendedCAServiceInfo next = (ExtendedCAServiceInfo) iter.next(); 389 if(next instanceof OCSPCAServiceInfo){ 390 if(((OCSPCAServiceInfo) next).getOCSPSignerCertificatePath() != null) 391 ocspcert = (X509Certificate ) ((OCSPCAServiceInfo) next).getOCSPSignerCertificatePath().get(0); 392 } 393 } 394 if (ocspcert == null) { 396 res.sendError(HttpServletResponse.SC_NOT_FOUND, "No OCSP certificate found for CA."); 397 return; 398 } 399 String filename=CertTools.getPartFromDN(CertTools.getSubjectDN(ocspcert), "CN"); 400 if (filename == null) 401 filename = "ocsp"; 402 byte[] enccert = null; 403 enccert = ocspcert.getEncoded(); 404 if (command.equalsIgnoreCase(COMMAND_NSOCSPCERT)) { 405 res.setContentType("application/x-x509-ca-cert"); 406 res.setContentLength(enccert.length); 407 res.getOutputStream().write(enccert); 408 log.debug("Sent OCSP cert to NS client, len="+enccert.length+"."); 409 } else if (command.equalsIgnoreCase(COMMAND_IEOCSPCERT)) { 410 ServletUtils.removeCacheHeaders(res); 412 res.setHeader("Content-disposition", "attachment; filename=\""+filename+".crt\""); 413 res.setContentType("application/octet-stream"); 414 res.setContentLength(enccert.length); 415 res.getOutputStream().write(enccert); 416 log.debug("Sent OCSP cert to IE client, len="+enccert.length+"."); 417 } else if (command.equalsIgnoreCase(COMMAND_OCSPCERT)) { 418 byte[] b64cert = Base64.encode(enccert); 419 String out; 420 out = "-----BEGIN CERTIFICATE-----\n"; 421 out += new String (b64cert); 422 out += "\n-----END CERTIFICATE-----\n"; 423 ServletUtils.removeCacheHeaders(res); 425 res.setHeader("Content-disposition", "attachment; filename=\""+filename+".pem\""); 426 res.setContentType("application/octet-stream"); 427 res.setContentLength(out.length()); 428 res.getOutputStream().write(out.getBytes()); 429 log.debug("Sent OCSP cert to client, len="+out.length()+"."); 430 } else { 431 res.setContentType("text/plain"); 432 res.getOutputStream().println("Commands="+COMMAND_NSCACERT+" || "+COMMAND_IECACERT+" || "+COMMAND_CACERT); 433 return; 434 } 435 } catch (Exception e) { 436 log.debug("Error getting OCSP certificate for CA: ", e); 437 res.sendError(HttpServletResponse.SC_NOT_FOUND, "Error getting OCSP certificate for CA."); 438 return; 439 } 440 } else if (command.equalsIgnoreCase(COMMAND_REVOKED)) { 441 String dn = req.getParameter(ISSUER_PROPERTY); 442 if (dn == null) { 443 log.debug("Bad request, no 'issuer' arg to 'revoked' command."); 444 res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Usage command=revoked?issuer=<issuerdn>&serno=<serialnumber>."); 445 return; 446 } 447 String serno = req.getParameter(SERNO_PROPERTY); 448 if (serno == null) { 449 log.debug("Bad request, no 'serno' arg to 'revoked' command."); 450 res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Usage command=revoked?issuer=<issuerdn>&serno=<serialnumber>."); 451 return; 452 } 453 log.debug("Looking for certificate for '"+dn+"' and serno='"+serno+"'."); 454 try { 455 ICertificateStoreSessionLocal store = getStoreSession(); 456 RevokedCertInfo revinfo = store.isRevoked(administrator, dn, new BigInteger (serno)); 457 PrintWriter pout = new PrintWriter (res.getOutputStream()); 458 res.setContentType("text/html"); 459 printHtmlHeader("Check revocation", pout); 460 if (revinfo != null) { 461 if (revinfo.getReason() == RevokedCertInfo.NOT_REVOKED) { 462 pout.println("<h1>NOT REVOKED</h1>"); 463 pout.println("Certificate with issuer '"+dn+"' and serial number '"+serno+"' is NOT revoked."); 464 } else { 465 pout.println("<h1>REVOKED</h1>"); 466 pout.println("Certificate with issuer '"+dn+"' and serial number '"+serno+"' is revoked."); 467 pout.println("RevocationDate is '"+revinfo.getRevocationDate()+"' and reason '"+revinfo.getReason()+"'."); 468 } 469 } else { 470 pout.println("<h1>CERTIFICATE DOES NOT EXIST</h1>"); 471 pout.println("Certificate with issuer '"+dn+"' and serial number '"+serno+"' does not exist."); 472 } 473 printHtmlFooter(pout); 474 pout.close(); 475 } catch (Exception e) { 476 log.debug("Error checking revocation for '"+dn+"' with serno '"+serno+"': ", e); 477 res.sendError(HttpServletResponse.SC_NOT_FOUND, "Error checking revocation."); 478 return; 479 } 480 } else { 481 res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Commands=cacert | lastcert | listcerts | crl | revoked && issuer=<issuerdn>"); 482 return; 483 } 484 485 } 487 private void printHtmlHeader(String title, PrintWriter pout) { 488 pout.println("<html><head>"); 489 pout.println("<title>"+title+"</title>"); 490 pout.println("<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">"); 491 pout.println("<META HTTP-EQUIV=\"Expires\" CONTENT=\"-1\">"); 492 pout.println("</head>"); 493 pout.println("<body><p>"); 494 } 495 private void printHtmlFooter(PrintWriter pout) { 496 pout.println("</body>"); 497 pout.println("<head>"); 498 pout.println("<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">"); 499 pout.println("<META HTTP-EQUIV=\"Expires\" CONTENT=\"-1\">"); 500 pout.println("</head>"); 501 pout.println("</html>"); 502 } 503 504 } 505 | Popular Tags |