KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejbca > ui > web > RequestHelper


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;
15
16 import java.io.BufferedReader JavaDoc;
17 import java.io.ByteArrayInputStream JavaDoc;
18 import java.io.IOException JavaDoc;
19 import java.io.InputStreamReader JavaDoc;
20 import java.io.OutputStream JavaDoc;
21 import java.io.PrintStream JavaDoc;
22 import java.io.PrintWriter JavaDoc;
23 import java.io.StringWriter JavaDoc;
24 import java.io.UnsupportedEncodingException JavaDoc;
25 import java.security.cert.X509Certificate JavaDoc;
26 import java.util.regex.Pattern JavaDoc;
27
28 import javax.servlet.ServletContext JavaDoc;
29 import javax.servlet.ServletOutputStream JavaDoc;
30 import javax.servlet.http.HttpServletRequest JavaDoc;
31 import javax.servlet.http.HttpServletResponse JavaDoc;
32
33 import org.apache.commons.lang.StringUtils;
34 import org.apache.log4j.Logger;
35 import org.bouncycastle.asn1.ASN1InputStream;
36 import org.bouncycastle.asn1.ASN1Sequence;
37 import org.bouncycastle.jce.netscape.NetscapeCertRequest;
38 import org.ejbca.core.ejb.ServiceLocator;
39 import org.ejbca.core.ejb.ServiceLocatorException;
40 import org.ejbca.core.ejb.ca.sign.ISignSessionLocal;
41 import org.ejbca.core.model.ca.SignRequestSignatureException;
42 import org.ejbca.core.model.log.Admin;
43 import org.ejbca.core.protocol.IResponseMessage;
44 import org.ejbca.core.protocol.PKCS10RequestMessage;
45 import org.ejbca.ui.web.pub.ServletDebug;
46 import org.ejbca.ui.web.pub.ServletUtils;
47 import org.ejbca.util.Base64;
48 import org.ejbca.util.CertTools;
49 import org.ejbca.util.FileTools;
50
51 /**
52  * Helper class for hadnling certificate request from browsers or general PKCS#10
53  *
54  * @version $Id: RequestHelper.java,v 1.5.2.2 2007/04/17 08:33:38 jeklund Exp $
55  */

