1 /* 2 * Copyright 2004,2005 The Apache Software Foundation. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.apache.rampart.builder; 18 19 import java.util.ArrayList; 20 import java.util.Iterator; 21 import java.util.Vector; 22 23 import org.apache.axiom.om.OMElement; 24 import org.apache.axiom.soap.SOAPEnvelope; 25 import org.apache.axis2.context.MessageContext; 26 import org.apache.commons.logging.Log; 27 import org.apache.commons.logging.LogFactory; 28 import org.apache.rahas.RahasConstants; 29 import org.apache.rahas.TrustException; 30 import org.apache.rampart.RampartConstants; 31 import org.apache.rampart.RampartException; 32 import org.apache.rampart.RampartMessageData; 33 import org.apache.rampart.policy.RampartPolicyData; 34 import org.apache.rampart.util.RampartUtil; 35 import org.apache.ws.secpolicy.SPConstants; 36 import org.apache.ws.secpolicy.model.AlgorithmSuite; 37 import org.apache.ws.secpolicy.model.Header; 38 import org.apache.ws.secpolicy.model.IssuedToken; 39 import org.apache.ws.secpolicy.model.SecureConversationToken; 40 import org.apache.ws.secpolicy.model.SignedEncryptedParts; 41 import org.apache.ws.secpolicy.model.SupportingToken; 42 import org.apache.ws.secpolicy.model.Token; 43 import org.apache.ws.secpolicy.model.UsernameToken; 44 import org.apache.ws.secpolicy.model.X509Token; 45 import org.apache.ws.security.WSConstants; 46 import org.apache.ws.security.WSEncryptionPart; 47 import org.apache.ws.security.WSSecurityException; 48 import org.apache.ws.security.conversation.ConversationException; 49 import org.apache.ws.security.handler.WSHandlerConstants; 50 import org.apache.ws.security.message.WSSecDKSign; 51 import org.apache.ws.security.message.WSSecEncryptedKey; 52 import org.apache.ws.security.message.WSSecSignature; 53 import org.apache.ws.security.message.WSSecUsernameToken; 54 import org.w3c.dom.Document; 55 import org.w3c.dom.Element; 56 57 public class TransportBindingBuilder extends BindingBuilder { 58 59 private static Log log = LogFactory.getLog(TransportBindingBuilder.class); 60 private static Log tlog = LogFactory.getLog(RampartConstants.TIME_LOG); 61 private boolean dotDebug = false; 62 63 public TransportBindingBuilder(){ 64 dotDebug = tlog.isDebugEnabled(); 65 } 66 67 public void build(RampartMessageData rmd) throws RampartException { 68 69 log.debug("TransportBindingBuilder build invoked"); 70 71 long t0 = 0, t1 = 0; 72 if(dotDebug){ 73 t1 = System.currentTimeMillis(); 74 } 75 76 RampartPolicyData rpd = rmd.getPolicyData(); 77 78 if (rpd.isIncludeTimestamp()) { 79 addTimestamp(rmd); 80 } 81 82 /* 83 * Process Supporting tokens 84 */ 85 if(rmd.isInitiator()) { 86 Vector signatureValues = new Vector(); 87 88 SupportingToken sgndSuppTokens = rpd.getSignedSupportingTokens(); 89 90 if(sgndSuppTokens != null && sgndSuppTokens.getTokens() != null && 91 sgndSuppTokens.getTokens().size() > 0) { 92 93 log.debug("Processing signed supporting tokens"); 94 95 ArrayList tokens = sgndSuppTokens.getTokens(); 96 for (Iterator iter = tokens.iterator(); iter.hasNext();) { 97 98 Token token = (Token) iter.next(); 99 if(token instanceof UsernameToken) { 100 WSSecUsernameToken utBuilder = addUsernameToken(rmd,(UsernameToken)token); 101 102 utBuilder.prepare(rmd.getDocument()); 103 104 //Add the UT 105 utBuilder.appendToHeader(rmd.getSecHeader()); 106 107 } else { 108 throw new RampartException("unsupportedSignedSupportingToken", 109 new String[]{"{" +token.getName().getNamespaceURI() 110 + "}" + token.getName().getLocalPart()}); 111 } 112 } 113 } 114 115 SupportingToken sgndEndSuppTokens = rpd.getSignedEndorsingSupportingTokens(); 116 if(sgndEndSuppTokens != null && sgndEndSuppTokens.getTokens() != null && 117 sgndEndSuppTokens.getTokens().size() > 0) { 118 119 log.debug("Processing endorsing signed supporting tokens"); 120 121 ArrayList tokens = sgndEndSuppTokens.getTokens(); 122 SignedEncryptedParts signdParts = sgndEndSuppTokens.getSignedParts(); 123 for (Iterator iter = tokens.iterator(); iter.hasNext();) { 124 Token token = (Token) iter.next(); 125 if(token instanceof IssuedToken && rmd.isInitiator()) { 126 signatureValues.add(doIssuedTokenSignature(rmd, token, signdParts)); 127 } else if(token instanceof X509Token) { 128 signatureValues.add(doX509TokenSignature(rmd, token, signdParts)); 129 } 130 } 131 } 132 133 SupportingToken endSupptokens = rpd.getEndorsingSupportingTokens(); 134 if(endSupptokens != null && endSupptokens.getTokens() != null && 135 endSupptokens.getTokens().size() > 0) { 136 log.debug("Processing endorsing supporting tokens"); 137 ArrayList tokens = endSupptokens.getTokens(); 138 SignedEncryptedParts signdParts = endSupptokens.getSignedParts(); 139 for (Iterator iter = tokens.iterator(); iter.hasNext();) { 140 Token token = (Token) iter.next(); 141 if(token instanceof IssuedToken && rmd.isInitiator()){ 142 signatureValues.add(doIssuedTokenSignature(rmd, token, signdParts)); 143 } else if(token instanceof X509Token) { 144 signatureValues.add(doX509TokenSignature(rmd, token, signdParts)); 145 } else if (token instanceof SecureConversationToken) { 146 handleSecureConversationTokens(rmd, (SecureConversationToken)token); 147 signatureValues.add(doSecureConversationSignature(rmd, token, signdParts)); 148 } 149 } 150 } 151 152 153 SupportingToken supportingToks = rpd.getSupportingTokens(); 154 this.handleSupportingTokens(rmd, supportingToks); 155 156 157 //Store the signature values vector 158 rmd.getMsgContext().setProperty(WSHandlerConstants.SEND_SIGV, signatureValues); 159 } else { 160 addSignatureConfirmation(rmd, null); 161 } 162 163 if(dotDebug){ 164 t1 = System.currentTimeMillis(); 165 tlog.debug("Transport binding build took "+ (t1 - t0)); 166 } 167 } 168 169 170 171 /** 172 * X.509 signature 173 * @param rmd 174 * @param token 175 * @param signdParts 176 */ 177 private byte[] doX509TokenSignature(RampartMessageData rmd, Token token, SignedEncryptedParts signdParts) throws RampartException { 178 179 RampartPolicyData rpd = rmd.getPolicyData(); 180 Document doc = rmd.getDocument(); 181 182 Vector sigParts = new Vector(); 183 184 if(this.timestampElement != null){ 185 sigParts.add(new WSEncryptionPart(rmd.getTimestampId())); 186 } 187 188 if(signdParts != null) { 189 if(signdParts.isBody()) { 190 SOAPEnvelope env = rmd.getMsgContext().getEnvelope(); 191 sigParts.add(new WSEncryptionPart(RampartUtil.addWsuIdToElement(env.getBody()))); 192 } 193 194 ArrayList headers = signdParts.getHeaders(); 195 for (Iterator iterator = headers.iterator(); iterator.hasNext();) { 196 Header header = (Header) iterator.next(); 197 WSEncryptionPart wep = new WSEncryptionPart(header.getName(), 198 header.getNamespace(), 199 "Content"); 200 sigParts.add(wep); 201 } 202 } 203 if(token.isDerivedKeys()) { 204 //In this case we will have to encrypt the ephmeral key with the 205 //other party's key and then use it as the parent key of the 206 // derived keys 207 try { 208 209 WSSecEncryptedKey encrKey = getEncryptedKeyBuilder(rmd, token); 210 211 Element bstElem = encrKey.getBinarySecurityTokenElement(); 212 if(bstElem != null) { 213 RampartUtil.appendChildToSecHeader(rmd, bstElem); 214 } 215 216 encrKey.appendToHeader(rmd.getSecHeader()); 217 218 WSSecDKSign dkSig = new WSSecDKSign(); 219 220 dkSig.setWsConfig(rmd.getConfig()); 221 222 dkSig.setSigCanonicalization(rpd.getAlgorithmSuite().getInclusiveC14n()); 223 dkSig.setSignatureAlgorithm(rpd.getAlgorithmSuite().getSymmetricSignature()); 224 dkSig.setDerivedKeyLength(rpd.getAlgorithmSuite().getSignatureDerivedKeyLength()/8); 225 226 dkSig.setExternalKey(encrKey.getEphemeralKey(), encrKey.getId()); 227 228 dkSig.prepare(doc, rmd.getSecHeader()); 229 230 231 if(rpd.isTokenProtection()) { 232 sigParts.add(new WSEncryptionPart(encrKey.getBSTTokenId())); 233 } 234 235 dkSig.setParts(sigParts); 236 237 dkSig.addReferencesToSign(sigParts, rmd.getSecHeader()); 238 239 //Do signature 240 dkSig.computeSignature(); 241 242 dkSig.appendDKElementToHeader(rmd.getSecHeader()); 243 244 dkSig.appendSigToHeader(rmd.getSecHeader()); 245 246 return dkSig.getSignatureValue(); 247 248 } catch (WSSecurityException e) { 249 throw new RampartException("errorInDerivedKeyTokenSignature", e); 250 } catch (ConversationException e) { 251 throw new RampartException("errorInDerivedKeyTokenSignature", e); 252 } 253 254 } else { 255 256 try { 257 WSSecSignature sig = this.getSignatureBuider(rmd, token); 258 259 260 sig.appendBSTElementToHeader(rmd.getSecHeader()); 261 262 if (rpd.isTokenProtection() 263 && !(SPConstants.INCLUDE_TOKEN_NEVER == token.getInclusion())) { 264 sigParts.add(new WSEncryptionPart(sig.getBSTTokenId())); 265 } 266 267 sig.addReferencesToSign(sigParts, rmd.getSecHeader()); 268 269 sig.appendToHeader(rmd.getSecHeader()); 270 271 sig.computeSignature(); 272 273 return sig.getSignatureValue(); 274 } catch (WSSecurityException e) { 275 throw new RampartException("errorInSignatureWithX509Token", e); 276 } 277 278 279 } 280 281 } 282 283 284 /** 285 * IssuedToken signature 286 * @param rmd 287 * @param token 288 * @param signdParts 289 * @throws RampartException 290 */ 291 private byte[] doIssuedTokenSignature(RampartMessageData rmd, Token token, SignedEncryptedParts signdParts) throws RampartException { 292 293 RampartPolicyData rpd = rmd.getPolicyData(); 294 Document doc= rmd.getDocument(); 295 296 //Get the issued token 297 String id = RampartUtil.getIssuedToken(rmd, (IssuedToken)token); 298 299 int inclusion = token.getInclusion(); 300 org.apache.rahas.Token tok = null; 301 try { 302 tok = rmd.getTokenStorage().getToken(id); 303 } catch (TrustException e) { 304 throw new RampartException("errorExtractingToken", 305 new String[]{id} ,e); 306 } 307 308 boolean tokenIncluded = false; 309 310 if(inclusion == SPConstants.INCLUDE_TOEKN_ALWAYS || 311 ((inclusion == SPConstants.INCLUDE_TOEKN_ALWAYS_TO_RECIPIENT 312 || inclusion == SPConstants.INCLUDE_TOKEN_ONCE) 313 && rmd.isInitiator())) { 314 315 //Add the token 316 rmd.getSecHeader().getSecurityHeader().appendChild( 317 doc.importNode((Element) tok.getToken(), true)); 318 319 tokenIncluded = true; 320 } 321 322 Vector sigParts = new Vector(); 323 324 if(this.timestampElement != null){ 325 sigParts.add(new WSEncryptionPart(rmd.getTimestampId())); 326 } 327 328 329 if(rpd.isTokenProtection() && tokenIncluded) { 330 sigParts.add(new WSEncryptionPart(id)); 331 } 332 333 if(signdParts != null) { 334 if(signdParts.isBody()) { 335 SOAPEnvelope env = rmd.getMsgContext().getEnvelope(); 336 sigParts.add(new WSEncryptionPart(RampartUtil.addWsuIdToElement(env.getBody()))); 337 } 338 339 ArrayList headers = signdParts.getHeaders(); 340 for (Iterator iterator = headers.iterator(); iterator.hasNext();) { 341 Header header = (Header) iterator.next(); 342 WSEncryptionPart wep = new WSEncryptionPart(header.getName(), 343 header.getNamespace(), 344 "Content"); 345 sigParts.add(wep); 346 } 347 } 348 349 //check for derived keys 350 AlgorithmSuite algorithmSuite = rpd.getAlgorithmSuite(); 351 if(token.isDerivedKeys()) { 352 //Create a derived key and add 353 try { 354 355 //Do Signature with derived keys 356 WSSecDKSign dkSign = new WSSecDKSign(); 357 358 // Setting the AttachedReference or the UnattachedReference according to the flag 359 OMElement ref; 360 if (tokenIncluded == true) { 361 ref = tok.getAttachedReference(); 362 } else { 363 ref = tok.getUnattachedReference(); 364 } 365 366 if(ref != null) { 367 dkSign.setExternalKey(tok.getSecret(), (Element) 368 doc.importNode((Element) ref, true)); 369 } else { 370 dkSign.setExternalKey(tok.getSecret(), tok.getId()); 371 } 372 373 //Set the algo info 374 dkSign.setSignatureAlgorithm(algorithmSuite.getSymmetricSignature()); 375 dkSign.setDerivedKeyLength(algorithmSuite.getSignatureDerivedKeyLength()); 376 377 dkSign.prepare(doc); 378 379 dkSign.appendDKElementToHeader(rmd.getSecHeader()); 380 381 dkSign.setParts(sigParts); 382 383 dkSign.addReferencesToSign(sigParts, rmd.getSecHeader()); 384 385 //Do signature 386 dkSign.computeSignature(); 387 388 dkSign.appendSigToHeader(rmd.getSecHeader()); 389 390 return dkSign.getSignatureValue(); 391 392 } catch (ConversationException e) { 393 throw new RampartException( 394 "errorInDerivedKeyTokenSignature", e); 395 } catch (WSSecurityException e) { 396 throw new RampartException( 397 "errorInDerivedKeyTokenSignature", e); 398 } 399 400 } else { 401 try { 402 WSSecSignature sig = new WSSecSignature(); 403 sig.setWsConfig(rmd.getConfig()); 404 sig.setCustomTokenId(tok.getId().substring(1)); 405 sig.setCustomTokenValueType(WSConstants.WSS_SAML_NS + 406 WSConstants.SAML_ASSERTION_ID); 407 sig.setSecretKey(tok.getSecret()); 408 sig.setSignatureAlgorithm(algorithmSuite.getAsymmetricSignature()); 409 sig.setSignatureAlgorithm(algorithmSuite.getSymmetricSignature()); 410 sig.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING); 411 sig.prepare(rmd.getDocument(), RampartUtil.getSignatureCrypto(rpd 412 .getRampartConfig(), rmd.getCustomClassLoader()), 413 rmd.getSecHeader()); 414 415 sig.setParts(sigParts); 416 sig.addReferencesToSign(sigParts, rmd.getSecHeader()); 417 418 //Do signature 419 sig.computeSignature(); 420 421 //Add elements to header 422 this.setInsertionLocation(RampartUtil.insertSiblingAfter( 423 rmd, 424 this.getInsertionLocation(), 425 sig.getSignatureElement())); 426 427 return sig.getSignatureValue(); 428 429 } catch (WSSecurityException e) { 430 throw new RampartException("errorInSignatureWithACustomToken", e); 431 } 432 } 433 } 434 435 private byte[] doSecureConversationSignature(RampartMessageData rmd, Token token, SignedEncryptedParts signdParts) throws RampartException { 436 437 RampartPolicyData rpd = rmd.getPolicyData(); 438 Document doc= rmd.getDocument(); 439 440 //Get the issued token 441 String id = rmd.getSecConvTokenId(); 442 443 int inclusion = token.getInclusion(); 444 org.apache.rahas.Token tok = null; 445 try { 446 tok = rmd.getTokenStorage().getToken(id); 447 } catch (TrustException e) { 448 throw new RampartException("errorExtractingToken", 449 new String[]{id} ,e); 450 } 451 452 boolean tokenIncluded = false; 453 454 if(inclusion == SPConstants.INCLUDE_TOEKN_ALWAYS || 455 ((inclusion == SPConstants.INCLUDE_TOEKN_ALWAYS_TO_RECIPIENT 456 || inclusion == SPConstants.INCLUDE_TOKEN_ONCE) 457 && rmd.isInitiator())) { 458 459 //Add the token 460 rmd.getSecHeader().getSecurityHeader().appendChild( 461 doc.importNode((Element) tok.getToken(), true)); 462 463 tokenIncluded = true; 464 } 465 466 Vector sigParts = new Vector(); 467 468 if(this.timestampElement != null){ 469 sigParts.add(new WSEncryptionPart(rmd.getTimestampId())); 470 } 471 472 473 if(rpd.isTokenProtection() && tokenIncluded) { 474 sigParts.add(new WSEncryptionPart(id)); 475 } 476 477 if(signdParts != null) { 478 if(signdParts.isBody()) { 479 SOAPEnvelope env = rmd.getMsgContext().getEnvelope(); 480 sigParts.add(new WSEncryptionPart(RampartUtil.addWsuIdToElement(env.getBody()))); 481 } 482 483 ArrayList headers = signdParts.getHeaders(); 484 for (Iterator iterator = headers.iterator(); iterator.hasNext();) { 485 Header header = (Header) iterator.next(); 486 WSEncryptionPart wep = new WSEncryptionPart(header.getName(), 487 header.getNamespace(), 488 "Content"); 489 sigParts.add(wep); 490 } 491 } 492 493 //check for derived keys 494 AlgorithmSuite algorithmSuite = rpd.getAlgorithmSuite(); 495 if(token.isDerivedKeys()) { 496 //Create a derived key and add 497 try { 498 499 //Do Signature with derived keys 500 WSSecDKSign dkSign = new WSSecDKSign(); 501 502 // Setting the AttachedReference or the UnattachedReference according to the flag 503 OMElement ref; 504 if (tokenIncluded == true) { 505 ref = tok.getAttachedReference(); 506 } else { 507 ref = tok.getUnattachedReference(); 508 } 509 510 if(ref != null) { 511 dkSign.setExternalKey(tok.getSecret(), (Element) 512 doc.importNode((Element) ref, true)); 513 } else { 514 dkSign.setExternalKey(tok.getSecret(), tok.getId()); 515 } 516 517 //Set the algo info 518 dkSign.setSignatureAlgorithm(algorithmSuite.getSymmetricSignature()); 519 dkSign.setDerivedKeyLength(algorithmSuite.getSignatureDerivedKeyLength()); 520 521 dkSign.prepare(doc); 522 523 dkSign.appendDKElementToHeader(rmd.getSecHeader()); 524 525 dkSign.setParts(sigParts); 526 527 dkSign.addReferencesToSign(sigParts, rmd.getSecHeader()); 528 529 //Do signature 530 dkSign.computeSignature(); 531 532 dkSign.appendSigToHeader(rmd.getSecHeader()); 533 534 return dkSign.getSignatureValue(); 535 536 } catch (ConversationException e) { 537 throw new RampartException( 538 "errorInDerivedKeyTokenSignature", e); 539 } catch (WSSecurityException e) { 540 throw new RampartException( 541 "errorInDerivedKeyTokenSignature", e); 542 } 543 544 } else { 545 try { 546 WSSecSignature sig = new WSSecSignature(); 547 sig.setWsConfig(rmd.getConfig()); 548 sig.setCustomTokenId(tok.getId().substring(1)); 549 sig.setCustomTokenValueType(WSConstants.WSS_SAML_NS + 550 WSConstants.SAML_ASSERTION_ID); 551 sig.setSecretKey(tok.getSecret()); 552 sig.setSignatureAlgorithm(algorithmSuite.getAsymmetricSignature()); 553 sig.setSignatureAlgorithm(algorithmSuite.getSymmetricSignature()); 554 sig.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING); 555 sig.prepare(rmd.getDocument(), RampartUtil.getSignatureCrypto(rpd 556 .getRampartConfig(), rmd.getCustomClassLoader()), 557 rmd.getSecHeader()); 558 559 sig.setParts(sigParts); 560 sig.addReferencesToSign(sigParts, rmd.getSecHeader()); 561 562 //Do signature 563 sig.computeSignature(); 564 565 //Add elements to header 566 this.setInsertionLocation(RampartUtil.insertSiblingAfter( 567 rmd, 568 this.getInsertionLocation(), 569 sig.getSignatureElement())); 570 571 return sig.getSignatureValue(); 572 573 } catch (WSSecurityException e) { 574 throw new RampartException("errorInSignatureWithACustomToken", e); 575 } 576 } 577 } 578 579 private void handleSecureConversationTokens(RampartMessageData rmd, 580 SecureConversationToken secConvTok) throws RampartException { 581 582 583 MessageContext msgContext = rmd.getMsgContext(); 584 585 String secConvTokenId = rmd.getSecConvTokenId(); 586 587 //The RSTR has to be secured with the cancelled token 588 String action = msgContext.getOptions().getAction(); 589 boolean cancelReqResp = action.equals(RahasConstants.WST_NS_05_02 + RahasConstants.RSTR_ACTION_CANCEL_SCT) || 590 action.equals(RahasConstants.WST_NS_05_02 + RahasConstants.RSTR_ACTION_CANCEL_SCT) || 591 action.equals(RahasConstants.WST_NS_05_02 + RahasConstants.RST_ACTION_CANCEL_SCT) || 592 action.equals(RahasConstants.WST_NS_05_02 + RahasConstants.RST_ACTION_CANCEL_SCT); 593 594 //In the case of the cancel req or resp we should mark the token as cancelled 595 if(secConvTokenId != null && cancelReqResp) { 596 try { 597 rmd.getTokenStorage().getToken(secConvTokenId).setState(org.apache.rahas.Token.CANCELLED); 598 msgContext.setProperty(RampartMessageData.SCT_ID, secConvTokenId); 599 600 //remove from the local map of contexts 601 String contextIdentifierKey = RampartUtil.getContextIdentifierKey(msgContext); 602 RampartUtil.getContextMap(msgContext).remove(contextIdentifierKey); 603 } catch (TrustException e) { 604 throw new RampartException("errorExtractingToken",e); 605 } 606 } 607 608 if (secConvTokenId == null 609 || (secConvTokenId != null && 610 (!RampartUtil.isTokenValid(rmd, secConvTokenId) && !cancelReqResp))) { 611 612 log.debug("No SecureConversationToken found, " + 613 "requesting a new token"); 614 615 try { 616 617 secConvTokenId = RampartUtil.getSecConvToken(rmd, secConvTok); 618 rmd.setSecConvTokenId(secConvTokenId); 619 620 } catch (TrustException e) { 621 throw new RampartException("errorInObtainingSct", e); 622 } 623 } 624 625 /* org.apache.rahas.Token token; 626 try { 627 token = rmd.getTokenStorage().getToken(secConvTokenId); 628 } catch (TrustException e) { 629 throw new RampartException("errorExtractingToken", e); 630 } 631 632 633 //Add the token to the header 634 Element siblingElem = RampartUtil 635 .insertSiblingAfter(rmd, this.getInsertionLocation(), 636 (Element) token.getToken()); 637 this.setInsertionLocation(siblingElem);*/ 638 639 } 640 }