KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejbca > ui > web > pub > CardCertReqServlet


1 /*************************************************************************
2  * *
3  * EJBCA: The OpenSource Certificate Authority *
4  * *
5  * This software is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU Lesser General Public *
7  * License as published by the Free Software Foundation; either *
8  * version 2.1 of the License, or any later version. *
9  * *
10  * See terms of license at gnu.org. *
11  * *
12  *************************************************************************/

13  
14 package org.ejbca.ui.web.pub;
15
16 import java.io.BufferedReader JavaDoc;
17 import java.io.IOException JavaDoc;
18 import java.io.InputStreamReader JavaDoc;
19 import java.io.OutputStream JavaDoc;
20 import java.io.PrintWriter JavaDoc;
21 import java.io.StringWriter JavaDoc;
22 import java.rmi.RemoteException JavaDoc;
23 import java.security.cert.X509Certificate JavaDoc;
24 import java.util.Enumeration JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Set JavaDoc;
28
29 import javax.ejb.CreateException JavaDoc;
30 import javax.ejb.ObjectNotFoundException JavaDoc;
31 import javax.naming.InitialContext JavaDoc;
32 import javax.rmi.PortableRemoteObject JavaDoc;
33 import javax.servlet.ServletConfig JavaDoc;
34 import javax.servlet.ServletContext JavaDoc;
35 import javax.servlet.ServletException JavaDoc;
36 import javax.servlet.http.HttpServlet JavaDoc;
37 import javax.servlet.http.HttpServletRequest JavaDoc;
38 import javax.servlet.http.HttpServletResponse JavaDoc;
39
40 import org.apache.log4j.Logger;
41 import org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionHome;
42 import org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionRemote;
43 import org.ejbca.core.ejb.ca.sign.ISignSessionHome;
44 import org.ejbca.core.ejb.ca.sign.ISignSessionRemote;
45 import org.ejbca.core.ejb.ca.store.ICertificateStoreSessionHome;
46 import org.ejbca.core.ejb.ca.store.ICertificateStoreSessionRemote;
47 import org.ejbca.core.ejb.hardtoken.IHardTokenSessionHome;
48 import org.ejbca.core.ejb.ra.IUserAdminSessionHome;
49 import org.ejbca.core.ejb.ra.IUserAdminSessionRemote;
50 import org.ejbca.core.model.SecConst;
51 import org.ejbca.core.model.ca.AuthLoginException;
52 import org.ejbca.core.model.ca.AuthStatusException;
53 import org.ejbca.core.model.ca.IllegalKeyException;
54 import org.ejbca.core.model.ca.SignRequestException;
55 import org.ejbca.core.model.ca.SignRequestSignatureException;
56 import org.ejbca.core.model.ca.caadmin.CAInfo;
57 import org.ejbca.core.model.ca.crl.RevokedCertInfo;
58 import org.ejbca.core.model.hardtoken.profiles.EIDProfile;
59 import org.ejbca.core.model.hardtoken.profiles.HardTokenProfile;
60 import org.ejbca.core.model.hardtoken.profiles.SwedishEIDProfile;
61 import org.ejbca.core.model.log.Admin;
62 import org.ejbca.core.model.ra.UserDataConstants;
63 import org.ejbca.core.model.ra.UserDataVO;
64 import org.ejbca.core.protocol.IResponseMessage;
65 import org.ejbca.core.protocol.PKCS10RequestMessage;
66 import org.ejbca.ui.web.RequestHelper;
67 import org.ejbca.util.Base64;
68 import org.ejbca.util.CertTools;
69
70
71 /**
72  * Servlet used to install a private key with a corresponding certificate in a browser. A new
73  * certificate is installed in the browser in following steps:<br>
74  * 1. The key pair is generated by the browser. <br>
75  * 2. The public part is sent to the servlet in a POST together with user info ("pkcs10|keygen",
76  * "inst", "user", "password"). For internet explorer the public key is sent as a PKCS10
77  * certificate request. <br>
78  * 3. The new certificate is created by calling the RSASignSession session bean. <br>
79  * 4. A page containing the new certificate and a script that installs it is returned to the
80  * browser. <br>
81  *
82  * <p></p>
83  *
84  * <p>
85  * The following initiation parameters are needed by this servlet: <br>
86  * "responseTemplate" file that defines the response to the user (IE). It should have one line
87  * with the text "cert =". This line is replaced with the new certificate. "keyStorePass".
88  * Password needed to load the key-store. If this parameter is none existing it is assumed that no
89  * password is needed. The path could be absolute or relative.<br>
90  * </p>
91  *
92  * @author Original code by Lars Silvén
93  * @version $Id: CardCertReqServlet.java,v 1.13 2007/01/03 14:34:11 anatom Exp $
94  */