56 public class RequestHelper {
57     private static Logger log = Logger.getLogger(RequestHelper.class);
58     private Admin administrator;
59     private ServletDebug debug;
60     private static final Pattern JavaDoc CLASSID = Pattern.compile("\\$CLASSID");
61
62     public static final String JavaDoc BEGIN_CERTIFICATE_REQUEST = "-----BEGIN CERTIFICATE REQUEST-----";
63     public static final String JavaDoc END_CERTIFICATE_REQUEST = "-----END CERTIFICATE REQUEST-----";
64     public static final String JavaDoc BEGIN_CERTIFICATE_REQUEST_WITH_NL = "-----BEGIN CERTIFICATE REQUEST-----\n";
65     public static final String JavaDoc END_CERTIFICATE_REQUEST_WITH_NL = "\n-----END CERTIFICATE REQUEST-----\n";
66
67     public static final String JavaDoc BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----";
68     public static final String JavaDoc END_CERTIFICATE = "-----END CERTIFICATE-----";
69     public static final String JavaDoc BEGIN_CERTIFICATE_WITH_NL = "-----BEGIN CERTIFICATE-----\n";
70     public static final String JavaDoc END_CERTIFICATE_WITH_NL = "\n-----END CERTIFICATE-----\n";
71     public static final String JavaDoc BEGIN_CRL_WITH_NL = "-----BEGIN X509 CRL-----\n";
72     public static final String JavaDoc END_CRL_WITH_NL = "\n-----END X509 CRL-----\n";
73
74     public static final String JavaDoc BEGIN_PKCS7 = "-----BEGIN PKCS7-----\n";
75     public static final String JavaDoc END_PKCS7 = "\n-----END PKCS7-----\n";
76     public static final String JavaDoc BEGIN_PKCS7_WITH_NL = "-----BEGIN PKCS7-----\n";
77     public static final String JavaDoc END_PKCS7_WITH_NL = "\n-----END PKCS7-----\n";
78     
79     public static final int ENCODED_CERTIFICATE = 1;
80     public static final int ENCODED_PKCS7 = 2;
81     
82     /**
83      * Creates a new RequestHelper object.
84      *
85      * @param administrator Admin doing the request
86      * @param debug object to send debug to
87      */

88     public RequestHelper(Admin administrator, ServletDebug debug) {
89         this.administrator = administrator;
90         this.debug = debug;
91     }
92
93     /**
94      * Handles NetScape certificate request (KEYGEN), these are constructed as: <code>
95      * SignedPublicKeyAndChallenge ::= SEQUENCE { publicKeyAndChallenge PublicKeyAndChallenge,
96      * signatureAlgorithm AlgorithmIdentifier, signature BIT STRING }</code> PublicKey's
97      * encoded-format has to be RSA X.509.
98      *
99      * @param signsession EJB session to signature bean.
100      * @param reqBytes buffer holding te request from NS.
101      * @param username username in EJBCA for authoriation.
102      * @param password users password for authorization.
103      *
104      * @return byte[] containing DER-encoded certificate.
105      */

106     public byte[] nsCertRequest(ISignSessionLocal signsession, byte[] reqBytes, String JavaDoc username,
107         String JavaDoc password) throws Exception JavaDoc {
108         byte[] buffer = Base64.decode(reqBytes);
109
110         if (buffer == null) {
111             return null;
112         }
113
114         ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream JavaDoc(buffer));
115         ASN1Sequence spkac = (ASN1Sequence) in.readObject();
116         in.close();
117
118         NetscapeCertRequest nscr = new NetscapeCertRequest(spkac);
119
120         // Verify POPO, we don't care about the challenge, it's not important.
121
nscr.setChallenge("challenge");
122
123         if (nscr.verify("challenge") == false) {
124             throw new SignRequestSignatureException(
125                 "Invalid signature in NetscapeCertRequest, popo-verification failed.");
126         }
127
128         log.debug("POPO verification successful");
129
130         X509Certificate JavaDoc cert = (X509Certificate JavaDoc) signsession.createCertificate(administrator,
131                 username, password, nscr.getPublicKey());
132
133         // Don't include certificate chain in the PKCS7 to mozilla
134
byte[] pkcs7 = signsession.createPKCS7(administrator, cert, false);
135         log.debug("Created certificate (PKCS7) for " + username);
136         debug.print("<h4>Generated certificate:</h4>");
137         debug.printInsertLineBreaks(cert.toString().getBytes());
138
139         return pkcs7;
140     } //nsCertRequest
141

142     /**
143      * Handles PKCS10 certificate request, these are constructed as: <code> CertificationRequest
144      * ::= SEQUENCE { certificationRequestInfo CertificationRequestInfo, signatureAlgorithm
145      * AlgorithmIdentifier{{ SignatureAlgorithms }}, signature BIT STRING }
146      * CertificationRequestInfo ::= SEQUENCE { version INTEGER { v1(0) } (v1,...),
147      * subject Name, subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
148      * attributes [0] Attributes{{ CRIAttributes }}} SubjectPublicKeyInfo { ALGORITHM :
149      * IOSet} ::= SEQUENCE { algorithm AlgorithmIdentifier {{IOSet}}, subjectPublicKey
150      * BIT STRING }</code> PublicKey's encoded-format has to be RSA X.509.
151      *
152      * @param signsession signsession to get certificate from
153      * @param b64Encoded base64 encoded pkcs10 request message
154      * @param username username of requesting user
155      * @param password password of requesting user
156      * @param resulttype should indicate if a PKCS7 or just the certificate is wanted.
157      * @param doSplitLines
158      * @return Base64 encoded byte[]
159      * @throws Exception
160      */

161     public byte[] pkcs10CertRequest(ISignSessionLocal signsession, byte[] b64Encoded,
162         String JavaDoc username, String JavaDoc password, int resulttype, boolean doSplitLines) throws Exception JavaDoc {
163         byte[] result = null;
164         X509Certificate JavaDoc cert=null;
165         PKCS10RequestMessage req = genPKCS10RequestMessageFromPEM(b64Encoded);
166         req.setUsername(username);
167         req.setPassword(password);
168         IResponseMessage resp = signsession.createCertificate(administrator,req,Class.forName("org.ejbca.core.protocol.X509ResponseMessage"));
169         cert = CertTools.getCertfromByteArray(resp.getResponseMessage());
170         if(resulttype == ENCODED_CERTIFICATE)
171           result = cert.getEncoded();
172         else
173           result = signsession.createPKCS7(administrator, cert, true);
174         log.debug("Created certificate (PKCS7) for " + username);
175         debug.print("<h4>Generated certificate:</h4>");
176         debug.printInsertLineBreaks(cert.toString().getBytes());
177         return Base64.encode(result, doSplitLines);
178     } //pkcs10CertReq
179

