1 13 14 package org.ejbca.core.protocol.xkms; 15 16 import java.security.cert.CertPath ; 17 import java.security.cert.CertPathValidator ; 18 import java.security.cert.CertPathValidatorException ; 19 import java.security.cert.CertStore ; 20 import java.security.cert.CertificateFactory ; 21 import java.security.cert.CollectionCertStoreParameters ; 22 import java.security.cert.PKIXParameters ; 23 import java.security.cert.TrustAnchor ; 24 import java.security.cert.X509Certificate ; 25 import java.util.ArrayList ; 26 import java.util.Collection ; 27 import java.util.Date ; 28 import java.util.HashSet ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 import java.util.Set ; 32 33 import javax.annotation.Resource; 34 import javax.ejb.CreateException ; 35 import javax.naming.Context ; 36 import javax.naming.InitialContext ; 37 import javax.naming.NamingException ; 38 import javax.servlet.http.HttpServletRequest ; 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 ; 46 import javax.xml.parsers.ParserConfigurationException ; 47 import javax.xml.transform.Source ; 48 import javax.xml.transform.Transformer ; 49 import javax.xml.transform.TransformerConfigurationException ; 50 import javax.xml.transform.TransformerException ; 51 import javax.xml.transform.TransformerFactory ; 52 import javax.xml.transform.TransformerFactoryConfigurationError ; 53 import javax.xml.transform.dom.DOMResult ; 54 import javax.xml.transform.dom.DOMSource ; 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 ; 101 import org.w3c.dom.Node ; 102 import org.w3c.dom.NodeList ; 103 104 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 > { 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 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 158 public Source invoke(Source request) { 159 Source response = null; 160 161 MessageContext msgContext = wsContext.getMessageContext(); 162 HttpServletRequest httpreq = (HttpServletRequest ) msgContext.get(MessageContext.SERVLET_REQUEST); 163 String remoteIP = httpreq.getRemoteAddr(); 164 165 Document requestDoc = null; 166 try{ 167 DOMResult dom = new DOMResult (); 168 Transformer trans = TransformerFactory.newInstance().newTransformer(); 169 trans.transform(request, dom); 170 requestDoc = (Document ) dom.getNode(); 171 } catch (TransformerConfigurationException e) { 172 log.error(intres.getLocalizedMessage("xkms.errorparsingdomreq"),e); 173 } catch (TransformerFactoryConfigurationError e) { 174 log.error(intres.getLocalizedMessage("xkms.errorparsingdomreq"),e); 175 } catch (TransformerException 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 responseId = ((MessageAbstractType) jAXBResult.getValue()).getId(); 215 216 Document doc = dbf.newDocumentBuilder().newDocument(); 217 marshaller.marshal( jAXBResult, doc ); 218 doc = signResponseIfNeeded(doc, responseId, respMecSign, intAdmin); 219 220 221 response = new DOMSource (doc); 222 223 224 } catch (JAXBException e) { 225 log.error(intres.getLocalizedMessage("xkms.errorunmarshallingreq"),e); 226 } catch (ParserConfigurationException e) { 227 log.error(intres.getLocalizedMessage("xkms.errorparsingresp"),e); 228 } 229 230 return response; 231 } 232 233 private JAXBElement validate(String 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 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 remoteIP, RegisterRequestType value, boolean requestVerifies, Document 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 remoteIP, ReissueRequestType value, boolean requestVerifies, Document 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 remoteIP, RecoverRequestType value, boolean requestVerifies, Document 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 remoteIP, RevokeRequestType value, boolean requestVerifies, Document 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 283 private boolean verifyRequest(Document requestDoc) { 284 boolean signatureExists = false; 285 286 Node xmlSig = null; 287 NodeList 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 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 xmlSigElement = (org.w3c.dom.Element )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 verCert = keyInfo.getX509Certificate(); 311 312 313 if(xmlVerifySig.checkSignatureValue(verCert)){ 315 int cAId = CertTools.getIssuerDN(verCert).hashCode(); 317 318 Collection acceptedCAIds = XKMSConfig.getAcceptedCA(intAdmin, getCAAdminSession()); 319 if(!acceptedCAIds.contains(new Integer (cAId))){ 320 throw new Exception ("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 cACertChain = cAInfo.getCertificateChain(); 325 X509Certificate rootCert = null; 327 Iterator iter = cACertChain.iterator(); 328 while(iter.hasNext()){ 329 X509Certificate cert = (X509Certificate ) 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 ("Error Root CA cert not found in cACertChain"); 338 } 339 340 List list = new ArrayList (); 341 list.add(verCert); 342 list.add(cACertChain); 343 344 345 CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters (list); 346 CertStore store = CertStore.getInstance("Collection", ccsp); 347 348 List certchain = new ArrayList (); 350 certchain.addAll(cACertChain); 351 certchain.add(verCert); 352 CertPath cp = CertificateFactory.getInstance("X.509","BC").generateCertPath(certchain); 353 354 Set trust = new HashSet (); 355 trust.add(new TrustAnchor (rootCert, null)); 356 357 CertPathValidator cpv = CertPathValidator.getInstance("PKIX","BC"); 358 PKIXParameters param = new PKIXParameters (trust); 359 param.addCertStore(store); 360 param.setDate(new Date ()); 361 param.setRevocationEnabled(false); 362 363 cpv.validate(cp, param); 364 365 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 e){ 375 log.error(intres.getLocalizedMessage("xkms.errorwhenverifyingreq")); 376 return false; 377 } 378 } 379 } 380 381 return true; 382 } 383 384 391 private Document signResponseIfNeeded(Document result, String id, boolean respMecSign, Admin admin){ 392 Document 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 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 , CreateException , NamingException { 413 if(certificatestoresession == null){ 414 Context context = new InitialContext (); 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 , CreateException , NamingException { 423 if(caadminsession == null){ 424 Context context = new InitialContext (); 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 , CreateException , NamingException { 433 if(signsession == null){ 434 Context context = new InitialContext (); 435 signsession = ((ISignSessionLocalHome) javax.rmi.PortableRemoteObject.narrow(context.lookup( 436 "SignSessionLocal"), ISignSessionLocalHome.class)).create(); 437 } 438 return signsession; 439 } 440 441 } 442 | Popular Tags |