95 public class CardCertReqServlet extends HttpServlet JavaDoc {
96     private final static Logger log = Logger.getLogger(CardCertReqServlet.class);
97     private ISignSessionHome signsessionhome = null;
98     private IUserAdminSessionHome useradminhome = null;
99     private ICertificateStoreSessionHome certificatestorehome = null;
100     private ICAAdminSessionHome caadminsessionhome = null;
101     private IHardTokenSessionHome tokenSessionHome = null;
102
103     /**
104      * Servlet init
105      *
106      * @param config servlet configuration
107      *
108      * @throws ServletException on error
109      */

110     public void init(ServletConfig JavaDoc config) throws ServletException JavaDoc {
111         super.init(config);
112
113         try {
114             // Install BouncyCastle provider
115
CertTools.installBCProvider();
116
117             // Get EJB context and home interfaces
118
InitialContext JavaDoc ctx = new InitialContext JavaDoc();
119             signsessionhome = (ISignSessionHome) PortableRemoteObject.narrow(
120                       ctx.lookup("RSASignSession"), ISignSessionHome.class );
121             useradminhome = (IUserAdminSessionHome) PortableRemoteObject.narrow(
122                              ctx.lookup("UserAdminSession"), IUserAdminSessionHome.class );
123             certificatestorehome = (ICertificateStoreSessionHome) PortableRemoteObject.narrow(
124                     ctx.lookup("CertificateStoreSession"), ICertificateStoreSessionHome.class );
125             caadminsessionhome = (ICAAdminSessionHome) javax.rmi.PortableRemoteObject.narrow(ctx.lookup("CAAdminSession"),
126                                                                                              ICAAdminSessionHome.class);
127             tokenSessionHome = (IHardTokenSessionHome)javax.rmi.PortableRemoteObject.narrow(ctx.lookup("HardTokenSession"),
128                                                                                             IHardTokenSessionHome.class);
129         } catch( Exception JavaDoc e ) {
130             throw new ServletException JavaDoc(e);
131         }
132     }
133
134     /**
135      * Handles HTTP POST
136      *
137      * @param request servlet request
138      * @param response servlet response
139      *
140      * @throws IOException input/output error
141      * @throws ServletException on error
142      */

143     public void doPost(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
144     throws IOException JavaDoc, ServletException JavaDoc {
145         final ServletDebug debug = new ServletDebug(request, response);
146         boolean usekeyrecovery = false;
147         try {
148             Admin administrator = new Admin(Admin.TYPE_RA_USER);
149             ICertificateStoreSessionRemote certificatestoresession = certificatestorehome.create();
150             final String JavaDoc username; {
151                 Object JavaDoc o = request.getAttribute("javax.servlet.request.X509Certificate");
152                 final X509Certificate JavaDoc[] certs;
153                 if ( o!=null && o instanceof X509Certificate JavaDoc[] )
154                     certs = (X509Certificate JavaDoc[])o;
155                 else
156                     throw new AuthLoginException("No authenicating certificate");
157                 RevokedCertInfo rci=certificatestoresession.isRevoked(administrator, certs[0].getIssuerDN().getName(),
158                                                                       certs[0].getSerialNumber());
159                 if ( rci==null || rci.getReason()!=RevokedCertInfo.NOT_REVOKED )
160                     throw new UserCertificateRevokedException(certs[0]);
161                 username = certificatestoresession.findUsernameByCertSerno(administrator,
162                         certs[0].getSerialNumber(), certs[0].getIssuerX500Principal().toString());
163                 if ( username==null || username.length()==0 )
164                     throw new ObjectNotFoundException JavaDoc("Not possible to retrieve user name");
165             }
166             IUserAdminSessionRemote adminsession = useradminhome.create();
167             ISignSessionRemote signsession = signsessionhome.create();
168             log.debug("Got request for " + username + ".");
169             debug.print("<h3>username: " + username + "</h3>");
170             
171             final UserDataVO data = adminsession.findUser(administrator, username);
172             final X509Certificate JavaDoc notRevokedCerts[]; {
173                 Set JavaDoc set = new HashSet JavaDoc();
174                 for( Iterator JavaDoc i = certificatestoresession.findCertificatesByUsername(administrator, username).iterator(); i.hasNext(); ) {
175                     Object JavaDoc o = i.next();
176                     if ( o instanceof X509Certificate JavaDoc ) {
177                         X509Certificate JavaDoc cert = (X509Certificate JavaDoc)o;
178                         RevokedCertInfo rci=certificatestoresession.isRevoked(administrator, cert.getIssuerDN().getName(), cert.getSerialNumber());
179                         if ( rci!=null && rci.getReason()==RevokedCertInfo.NOT_REVOKED )
180                             set.add(cert);
181                     }
182                 }
183                 notRevokedCerts = (X509Certificate JavaDoc[])set.toArray(new X509Certificate JavaDoc[0]);
184             }
185             if (data == null)
186                 throw new ObjectNotFoundException JavaDoc();
187             
188             final String JavaDoc authReq = request.getParameter("authpkcs10");
189             final String JavaDoc signReq = request.getParameter("signpkcs10");
190             
191             if ( authReq!=null && signReq!=null ) {
192                 final int authCertProfile;
193                 final int signCertProfile;
194                 final HardTokenProfile hardTokenProfile = tokenSessionHome.create().getHardTokenProfile(administrator, data.getTokenType());
195                 {
196                     CertProfileID certProfileID = new CertProfileID(certificatestoresession, data, administrator,
197                                                                     hardTokenProfile);
198                     authCertProfile = certProfileID.getProfileID("authCertProfile", SwedishEIDProfile.CERTUSAGE_AUTHENC);
199                     signCertProfile = certProfileID.getProfileID("signCertProfile", SwedishEIDProfile.CERTUSAGE_SIGN);
200                 }
201                 final int authCA;
202                 final int signCA;
203                 {
204                     CAID caid = new CAID(data,administrator, hardTokenProfile);
205                     authCA = caid.getProfileID("authCA", SwedishEIDProfile.CERTUSAGE_AUTHENC);
206                     signCA = caid.getProfileID("signCA", SwedishEIDProfile.CERTUSAGE_SIGN);
207                 }
208                 // if not IE, check if it's manual request
209
final byte[] authReqBytes = authReq.getBytes();
210                 final byte[] signReqBytes = signReq.getBytes();
211                 if ( authReqBytes!=null && signReqBytes!=null) {
212                     try {
213                     adminsession.changeUser(administrator, username,data.getPassword(), data.getDN(), data.getSubjectAltName(),
214                                             data.getEmail(), true, data.getEndEntityProfileId(), authCertProfile, data.getType(),
215                                             SecConst.TOKEN_SOFT_BROWSERGEN, 0, data.getStatus(), authCA);
216                     final byte[] authb64cert=pkcs10CertRequest(administrator, signsession, authReqBytes, username, data.getPassword());
217
218                     adminsession.changeUser(administrator, username, data.getPassword(), data.getDN(), data.getSubjectAltName(),
219                                             data.getEmail(), true, data.getEndEntityProfileId(), signCertProfile, data.getType(),
220                                             SecConst.TOKEN_SOFT_BROWSERGEN, 0, UserDataConstants.STATUS_NEW, signCA);
221                     final byte[] signb64cert=pkcs10CertRequest(administrator, signsession, signReqBytes, username, data.getPassword());
222
223
224                     for (int i=0; i<notRevokedCerts.length; i++)
225                         adminsession.revokeCert(administrator, notRevokedCerts[i].getSerialNumber(),
226                                                 notRevokedCerts[i].getIssuerDN().toString(), username,
227                                                 RevokedCertInfo.REVOKATION_REASON_SUPERSEDED);
228
229                     sendCertificates(authb64cert, signb64cert, response, getServletContext(),
230                                      getInitParameter("responseTemplate"), notRevokedCerts);
231                     } catch( Throwable JavaDoc t ) {
232                         if (t instanceof Exception JavaDoc)
233                             throw (Exception JavaDoc)t;
234                         else
235                             throw new Error JavaDoc(t);
236                     } finally {
237                         data.setStatus(UserDataConstants.STATUS_GENERATED);
238                         adminsession.changeUser(administrator, data, true); // set back to original values
239
}
240                 }
241             }
242         } catch( UserCertificateRevokedException e) {
243             log.error("An error revoking certificaates occured: ", e);
244             debug.printMessage(e.getMessage());
245             debug.printDebugInfo();
246             return;
247         } catch (ObjectNotFoundException JavaDoc oe) {
248             log.error("Non existent username!", oe);
249             debug.printMessage("Non existent username!");
250             debug.printDebugInfo();
251             return;
252         } catch (AuthStatusException ase) {
253             log.error("Wrong user status!", ase);
254             debug.printMessage("Wrong user status!");
255             if (usekeyrecovery) {
256                 debug.printMessage(
257                 "To generate a certificate for a user the user must have status new, failed or inprocess.");
258             } else {
259                 debug.printMessage(
260                 "To generate a certificate for a user the user must have status new, failed or inprocess.");
261             }
262             debug.printDebugInfo();
263             return;
264         } catch (AuthLoginException ale) {
265             log.error("Wrong password for user!", ale);
266             debug.printMessage("Wrong username or password!");
267             debug.printDebugInfo();
268             return;
269         } catch (SignRequestException re) {
270             log.error("Invalid request!", re);
271             debug.printMessage("Invalid request!");
272             debug.printMessage("Please supply a correct request.");
273             debug.printDebugInfo();
274             return;
275         } catch (SignRequestSignatureException se) {
276             log.error("Invalid signature on certificate request!", se);
277             debug.printMessage("Invalid signature on certificate request!");
278             debug.printMessage("Please supply a correctly signed request.");
279             debug.printDebugInfo();
280             return;
281         } catch (java.lang.ArrayIndexOutOfBoundsException JavaDoc ae) {
282             log.error("Empty or invalid request received.", ae);
283             debug.printMessage("Empty or invalid request!");
284             debug.printMessage("Please supply a correct request.");
285             debug.printDebugInfo();
286             return;
287         } catch (IllegalKeyException e) {
288             log.error("Illegal Key received: ", e);
289             debug.printMessage("Invalid Key in request: "+e.getMessage());
290             debug.printMessage("Please supply a correct request.");
291             debug.printDebugInfo();
292             return;
293         } catch (Exception JavaDoc e) {
294             log.error("Exception occured: ", e);
295             debug.print("<h3>parameter name and values: </h3>");
296             Enumeration JavaDoc paramNames = request.getParameterNames();
297             while (paramNames.hasMoreElements()) {
298                 String JavaDoc name = paramNames.nextElement().toString();
299                 String JavaDoc parameter = request.getParameter(name);
300                 debug.print("<h4>" + name + ":</h4>" + parameter + "<br>");
301             }
302             debug.takeCareOfException(e);
303             debug.printDebugInfo();
304         }
305     } //doPost
306

307     private class UserCertificateRevokedException extends Exception JavaDoc {
308         UserCertificateRevokedException(X509Certificate JavaDoc cert) {
309             super("User certificate with serial number "+cert.getSerialNumber() +
310                   " from issuer \'"+cert.getIssuerX500Principal()+"\' is revoked.");
311         }
312     }
313     private class CAID extends BaseID {
314         final private ICAAdminSessionRemote caadminsession;
315         CAID(UserDataVO d, Admin a, HardTokenProfile hardTokenProfile) throws RemoteException JavaDoc, CreateException JavaDoc {
316             super(d, a, hardTokenProfile);
317             caadminsession = caadminsessionhome.create();
318         }
319         protected int getFromName(String JavaDoc name) throws RemoteException JavaDoc {
320             CAInfo caInfo = caadminsession.getCAInfo(administrator, name);
321             if ( caInfo!=null )
322                 return caInfo.getCAId();
323             else
324                 return 0;
325         }
326         protected int getFromOldData() {
327             return data.getCAId();
328         }
329         protected int getFromHardToken(int keyType) {
330             final int id = hardTokenProfile.getCAId(keyType);
331             if ( id!=EIDProfile.CAID_USEUSERDEFINED )
332                 return id;
333             else
334                 return data.getCAId();
335         }
336     }
337     private class CertProfileID extends BaseID {
338         final ICertificateStoreSessionRemote certificatestoresession;
339         CertProfileID(ICertificateStoreSessionRemote c, UserDataVO d, Admin a,
340                       HardTokenProfile hardTokenProfile) throws RemoteException JavaDoc, CreateException JavaDoc {
341             super(d, a, hardTokenProfile);
342             certificatestoresession = c;
343         }
344         protected int getFromName(String JavaDoc name) throws RemoteException JavaDoc {
345             return certificatestoresession.getCertificateProfileId(administrator, name);
346         }
347         protected int getFromOldData() {
348             return data.getCertificateProfileId();
349         }
350         protected int getFromHardToken(int keyType) {
351             return hardTokenProfile.getCertificateProfileId(keyType);
352         }
353     }
354     private abstract class BaseID {
355         final UserDataVO data;
356         final Admin administrator;
357         final EIDProfile hardTokenProfile;
358         
359         protected abstract int getFromHardToken(int keyType);
360         protected abstract int getFromName(String JavaDoc name) throws RemoteException JavaDoc;
361         protected abstract int getFromOldData();
362         BaseID(UserDataVO d, Admin a, HardTokenProfile htp) {
363             data = d;
364             administrator = a;
365             if ( htp!=null && htp instanceof EIDProfile )
366                 hardTokenProfile = (EIDProfile)htp;
367             else
368                 hardTokenProfile = null;
369         }
370         public int getProfileID(String JavaDoc parameterName, int keyType) throws RemoteException JavaDoc {
371             if ( hardTokenProfile!=null )
372                 return getFromHardToken(keyType);
373             String JavaDoc name = CardCertReqServlet.this.getInitParameter(parameterName);
374             if ( name!=null && name.length()>0 ) {
375                 final int id = getFromName(name);
376                 log.debug("parameter name "+parameterName+" has ID "+id);
377                 if (id!=0)
378                     return id;
379             }
380             return getFromOldData();
381         }
382     }
383     /**
384      * Handles HTTP GET
385      *
386      * @param request servlet request
387      * @param response servlet response
388      *
389      * @throws IOException input/output error
390      * @throws ServletException on error
391      */

392     public void doGet(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
393         throws IOException JavaDoc, ServletException JavaDoc {
394         log.debug(">doGet()");
395         response.setHeader("Allow", "POST");
396
397         ServletDebug debug = new ServletDebug(request, response);
398         debug.print("The certificate request servlet only handles POST method.");
399         debug.printDebugInfo();
400         log.debug("<doGet()");
401     }
402
403     // doGet
404

405     
406     /**
407      * Reads template and inserts cert to send back to netid for installation of cert
408      *
409      * @param b64cert cert to be installed in netid
410      * @param response utput stream to send to
411      * @param sc serveltcontext
412      * @param responseTemplate path to responseTemplate
413      * @param notRevokedCerts
414      * @param classid replace
415      *
416      * @throws Exception on error
417      */

418     private static void sendCertificates(byte[] authb64cert,byte[] signb64cert, HttpServletResponse JavaDoc response, ServletContext JavaDoc sc,
419         String JavaDoc responseTemplate, X509Certificate JavaDoc[] notRevokedCerts) throws Exception JavaDoc {
420         if (authb64cert.length == 0 || signb64cert.length == 0) {
421             log.error("0 length certificate can not be sent to client!");
422             return;
423         }
424         StringWriter JavaDoc sw = new StringWriter JavaDoc();
425         {
426             BufferedReader JavaDoc br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(sc.getResourceAsStream(responseTemplate)));
427             PrintWriter JavaDoc pw = new PrintWriter JavaDoc(sw);
428             while (true) {
429                 String JavaDoc line = br.readLine();
430                 if (line == null)
431                     break;
432                 line = line.replaceAll("TAG_authb64cert",new String JavaDoc(authb64cert));
433                 line = line.replaceAll("TAG_signb64cert",new String JavaDoc(signb64cert));
434                 if ( notRevokedCerts.length > 0 )
435                     line = line.replaceAll("TAG_certToRemove1",new String JavaDoc(Base64.encode(notRevokedCerts[0].getEncoded(),false)));
436                 if ( notRevokedCerts.length > 1 )
437                     line = line.replaceAll("TAG_certToRemove2",new String JavaDoc(Base64.encode(notRevokedCerts[1].getEncoded(),false)));
438                 if ( notRevokedCerts.length > 2 )
439                     line = line.replaceAll("TAG_certToRemove3",new String JavaDoc(Base64.encode(notRevokedCerts[2].getEncoded(),false)));
440                 if ( notRevokedCerts.length > 3 )
441                     line = line.replaceAll("TAG_certToRemove4",new String JavaDoc(Base64.encode(notRevokedCerts[3].getEncoded(),false)));
442                 pw.println(line);
443             }
444             pw.close();
445             sw.flush();
446         }
447         {
448             OutputStream JavaDoc out = response.getOutputStream();
449             PrintWriter JavaDoc pw = new PrintWriter JavaDoc(out);
450             log.debug(sw);
451             pw.print(sw);
452             pw.close();
453             out.flush();
454         }
455     } // sendCertificates
456

457     /**
458      * Handles PKCS10 certificate request, these are constructed as: <code> CertificationRequest
459      * ::= SEQUENCE { certificationRequestInfo CertificationRequestInfo, signatureAlgorithm
460      * AlgorithmIdentifier{{ SignatureAlgorithms }}, signature BIT STRING }
461      * CertificationRequestInfo ::= SEQUENCE { version INTEGER { v1(0) } (v1,...),
462      * subject Name, subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
463      * attributes [0] Attributes{{ CRIAttributes }}} SubjectPublicKeyInfo { ALGORITHM :
464      * IOSet} ::= SEQUENCE { algorithm AlgorithmIdentifier {{IOSet}}, subjectPublicKey
465      * BIT STRING }</code> PublicKey's encoded-format has to be RSA X.509.
466      *
467      * @param signsession signsession to get certificate from
468      * @param b64Encoded base64 encoded pkcs10 request message
469      * @param username username of requesting user
470      * @param password password of requesting user
471      * @param resulttype should indicate if a PKCS7 or just the certificate is wanted.
472      *
473      * @return Base64 encoded byte[]
474      */

475     private byte[] pkcs10CertRequest(Admin administrator, ISignSessionRemote signsession, byte[] b64Encoded,
476         String JavaDoc username, String JavaDoc password) throws Exception JavaDoc {
477         byte[] result = null;
478         X509Certificate JavaDoc cert=null;
479         PKCS10RequestMessage req = RequestHelper.genPKCS10RequestMessageFromPEM(b64Encoded);
480         req.setUsername(username);
481         req.setPassword(password);
482         IResponseMessage resp = signsession.createCertificate(administrator,req,Class.forName("org.ejbca.core.protocol.X509ResponseMessage"));
483         cert = CertTools.getCertfromByteArray(resp.getResponseMessage());
484           result = cert.getEncoded();
485
486         return Base64.encode(result, false);
487     } //pkcs10CertReq
488
}
489
490
491 // CertReqServlet
492
Popular Tags