180     /**
181      *
182      * @param signsession
183      * @param b64Encoded
184      * @param username
185      * @param password
186      * @param resulttype
187      * @return
188      * @throws Exception
189      */

190     public byte[] pkcs10CertRequest(ISignSessionLocal signsession, byte[] b64Encoded,
191                                     String JavaDoc username, String JavaDoc password, int resulttype) throws Exception JavaDoc {
192         return pkcs10CertRequest(signsession, b64Encoded, username, password, resulttype, true);
193     }
194
195     /**
196      * Formats certificate in form to be received by IE
197      *
198      * @param bA input
199      * @param out Output
200      */

201     public static void ieCertFormat(byte[] bA, PrintStream JavaDoc out)
202         throws Exception JavaDoc {
203         BufferedReader JavaDoc br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(new ByteArrayInputStream JavaDoc(bA)));
204         int rowNr = 0;
205
206         while (true) {
207             String JavaDoc line = br.readLine();
208
209             if (line == null) {
210                 break;
211             }
212
213             if (line.indexOf("END CERT") < 0) {
214                 if (line.indexOf(" CERT") < 0) {
215                     if (++rowNr > 1) {
216                         out.println(" & _ ");
217                     } else {
218                         out.print(" cert = ");
219                     }
220
221                     out.print('\"' + line + '\"');
222                 }
223             } else {
224                 break;
225             }
226         }
227
228         out.println();
229     } // ieCertFormat
230

231     /**
232      * @param certificate b64 encoded cert to be installed in netid
233      * @param response output stream to send to
234      * @param sc serveltcontext
235      * @param responseTemplate path to template page for response
236      * @throws Exception
237      */

238     public static void sendNewCertToIidClient(byte[] certificate, OutputStream JavaDoc out, ServletContext JavaDoc sc,
239                                                 String JavaDoc responseTemplate, String JavaDoc classid) throws Exception JavaDoc {
240         if (certificate.length <= 0) {
241             log.error("0 length certificate can not be sent to client!");
242             return;
243         }
244         StringWriter JavaDoc sw = new StringWriter JavaDoc();
245         {
246             BufferedReader JavaDoc br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(sc.getResourceAsStream(responseTemplate)));
247             PrintWriter JavaDoc pw = new PrintWriter JavaDoc(sw);
248             while (true) {
249                 String JavaDoc line = br.readLine();
250                 if (line == null)
251                     break;
252                 line = line.replaceAll("TAG_cert",new String JavaDoc(certificate));
253                 line = CLASSID.matcher(line).replaceFirst(classid);
254                 pw.println(line);
255             }
256             pw.close();
257             sw.flush();
258         }
259         {
260             PrintWriter JavaDoc pw = new PrintWriter JavaDoc(out);
261             log.debug(sw);
262             pw.print(sw);
263             pw.close();
264             out.flush();
265         }
266     } // sendCertificates
267
/**
268      * Reads template and inserts cert to send back to IE for installation of cert
269      *
270      * @param b64cert cert to be installed in IE-client
271      * @param out utput stream to send to
272      * @param sc serveltcontext
273      * @param responseTemplate path to responseTemplate
274      * @param classid replace
275      *
276      * @throws Exception on error
277      */

278     public static void sendNewCertToIEClient(byte[] b64cert, OutputStream JavaDoc out, ServletContext JavaDoc sc,
279         String JavaDoc responseTemplate, String JavaDoc classid) throws Exception JavaDoc {
280         if (b64cert.length == 0) {
281             log.error("0 length certificate can not be sent to IE client!");
282             return;
283         }
284
285         PrintStream JavaDoc ps = new PrintStream JavaDoc(out);
286         BufferedReader JavaDoc br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(sc.getResourceAsStream(
287                         responseTemplate)));
288
289         while (true) {
290             String JavaDoc line = br.readLine();
291
292             if (line == null) {
293                 break;
294             }
295
296             if (line.indexOf("cert =") < 0) {
297                 ps.println(CLASSID.matcher(line).replaceFirst(classid));
298             } else {
299                 RequestHelper.ieCertFormat(b64cert, ps);
300             }
301         }
302
303         ps.close();
304         log.debug("Sent reply to IE client");
305         log.debug(new String JavaDoc(b64cert));
306     } // sendNewCertToIEClient
307

