KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejbca > core > protocol > xkms > XKMSProvider


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.core.protocol.xkms;
15
16 import java.security.cert.CertPath JavaDoc;
17 import java.security.cert.CertPathValidator JavaDoc;
18 import java.security.cert.CertPathValidatorException JavaDoc;
19 import java.security.cert.CertStore JavaDoc;
20 import java.security.cert.CertificateFactory JavaDoc;
21 import java.security.cert.CollectionCertStoreParameters JavaDoc;
22 import java.security.cert.PKIXParameters JavaDoc;
23 import java.security.cert.TrustAnchor JavaDoc;
24 import java.security.cert.X509Certificate JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Collection JavaDoc;
27 import java.util.Date JavaDoc;
28 import java.util.HashSet JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Set JavaDoc;
32
33 import javax.annotation.Resource;
34 import javax.ejb.CreateException JavaDoc;
35 import javax.naming.Context JavaDoc;
36 import javax.naming.InitialContext JavaDoc;
37 import javax.naming.NamingException JavaDoc;
38 import javax.servlet.http.HttpServletRequest JavaDoc;
39 import javax.xml.bind.JAXBContext;
40 import javax.xml.bind.JAXBElement;
41 import javax.xml.bind.JAXBException;
42 import javax.xml.bind.Marshaller;
43 import javax.xml.bind.PropertyException;
44 import javax.xml.bind.Unmarshaller;
45 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
46 import javax.xml.parsers.ParserConfigurationException JavaDoc;
47 import javax.xml.transform.Source JavaDoc;
48 import javax.xml.transform.Transformer JavaDoc;
49 import javax.xml.transform.TransformerConfigurationException JavaDoc;
50 import javax.xml.transform.TransformerException JavaDoc;
51 import javax.xml.transform.TransformerFactory JavaDoc;
52 import javax.xml.transform.TransformerFactoryConfigurationError JavaDoc;
53 import javax.xml.transform.dom.DOMResult JavaDoc;
54 import javax.xml.transform.dom.DOMSource JavaDoc;
55 import javax.xml.ws.Provider;
56 import javax.xml.ws.Service;
57 import javax.xml.ws.ServiceMode;
58 import javax.xml.ws.WebServiceContext;
59 import javax.xml.ws.WebServiceProvider;
60 import javax.xml.ws.handler.MessageContext;
61
62 import org.apache.log4j.Logger;
63 import org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionLocal;
64 import org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionLocalHome;
65 import org.ejbca.core.ejb.ca.sign.ISignSessionLocal;
66 import org.ejbca.core.ejb.ca.sign.ISignSessionLocalHome;
67 import org.ejbca.core.ejb.ca.store.ICertificateStoreSessionLocal;
68 import org.ejbca.core.ejb.ca.store.ICertificateStoreSessionLocalHome;
69 import org.ejbca.core.model.InternalResources;
70 import org.ejbca.core.model.ca.caadmin.CAInfo;
71 import org.ejbca.core.model.ca.caadmin.extendedcaservices.XKMSCAServiceRequest;
72 import org.ejbca.core.model.ca.caadmin.extendedcaservices.XKMSCAServiceResponse;
73 import org.ejbca.core.model.ca.crl.RevokedCertInfo;
74 import org.ejbca.core.model.log.Admin;
75 import org.ejbca.core.protocol.xkms.common.XKMSConstants;
76 import org.ejbca.core.protocol.xkms.common.XKMSNamespacePrefixMapper;
77 import org.ejbca.core.protocol.xkms.generators.LocateResponseGenerator;
78 import org.ejbca.core.protocol.xkms.generators.RecoverResponseGenerator;
79 import org.ejbca.core.protocol.xkms.generators.RegisterResponseGenerator;
80 import org.ejbca.core.protocol.xkms.generators.ReissueResponseGenerator;
81 import org.ejbca.core.protocol.xkms.generators.RevokeResponseGenerator;
82 import org.ejbca.core.protocol.xkms.generators.ValidateResponseGenerator;
83 import org.ejbca.core.protocol.xkms.generators.XKMSConfig;
84 import org.ejbca.util.CertTools;
85 import org.w3._2002._03.xkms_.LocateRequestType;
86 import org.w3._2002._03.xkms_.LocateResultType;
87 import org.w3._2002._03.xkms_.MessageAbstractType;
88 import org.w3._2002._03.xkms_.ObjectFactory;
89 import org.w3._2002._03.xkms_.RecoverRequestType;
90 import org.w3._2002._03.xkms_.RecoverResultType;
91 import org.w3._2002._03.xkms_.RegisterRequestType;
92 import org.w3._2002._03.xkms_.RegisterResultType;
93 import org.w3._2002._03.xkms_.ReissueRequestType;
94 import org.w3._2002._03.xkms_.ReissueResultType;
95 import org.w3._2002._03.xkms_.RequestAbstractType;
96 import org.w3._2002._03.xkms_.RevokeRequestType;
97 import org.w3._2002._03.xkms_.RevokeResultType;
98 import org.w3._2002._03.xkms_.ValidateRequestType;
99 import org.w3._2002._03.xkms_.ValidateResultType;
100 import org.w3c.dom.Document JavaDoc;
101 import org.w3c.dom.Node JavaDoc;
102 import org.w3c.dom.NodeList JavaDoc;
103
104 /**
105  * The XKMS Web Service in provider form
106  *
107  * This is used as a workaround for the namespace prefix handling
108  * in the JAX-WS
109  *
110  *
111  * @author Philip Vendil 2006 dec 18
112  *
113  * @version $Id: XKMSProvider.java,v 1.3.2.1 2007/02/02 08:59:00 anatom Exp $
114  */