308     /**
309      * Sends back cert to NS/Mozilla for installation of cert
310      *
311      * @param certs DER encoded certificates to be installed in browser
312      * @param out output stream to send to
313      *
314      * @throws Exception on error
315      */

316     public static void sendNewCertToNSClient(byte[] certs, HttpServletResponse JavaDoc out)
317         throws Exception JavaDoc {
318         if (certs.length == 0) {
319             log.error("0 length certificate can not be sent to NS client!");
320             return;
321         }
322
323         // Set content-type to what NS wants
324
out.setContentType("application/x-x509-user-cert");
325         out.setContentLength(certs.length);
326
327         // Print the certificate
328
out.getOutputStream().write(certs);
329         log.debug("Sent reply to NS client");
330         log.debug(new String JavaDoc(Base64.encode(certs)));
331     } // sendNewCertToNSClient
332

333     /**
334      * Sends back certificate as binary file (application/octet-stream)
335      *
336      * @param b64cert base64 encoded certificate to be returned
337      * @param out output stream to send to
338      * @param filename filename sent as 'Content-disposition' header
339      * @param beginKey, String contaitning key information, ie BEGIN_CERTIFICATE_WITH_NL or BEGIN_PKCS7_WITH_NL
340      * @param beginKey, String contaitning key information, ie END_CERTIFICATE_WITH_NL or END_PKCS7_WITH_NL
341      * @throws IOException
342      * @throws Exception on error
343      */

344     public static void sendNewB64File(byte[] b64cert, HttpServletResponse JavaDoc out, String JavaDoc filename, String JavaDoc beginKey, String JavaDoc endKey)
345     throws IOException JavaDoc {
346         if (b64cert.length == 0) {
347             log.error("0 length certificate can not be sent to client!");
348             return;
349         }
350
351         // We must remove cache headers for IE
352
ServletUtils.removeCacheHeaders(out);
353
354         // Set content-type to general file
355
out.setContentType("application/octet-stream");
356         out.setHeader("Content-disposition", "filename=\""+filename+"\"");
357
358         out.setContentLength(b64cert.length + beginKey.length() + endKey.length());
359
360         // Write the certificate
361
ServletOutputStream JavaDoc os = out.getOutputStream();
362         os.write(beginKey.getBytes());
363         os.write(b64cert);
364         os.write(endKey.getBytes());
365         out.flushBuffer();
366         log.debug("Sent reply to client");
367         log.debug(new String JavaDoc(b64cert));
368     }
369     /**
370      * Sends back certificate as binary file (application/octet-stream)
371      *
372      * @param b64cert base64 encoded certificate to be returned
373      * @param out output stream to send to
374      * @param beginKey, String contaitning key information, ie BEGIN_CERTIFICATE_WITH_NL or BEGIN_PKCS7_WITH_NL
375      * @param beginKey, String contaitning key information, ie END_CERTIFICATE_WITH_NL or END_PKCS7_WITH_NL
376      * @throws Exception on error
377      */

378     public static void sendNewB64Cert(byte[] b64cert, HttpServletResponse JavaDoc out, String JavaDoc beginKey, String JavaDoc endKey)
379         throws IOException JavaDoc {
380         RequestHelper.sendNewB64File(b64cert, out, "cert.pem", beginKey, endKey);
381     } // sendNewB64Cert
382

383     /**
384      * Sends back CA-certificate as binary file (application/x-x509-ca-cert)
385      *
386      * @param cert DER encoded certificate to be returned
387      * @param out output stream to send to
388      *
389      * @throws Exception on error
390      */

391     public static void sendNewX509CaCert(byte[] cert, HttpServletResponse JavaDoc out)
392         throws Exception JavaDoc {
393         // Set content-type to CA-cert
394
sendBinaryBytes(cert, out, "application/x-x509-ca-cert", null);
395     } // sendNewX509CaCert
396

397     /**
398      * Sends back a number of bytes
399      *
400      * @param bytes DER encoded certificate to be returned
401      * @param out output stream to send to
402      * @param contentType mime type to send back bytes as
403      * @param fileName to call the file in a Content-disposition, can be null to leave out this header
404      *
405      * @throws Exception on error
406      */

407     public static void sendBinaryBytes(byte[] bytes, HttpServletResponse JavaDoc out, String JavaDoc contentType, String JavaDoc filename)
408         throws Exception JavaDoc {
409         if ( (bytes == null) || (bytes.length == 0) ) {
410             log.error("0 length can not be sent to client!");
411             return;
412         }
413
414         if (filename != null) {
415             // We must remove cache headers for IE
416
ServletUtils.removeCacheHeaders(out);
417             out.setHeader("Content-disposition", "filename=\""+filename+"\"");
418         }
419
420         // Set content-type to general file
421
out.setContentType(contentType);
422         out.setContentLength(bytes.length);
423
424         // Write the certificate
425
ServletOutputStream JavaDoc os = out.getOutputStream();
426         os.write(bytes);
427         out.flushBuffer();
428         log.debug("Sent " + bytes.length + " bytes to client");
429     } // sendBinaryBytes
430

431     public static PKCS10RequestMessage genPKCS10RequestMessageFromPEM(byte[] b64Encoded){
432       byte[] buffer = null;
433       try {
434         // A real PKCS10 PEM request
435
String JavaDoc beginKey = BEGIN_CERTIFICATE_REQUEST;
436         String JavaDoc endKey = END_CERTIFICATE_REQUEST;
437         buffer = FileTools.getBytesFromPEM(b64Encoded, beginKey, endKey);
438       } catch (IOException JavaDoc e) {
439         try {
440             // Keytool PKCS10 PEM request
441
String JavaDoc beginKey = "-----BEGIN NEW CERTIFICATE REQUEST-----";
442             String JavaDoc endKey = "-----END NEW CERTIFICATE REQUEST-----";
443             buffer = FileTools.getBytesFromPEM(b64Encoded, beginKey, endKey);
444         } catch (IOException JavaDoc ioe) {
445             // IE PKCS10 Base64 coded request
446
buffer = Base64.decode(b64Encoded);
447         }
448       }
449       if (buffer == null) {
450         return null;
451       }
452       return new PKCS10RequestMessage(buffer);
453     } // PKCS10RequestMessage
454

455     /** Returns the default content encoding used in JSPs. Reads the env-entry contentEncoding from web.xml.
456      *
457      * @return The content encoding set in the webs env-entry java:comp/env/contentEncoding, or ISO-8859-1 (default), never returns null.
458      */

459     public static String JavaDoc getDefaultContentEncoding() {
460         String JavaDoc ret = null;
461         try {
462             ret = ServiceLocator.getInstance().getString("java:comp/env/contentEncoding");
463         } catch (ServiceLocatorException e) {
464             log.debug("Can not find any default content encoding, using hard default ISO-8859-1.");
465             ret = "ISO-8859-1";
466         }
467         if (ret == null) {
468             log.debug("Can not find any default content encoding, using hard default ISO-8859-1.");
469             ret = "ISO-8859-1";
470         }
471         return ret;
472     }
473     
474     /** Sets the default character encoding for decoding post and get parameters.
475      * First tries to get the character encoding from the request, if the browser is so kind to tell us which it is using, which it never does...
476      * Otherwise, when the browser is silent, it sets the character encoding to the same encoding that we use to display the pages.
477      *
478      * @param request HttpServletRequest
479      * @throws UnsupportedEncodingException
480      *
481      */

482     public static void setDefaultCharacterEncoding(HttpServletRequest JavaDoc request) throws UnsupportedEncodingException JavaDoc {
483         String JavaDoc encoding = request.getCharacterEncoding();
484         if(StringUtils.isEmpty(encoding)) {
485             encoding = RequestHelper.getDefaultContentEncoding();
486             log.debug("Setting encoding to default value: "+encoding);
487             request.setCharacterEncoding(encoding);
488         } else {
489             log.debug("Setting encoding to value from request: "+encoding);
490             request.setCharacterEncoding(encoding);
491         }
492     }
493         
494 }
495
Popular Tags