115
116 @ServiceMode(value=Service.Mode.PAYLOAD)
117 @WebServiceProvider(serviceName="XKMSService", targetNamespace = "http://www.w3.org/2002/03/xkms#wsdl", portName="XKMSPort")
118 public class XKMSProvider implements Provider<Source JavaDoc> {
119     @Resource
120     private WebServiceContext wsContext;
121     
122     private static Logger log = Logger.getLogger(XKMSPortType.class);
123     
124     private static final InternalResources intres = InternalResources.getInstance();
125     
126     protected Admin intAdmin = new Admin(Admin.TYPE_INTERNALUSER);
127     
128     private ObjectFactory xKMSObjectFactory = new ObjectFactory();
129     
130     private static JAXBContext jAXBContext = null;
131     private static Marshaller marshaller = null;
132     private static Unmarshaller unmarshaller = null;
133     private static DocumentBuilderFactory JavaDoc dbf = null;
134     
135     static{
136         try {
137             org.apache.xml.security.Init.init();
138             jAXBContext = JAXBContext.newInstance("org.w3._2002._03.xkms_:org.w3._2001._04.xmlenc_:org.w3._2000._09.xmldsig_");
139             marshaller = jAXBContext.createMarshaller();
140             try {
141                 marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper",new XKMSNamespacePrefixMapper());
142             } catch( PropertyException e ) {
143                log.error(intres.getLocalizedMessage("xkms.errorregisteringnamespace"),e);
144             }
145             dbf = DocumentBuilderFactory.newInstance();
146             dbf.setNamespaceAware(true);
147             unmarshaller = jAXBContext.createUnmarshaller();
148
149         } catch (JAXBException e) {
150             log.error(intres.getLocalizedMessage("xkms.errorinitializinggenerator"),e);
151         }
152     
153     }
154     
155     /**
156      * The main method performing the actual calls
157      */

158     public Source JavaDoc invoke(Source JavaDoc request) {
159         Source JavaDoc response = null;
160         
161         MessageContext msgContext = wsContext.getMessageContext();
162         HttpServletRequest JavaDoc httpreq = (HttpServletRequest JavaDoc) msgContext.get(MessageContext.SERVLET_REQUEST);
163         String JavaDoc remoteIP = httpreq.getRemoteAddr();
164         
165         Document JavaDoc requestDoc = null;
166         try{
167             DOMResult JavaDoc dom = new DOMResult JavaDoc();
168             Transformer JavaDoc trans = TransformerFactory.newInstance().newTransformer();
169             trans.transform(request, dom);
170             requestDoc = (Document JavaDoc) dom.getNode();
171         } catch (TransformerConfigurationException JavaDoc e) {
172             log.error(intres.getLocalizedMessage("xkms.errorparsingdomreq"),e);
173         } catch (TransformerFactoryConfigurationError JavaDoc e) {
174             log.error(intres.getLocalizedMessage("xkms.errorparsingdomreq"),e);
175         } catch (TransformerException JavaDoc e) {
176             log.error(intres.getLocalizedMessage("xkms.errorparsingdomreq"),e);
177         }
178         
179         boolean respMecSign = false;
180         try {
181             JAXBElement jAXBRequest = (JAXBElement) unmarshaller.unmarshal(request);
182             
183             JAXBElement jAXBResult = null;
184             if(jAXBRequest.getValue() instanceof RequestAbstractType){
185                 respMecSign = ((RequestAbstractType)jAXBRequest.getValue()).getResponseMechanism().contains(XKMSConstants.RESPONSMEC_REQUESTSIGNATUREVALUE);
186             }
187             if(jAXBRequest.getValue() instanceof ValidateRequestType ){
188                 boolean requestVerifies = verifyRequest(requestDoc);
189                 jAXBResult = validate(remoteIP, (ValidateRequestType) jAXBRequest.getValue(), requestVerifies);
190             }
191             if(jAXBRequest.getValue() instanceof LocateRequestType ){
192                 boolean requestVerifies = verifyRequest(requestDoc);
193                 jAXBResult = locate(remoteIP, (LocateRequestType) jAXBRequest.getValue(), requestVerifies);
194             }
195             if(jAXBRequest.getValue() instanceof RegisterRequestType ){
196                 boolean requestVerifies = verifyRequest(requestDoc);
197                 jAXBResult = register(remoteIP, (RegisterRequestType) jAXBRequest.getValue(), requestVerifies, requestDoc);
198             }
199             if(jAXBRequest.getValue() instanceof ReissueRequestType ){
200                 boolean requestVerifies = verifyRequest(requestDoc);
201                 jAXBResult = reissue(remoteIP, (ReissueRequestType) jAXBRequest.getValue(), requestVerifies, requestDoc);
202             }
203             if(jAXBRequest.getValue() instanceof RecoverRequestType ){
204                 boolean requestVerifies = verifyRequest(requestDoc);
205                 jAXBResult = recover(remoteIP, (RecoverRequestType) jAXBRequest.getValue(), requestVerifies, requestDoc);
206             }
207             
208             if(jAXBRequest.getValue() instanceof RevokeRequestType ){
209                 boolean requestVerifies = verifyRequest(requestDoc);
210                 jAXBResult = revoke(remoteIP, (RevokeRequestType) jAXBRequest.getValue(), requestVerifies, requestDoc);
211             }
212             
213             
214             String JavaDoc responseId = ((MessageAbstractType) jAXBResult.getValue()).getId();
215             
216             Document JavaDoc doc = dbf.newDocumentBuilder().newDocument();
217             marshaller.marshal( jAXBResult, doc );
218             doc = signResponseIfNeeded(doc, responseId, respMecSign, intAdmin);
219
220                         
221             response = new DOMSource JavaDoc(doc);
222             
223                     
224         } catch (JAXBException e) {
225            log.error(intres.getLocalizedMessage("xkms.errorunmarshallingreq"),e);
226         } catch (ParserConfigurationException JavaDoc e) {
227            log.error(intres.getLocalizedMessage("xkms.errorparsingresp"),e);
228         }
229         
230         return response;
231     }
232
233     private JAXBElement validate(String JavaDoc remoteIP, ValidateRequestType value, boolean requestVerifies) {
234         ValidateResponseGenerator gen = new ValidateResponseGenerator(remoteIP,value);
235         
236         JAXBElement<ValidateResultType> validateresult = xKMSObjectFactory.createValidateResult(gen.getResponse(requestVerifies));
237         return validateresult;
238     }
239     
240     private JAXBElement locate(String JavaDoc remoteIP, LocateRequestType value, boolean requestVerifies) {
241         LocateResponseGenerator gen = new LocateResponseGenerator(remoteIP, value);
242         
243         JAXBElement<LocateResultType> locateresult = xKMSObjectFactory.createLocateResult(gen.getResponse(requestVerifies));
244         return locateresult;
245     }
246     
247     private JAXBElement register(String JavaDoc remoteIP, RegisterRequestType value, boolean requestVerifies, Document JavaDoc requestDoc) {
248         RegisterResponseGenerator gen = new RegisterResponseGenerator(remoteIP, value,requestDoc);
249         
250         JAXBElement<RegisterResultType> registerresult = xKMSObjectFactory.createRegisterResult(gen.getResponse(requestVerifies));
251         return registerresult;
252     }
253     
254     private JAXBElement reissue(String JavaDoc remoteIP, ReissueRequestType value, boolean requestVerifies, Document JavaDoc requestDoc) {
255         ReissueResponseGenerator gen = new ReissueResponseGenerator(remoteIP, value,requestDoc);
256         
257         JAXBElement<ReissueResultType> reissueresult = xKMSObjectFactory.createReissueResult(gen.getResponse(requestVerifies));
258         return reissueresult;
259     }
260     
261     private JAXBElement recover(String JavaDoc remoteIP, RecoverRequestType value, boolean requestVerifies, Document JavaDoc requestDoc) {
262         RecoverResponseGenerator gen = new RecoverResponseGenerator(remoteIP, value,requestDoc);
263         
264         JAXBElement<RecoverResultType> recoverresult = xKMSObjectFactory.createRecoverResult(gen.getResponse(requestVerifies));
265         return recoverresult;
266     }
267     
268     private JAXBElement revoke(String JavaDoc remoteIP, RevokeRequestType value, boolean requestVerifies, Document JavaDoc requestDoc) {
269         RevokeResponseGenerator gen = new RevokeResponseGenerator(remoteIP, value,requestDoc);
270         
271         JAXBElement<RevokeResultType> recoverresult = xKMSObjectFactory.createRevokeResult(gen.getResponse(requestVerifies));
272         return recoverresult;
273     }
274     
275     
276     /**
277      * Method that verifies the content of the requests against the
278      * configured trusted CA.
279      *
280      * @param kISSRequest if the caller is a kISSRequest
281      *
282      */

283     private boolean verifyRequest(Document JavaDoc requestDoc) {
284             boolean signatureExists = false;
285
286             Node JavaDoc xmlSig = null;
287             NodeList JavaDoc nodeList = requestDoc.getChildNodes().item(0).getChildNodes();
288             for(int i=0;i<nodeList.getLength();i++){
289               if(nodeList.item(i).getLocalName().equalsIgnoreCase("Signature")){
290                   xmlSig = nodeList.item(i);
291               }
292             }
293             
294             signatureExists = xmlSig != null;
295
296             // Check that signature exists and if it's required
297
boolean sigRequired = XKMSConfig.isSignedRequestRequired();
298
299             if(sigRequired && !signatureExists){
300                 log.error(intres.getLocalizedMessage("xkms.recievedreqwithoutsig"));
301                 return false;
302             }else{
303                 if(signatureExists){
304
305                     try{
306                         org.w3c.dom.Element JavaDoc xmlSigElement = (org.w3c.dom.Element JavaDoc)xmlSig;
307                         org.apache.xml.security.signature.XMLSignature xmlVerifySig = new org.apache.xml.security.signature.XMLSignature(xmlSigElement, null);
308
309                         org.apache.xml.security.keys.KeyInfo keyInfo = xmlVerifySig.getKeyInfo();
310                         java.security.cert.X509Certificate JavaDoc verCert = keyInfo.getX509Certificate();
311
312
313                         // Check signature
314
if(xmlVerifySig.checkSignatureValue(verCert)){
315                             // Check that the issuer is among accepted issuers
316
int cAId = CertTools.getIssuerDN(verCert).hashCode();
317
318                             Collection JavaDoc acceptedCAIds = XKMSConfig.getAcceptedCA(intAdmin, getCAAdminSession());
319                             if(!acceptedCAIds.contains(new Integer JavaDoc(cAId))){
320                                 throw new Exception JavaDoc("Error XKMS request signature certificate isn't among the list of accepted CA certificates");
321                             }
322
323                             CAInfo cAInfo = getCAAdminSession().getCAInfo(intAdmin, cAId);
324                             Collection JavaDoc cACertChain = cAInfo.getCertificateChain();
325                             // Check issuer and validity
326
X509Certificate JavaDoc rootCert = null;
327                             Iterator JavaDoc iter = cACertChain.iterator();
328                             while(iter.hasNext()){
329                                 X509Certificate JavaDoc cert = (X509Certificate JavaDoc) iter.next();
330                                 if(cert.getIssuerDN().equals(cert.getSubjectDN())){
331                                     rootCert = cert;
332                                     break;
333                                 }
334                             }
335
336                             if(rootCert == null){
337                                 throw new CertPathValidatorException JavaDoc("Error Root CA cert not found in cACertChain");
338                             }
339
340                             List JavaDoc list = new ArrayList JavaDoc();
341                             list.add(verCert);
342                             list.add(cACertChain);
343
344
345                             CollectionCertStoreParameters JavaDoc ccsp = new CollectionCertStoreParameters JavaDoc(list);
346                             CertStore JavaDoc store = CertStore.getInstance("Collection", ccsp);
347
348                             //validating path
349
List JavaDoc certchain = new ArrayList JavaDoc();
350                             certchain.addAll(cACertChain);
351                             certchain.add(verCert);
352                             CertPath JavaDoc cp = CertificateFactory.getInstance("X.509","BC").generateCertPath(certchain);
353
354                             Set JavaDoc trust = new HashSet JavaDoc();
355                             trust.add(new TrustAnchor JavaDoc(rootCert, null));
356
357                             CertPathValidator JavaDoc cpv = CertPathValidator.getInstance("PKIX","BC");
358                             PKIXParameters JavaDoc param = new PKIXParameters JavaDoc(trust);
359                             param.addCertStore(store);
360                             param.setDate(new Date JavaDoc());
361                             param.setRevocationEnabled(false);
362
363                             cpv.validate(cp, param);
364
365                             // Check revokation status
366
RevokedCertInfo revCertInfo = getCertStoreSession().isRevoked(intAdmin, CertTools.getIssuerDN(verCert), verCert.getSerialNumber());
367                             if(revCertInfo.getReason() != RevokedCertInfo.NOT_REVOKED){
368                                 return false;
369                             }
370                         }else{
371                             log.error(intres.getLocalizedMessage("xkms.errorreqsigdoesntverify"));
372                             return false;
373                         }
374                     }catch(Exception JavaDoc e){
375                         log.error(intres.getLocalizedMessage("xkms.errorwhenverifyingreq"));
376                         return false;
377                     }
378                 }
379             }
380
381         return true;
382     }
383     
384     /**
385      * Method that checks if signing is required by
386      * checking the service configuration and the request,
387      * It then signs the request, othervise it isn't
388      * @param admin
389      * @return the document signed or null of the signature failed;
390      */

391     private Document JavaDoc signResponseIfNeeded(Document JavaDoc result, String JavaDoc id, boolean respMecSign, Admin admin){
392         Document JavaDoc retval = result;
393
394         if(XKMSConfig.alwaysSignResponses() || (XKMSConfig.acceptSignRequests() && respMecSign)){
395             try {
396
397                 XKMSCAServiceRequest cAReq = new XKMSCAServiceRequest(result, id,true,false);
398
399                 XKMSCAServiceResponse resp = (XKMSCAServiceResponse) getSignSession().extendedService(admin, XKMSConfig.cAIdUsedForSigning(admin, getCAAdminSession()), cAReq);
400
401                 retval = resp.getSignedDocument();
402             } catch (Exception JavaDoc e) {
403                 log.error(intres.getLocalizedMessage("xkms.errorgenrespsig"), e);
404                 retval = null;
405             }
406         }
407
408         return retval;
409     }
410     
411     private ICertificateStoreSessionLocal certificatestoresession = null;
412     protected ICertificateStoreSessionLocal getCertStoreSession() throws ClassCastException JavaDoc, CreateException JavaDoc, NamingException JavaDoc{
413         if(certificatestoresession == null){
414             Context JavaDoc context = new InitialContext JavaDoc();
415             certificatestoresession = ((ICertificateStoreSessionLocalHome) javax.rmi.PortableRemoteObject.narrow(context.lookup(
416             "CertificateStoreSessionLocal"), ICertificateStoreSessionLocalHome.class)).create();
417         }
418         return certificatestoresession;
419     }
420     
421     private ICAAdminSessionLocal caadminsession = null;
422     protected ICAAdminSessionLocal getCAAdminSession() throws ClassCastException JavaDoc, CreateException JavaDoc, NamingException JavaDoc{
423         if(caadminsession == null){
424             Context JavaDoc context = new InitialContext JavaDoc();
425             caadminsession = ((ICAAdminSessionLocalHome) javax.rmi.PortableRemoteObject.narrow(context.lookup(
426             "CAAdminSessionLocal"), ICAAdminSessionLocalHome.class)).create();
427         }
428         return caadminsession;
429     }
430     
431     private ISignSessionLocal signsession = null;
432     protected ISignSessionLocal getSignSession() throws ClassCastException JavaDoc, CreateException JavaDoc, NamingException JavaDoc{
433         if(signsession == null){
434             Context JavaDoc context = new InitialContext JavaDoc();
435             signsession = ((ISignSessionLocalHome) javax.rmi.PortableRemoteObject.narrow(context.lookup(
436             "SignSessionLocal"), ISignSessionLocalHome.class)).create();
437         }
438         return signsession;
439     }
440
441 }
442
Popular Tags