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;
18
19 import org.apache.axiom.om.OMElement;
20 import org.apache.axiom.soap.SOAPEnvelope;
21 import org.apache.axis2.AxisFault;
22 import org.apache.axis2.context.MessageContext;
23 import org.apache.axis2.context.OperationContext;
24 import org.apache.axis2.description.AxisService;
25 import org.apache.axis2.description.Parameter;
26 import org.apache.axis2.wsdl.WSDLConstants;
27 import org.apache.neethi.Policy;
28 import org.apache.neethi.PolicyEngine;
29 import org.apache.rahas.RahasConstants;
30 import org.apache.rahas.SimpleTokenStore;
31 import org.apache.rahas.TokenStorage;
32 import org.apache.rahas.TrustException;
33 import org.apache.rahas.TrustUtil;
34 import org.apache.rampart.handler.WSSHandlerConstants;
35 import org.apache.rampart.policy.RampartPolicyBuilder;
36 import org.apache.rampart.policy.RampartPolicyData;
37 import org.apache.rampart.policy.model.RampartConfig;
38 import org.apache.rampart.util.Axis2Util;
39 import org.apache.rampart.util.RampartUtil;
40 import org.apache.ws.secpolicy.WSSPolicyException;
41 import org.apache.ws.security.SOAPConstants;
42 import org.apache.ws.security.WSConstants;
43 import org.apache.ws.security.WSSConfig;
44 import org.apache.ws.security.WSSecurityEngineResult;
45 import org.apache.ws.security.WSSecurityException;
46 import org.apache.ws.security.conversation.ConversationConstants;
47 import org.apache.ws.security.handler.WSHandlerConstants;
48 import org.apache.ws.security.handler.WSHandlerResult;
49 import org.apache.ws.security.message.WSSecHeader;
50 import org.apache.ws.security.message.token.SecurityContextToken;
51 import org.apache.ws.security.util.Loader;
52 import org.apache.ws.security.util.WSSecurityUtil;
53 import org.opensaml.SAMLAssertion;
54 import org.w3c.dom.Document;
55
56 import java.util.List;
57 import java.util.Vector;
58
59 public class RampartMessageData {
60
61 /**
62 * Axis2 parameter name to be used in the client's axis2 xml
63 */
64 public final static String KEY_RAMPART_POLICY = "rampartPolicy";
65
66 /**
67 * Key to hold the populated RampartPolicyData object
68 */
69 public final static String RAMPART_POLICY_DATA = "rampartPolicyData";
70
71 public final static String RAMPART_STS_POLICY = "rampartStsPolicy";
72
73 /**
74 * Key to hold the custom issued token identifier
75 */
76 public final static String KEY_CUSTOM_ISSUED_TOKEN = "customIssuedToken";
77
78 /**
79 * Key to hold the WS-Trust version
80 */
81 public final static String KEY_WST_VERSION = "wstVersion";
82
83 public final static String PARAM_CLIENT_SIDE = "CLIENT_SIDE";
84
85 /**
86 * Key to hold the WS-SecConv version
87 */
88 public final static String KEY_WSSC_VERSION = "wscVersion";
89
90 public static final String KEY_SCT_ISSUER_POLICY = "sct-issuer-policy";
91
92 public final static String CANCEL_REQUEST = "cancelrequest";
93
94 public final static String SCT_ID = "sctID";
95
96 private MessageContext msgContext = null;
97
98 private RampartPolicyData policyData = null;
99
100 private WSSecHeader secHeader = null;
101
102 private WSSConfig config = null;
103
104 private int timeToLive = 300;
105
106 private int timestampMaxSkew = 0;
107
108 private String timestampId;
109
110 private Document document;
111
112 private TokenStorage tokenStorage;
113
114 /**
115 * WS-Trust version to use.
116 *
117 * Possible values:
118 * RahasConstants.VERSION_05_02
119 * RahasConstants.VERSION_05_12
120 */
121
122 private int wstVersion = RahasConstants.VERSION_05_02;
123
124 private int secConvVersion = ConversationConstants.DEFAULT_VERSION;
125
126 /*
127 * IssuedTokens or SecurityContextTokens can be used
128 * as the encryption token, signature token
129 */
130 private String issuedEncryptionTokenId;
131
132 private String issuedSignatureTokenId;
133
134 /**
135 * The service policy extracted from the message context.
136 * If policy is specified in the RampartConfig <b>this</b> will take precedence
137 */
138 private Policy servicePolicy;
139
140 private boolean isInitiator;
141
142 private boolean sender;
143
144 private ClassLoader customClassLoader;
145
146 private SOAPConstants soapConstants;
147
148 public RampartMessageData(MessageContext msgCtx, boolean sender) throws RampartException {
149
150 this.msgContext = msgCtx;
151
152 try {
153
154 /*
155 * First get the SOAP envelope as document, then create a security
156 * header and insert into the document (Envelope)
157 */
158 this.document = Axis2Util.getDocumentFromSOAPEnvelope(msgCtx.getEnvelope(), true);
159 msgCtx.setEnvelope((SOAPEnvelope)this.document.getDocumentElement());
160
161 this.soapConstants = WSSecurityUtil.getSOAPConstants(this.document.getDocumentElement());
162
163 //Extract known properties from the msgCtx
164
165 if(msgCtx.getProperty(KEY_WST_VERSION) != null) {
166 this.wstVersion = TrustUtil.getWSTVersion((String)msgCtx.getProperty(KEY_WST_VERSION));
167 }
168
169 if(msgCtx.getProperty(KEY_WSSC_VERSION) != null) {
170 this.secConvVersion = TrustUtil.getWSTVersion((String)msgCtx.getProperty(KEY_WSSC_VERSION));
171 }
172
173 // First obtain the axis service as we have to do a null check, there can be situations
174 // where Axis Service is null
175 AxisService axisService = msgCtx.getAxisService();
176
177 if(axisService != null && axisService.getParameter(PARAM_CLIENT_SIDE) != null) {
178 this.isInitiator = true;
179 } else {
180 this.isInitiator = !msgCtx.isServerSide();
181 //TODO if Axis Service is null at this point, do we have to create a dummy one ??
182 if(this.isInitiator && axisService != null ) {
183 Parameter clientSideParam = new Parameter();
184 clientSideParam.setName(PARAM_CLIENT_SIDE);
185 clientSideParam.setLocked(true);
186 msgCtx.getAxisService().addParameter(clientSideParam);
187 }
188 }
189
190 if(msgCtx.getProperty(KEY_RAMPART_POLICY) != null) {
191 this.servicePolicy = (Policy)msgCtx.getProperty(KEY_RAMPART_POLICY);
192 }
193
194 /*
195 * Init policy:
196 * When creating the RampartMessageData instance we
197 * extract the service policy is set in the msgCtx.
198 * If it is missing then try to obtain from the configuration files.
199 */
200
201 if(this.servicePolicy == null) {
202 this.servicePolicy = msgCtx.getEffectivePolicy();
203 }
204
205 if(this.servicePolicy == null) {
206 Parameter param = msgCtx.getParameter(RampartMessageData.KEY_RAMPART_POLICY);
207 if(param != null) {
208 OMElement policyElem = param.getParameterElement().getFirstElement();
209 this.servicePolicy = PolicyEngine.getPolicy(policyElem);
210 }
211 }
212
213
214 if(this.servicePolicy != null){
215 List it = (List)this.servicePolicy.getAlternatives().next();
216
217 //Process policy and build policy data
218 this.policyData = RampartPolicyBuilder.build(it);
219 }
220
221
222 if(this.policyData != null) {
223
224 //Check for RST and RSTR for an SCT
225 if((WSSHandlerConstants.RST_ACTON_SCT.equals(msgContext.getWSAAction())
226 || WSSHandlerConstants.RSTR_ACTON_SCT.equals(msgContext.getWSAAction())) &&
227 this.policyData.getIssuerPolicy() != null) {
228
229 this.servicePolicy = this.policyData.getIssuerPolicy();
230
231 RampartConfig rampartConfig = policyData.getRampartConfig();
232 if(rampartConfig != null) {
233 /*
234 * Copy crypto info into the new issuer policy
235 */
236 RampartConfig rc = new RampartConfig();
237 rc.setEncrCryptoConfig(rampartConfig.getEncrCryptoConfig());
238 rc.setSigCryptoConfig(rampartConfig.getSigCryptoConfig());
239 rc.setDecCryptoConfig(rampartConfig.getDecCryptoConfig());
240 rc.setUser(rampartConfig.getUser());
241 rc.setEncryptionUser(rampartConfig.getEncryptionUser());
242 rc.setPwCbClass(rampartConfig.getPwCbClass());
243 rc.setSSLConfig(rampartConfig.getSSLConfig());
244
245 this.servicePolicy.addAssertion(rc);
246 }
247
248 List it = (List)this.servicePolicy.getAlternatives().next();
249
250 //Process policy and build policy data
251 this.policyData = RampartPolicyBuilder.build(it);
252 }
253 }
254
255
256 this.sender = sender;
257
258 OperationContext opCtx = this.msgContext.getOperationContext();
259
260 if(!this.isInitiator && this.sender) {
261 //Get hold of the incoming msg ctx
262 MessageContext inMsgCtx;
263 if (opCtx != null
264 && (inMsgCtx = opCtx
265 .getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE)) != null
266 && msgContext.getProperty(WSHandlerConstants.RECV_RESULTS) == null) {
267 msgContext.setProperty(WSHandlerConstants.RECV_RESULTS,
268 inMsgCtx.getProperty(WSHandlerConstants.RECV_RESULTS));
269
270 //If someone set the sct_id externally use it at the receiver
271 msgContext.setProperty(SCT_ID, inMsgCtx.getProperty(SCT_ID));
272 }
273 }
274
275 if(this.isInitiator && !this.sender) {
276 MessageContext outMsgCtx;
277 if (opCtx != null
278 && (outMsgCtx = opCtx
279 .getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE)) != null) {
280
281 //If someone set the sct_id externally use it at the receiver
282 msgContext.setProperty(SCT_ID, outMsgCtx.getProperty(SCT_ID));
283 }
284 }
285
286 // Check whether RampartConfig is present
287 if (this.policyData != null && this.policyData.getRampartConfig() != null) {
288
289 boolean timestampPrecisionInMilliseconds = Boolean.valueOf(this.policyData
290 .getRampartConfig().getTimestampPrecisionInMilliseconds()).booleanValue();
291
292 // This is not the default behavior, we clone the default WSSConfig to prevent this
293 // affecting globally
294 if (timestampPrecisionInMilliseconds == WSSConfig.getDefaultWSConfig()
295 .isPrecisionInMilliSeconds()) {
296 this.config = WSSConfig.getDefaultWSConfig();
297 } else {
298 this.config = RampartUtil.getWSSConfigInstance();
299 this.config.setPrecisionInMilliSeconds(timestampPrecisionInMilliseconds);
300 }
301 } else {
302 this.config = WSSConfig.getDefaultWSConfig();
303 }
304
305
306
307
308 this.customClassLoader = msgCtx.getAxisService().getClassLoader();
309
310 if(this.sender && this.policyData != null) {
311 this.secHeader = new WSSecHeader();
312 secHeader.insertSecurityHeader(this.document);
313 }
314
315 } catch (TrustException e) {
316 throw new RampartException("errorInExtractingMsgProps", e);
317 } catch (AxisFault e) {
318 throw new RampartException("errorInExtractingMsgProps", e);
319 } catch (WSSPolicyException e) {
320 throw new RampartException("errorInExtractingMsgProps", e);
321 } catch (WSSecurityException e) {
322 throw new RampartException("errorInExtractingMsgProps", e);
323 }
324
325 }
326
327 /**
328 * @return Returns the document.
329 */
330 public Document getDocument() {
331 return document;
332 }
333
334 /**
335 * @param document The document to set.
336 * @deprecated document is derived from MessageContext passed in constructor
337 */
338 public void setDocument(Document document) {
339 this.document = document;
340 }
341
342 /**
343 * @return Returns the timeToLive.
344 */
345 public int getTimeToLive() {
346 return timeToLive;
347 }
348
349 /**
350 * @param timeToLive The timeToLive to set.
351 */
352 public void setTimeToLive(int timeToLive) {
353 this.timeToLive = timeToLive;
354 }
355
356 /**
357 * @return Returns the timestampMaxSkew.
358 */
359 public int getTimestampMaxSkew() {
360 return timestampMaxSkew;
361 }
362
363 /**
364 * @param timestampMaxSkew The timestampMaxSkew to set.
365 */
366 public void setTimestampMaxSkew(int timestampMaxSkew) {
367 this.timestampMaxSkew = timestampMaxSkew;
368 }
369
370 /**
371 * @return Returns the config.
372 */
373 public WSSConfig getConfig() {
374 return config;
375 }
376
377 /**
378 * @param config
379 * The config to set.
380 */
381 public void setConfig(WSSConfig config) {
382 this.config = config;
383 }
384
385 /**
386 * @return Returns the msgContext.
387 */
388 public MessageContext getMsgContext() {
389 return msgContext;
390 }
391
392 /**
393 * @param msgContext The msgContext to set.
394 * @deprecated MessageContext is set in constructor
395 */
396 public void setMsgContext(MessageContext msgContext) {
397 this.msgContext = msgContext;
398 }
399
400 /**
401 * @return Returns the policyData.
402 */
403 public RampartPolicyData getPolicyData() {
404 return policyData;
405 }
406
407 /**
408 * @param policyData The policyData to set.
409 * @deprecated Policy data determined within constructor
410 */
411 public void setPolicyData(RampartPolicyData policyData) throws RampartException {
412 this.policyData = policyData;
413
414 try {
415 //if client side then check whether sig conf enabled
416 //and get hold of the stored signature values
417 if(this.isInitiator && !this.sender && policyData.isSignatureConfirmation()) {
418 OperationContext opCtx = msgContext.getOperationContext();
419 MessageContext outMsgCtx = opCtx
420 .getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
421 msgContext.setProperty(WSHandlerConstants.SEND_SIGV, outMsgCtx
422 .getProperty(WSHandlerConstants.SEND_SIGV));
423 }
424 } catch (AxisFault e) {
425 throw new RampartException("errorGettingSignatureValuesForSigconf", e);
426 }
427 }
428
429 /**
430 * @return Returns the secHeader.
431 */
432 public WSSecHeader getSecHeader() {
433 return secHeader;
434 }
435
436 /**
437 * @param secHeader
438 * The secHeader to set.
439 */
440 public void setSecHeader(WSSecHeader secHeader) {
441 this.secHeader = secHeader;
442 }
443
444 /**
445 * @return Returns the issuedEncryptionTokenId.
446 */
447 public String getIssuedEncryptionTokenId() {
448 return issuedEncryptionTokenId;
449 }
450
451 /**
452 * @param issuedEncryptionTokenId The issuedEncryptionTokenId to set.
453 */
454 public void setIssuedEncryptionTokenId(String issuedEncryptionTokenId) {
455 this.issuedEncryptionTokenId = issuedEncryptionTokenId;
456 }
457
458 /**
459 * @return Returns the issuedSignatureTokenId.
460 */
461 public String getIssuedSignatureTokenId() {
462 if(this.isInitiator) {
463 return issuedSignatureTokenId;
464 } else {
465 //Pick the first SAML token
466 //TODO : This is a hack , MUST FIX
467 //get the sec context id from the req msg ctx
468 Vector results = (Vector)this.msgContext.getProperty(WSHandlerConstants.RECV_RESULTS);
469 for (int i = 0; i < results.size(); i++) {
470 WSHandlerResult rResult = (WSHandlerResult) results.get(i);
471 Vector wsSecEngineResults = rResult.getResults();
472
473 for (int j = 0; j < wsSecEngineResults.size(); j++) {
474 WSSecurityEngineResult wser = (WSSecurityEngineResult) wsSecEngineResults
475 .get(j);
476 final Integer actInt =
477 (Integer)wser.get(WSSecurityEngineResult.TAG_ACTION);
478 if(WSConstants.ST_UNSIGNED == actInt.intValue()) {
479 final SAMLAssertion assertion =
480 ((SAMLAssertion) wser
481 .get(WSSecurityEngineResult.TAG_SAML_ASSERTION));
482 return assertion.getId();
483 }
484
485 }
486 }
487 return null;
488 }
489 }
490
491 /**
492 * @param issuedSignatureTokenId The issuedSignatureTokenId to set.
493 */
494 public void setIssuedSignatureTokenId(String issuedSignatureTokenId) {
495 this.issuedSignatureTokenId = issuedSignatureTokenId;
496 }
497
498 /**
499 * @return Returns the secConvTokenId.
500 */
501 public String getSecConvTokenId() {
502 String id = null;
503
504 if(this.isInitiator) {
505 String contextIdentifierKey = RampartUtil.getContextIdentifierKey(this.msgContext);
506 id = (String) RampartUtil.getContextMap(this.msgContext).get(contextIdentifierKey);
507 } else {
508 //get the sec context id from the req msg ctx
509 Vector results = (Vector)this.msgContext.getProperty(WSHandlerConstants.RECV_RESULTS);
510 for (int i = 0; i < results.size(); i++) {
511 WSHandlerResult rResult = (WSHandlerResult) results.get(i);
512 Vector wsSecEngineResults = rResult.getResults();
513
514 for (int j = 0; j < wsSecEngineResults.size(); j++) {
515 WSSecurityEngineResult wser = (WSSecurityEngineResult) wsSecEngineResults
516 .get(j);
517 final Integer actInt =
518 (Integer)wser.get(WSSecurityEngineResult.TAG_ACTION);
519 if(WSConstants.SCT == actInt.intValue()) {
520 final SecurityContextToken sct =
521 ((SecurityContextToken) wser
522 .get(WSSecurityEngineResult.TAG_SECURITY_CONTEXT_TOKEN));
523 id = sct.getID();
524 }
525
526 }
527 }
528 }
529
530 if(id == null || id.length() == 0) {
531 //If we can't find the sec conv token id up to this point then
532 //check if someone has specified which one to use
533 id = (String)this.msgContext.getProperty(SCT_ID);
534 }
535
536 return id;
537 }
538
539 /**
540 * @param secConvTokenId The secConvTokenId to set.
541 */
542 public void setSecConvTokenId(String secConvTokenId) {
543 String contextIdentifierKey = RampartUtil.getContextIdentifierKey(this.msgContext);
544 RampartUtil.getContextMap(this.msgContext).put(
545 contextIdentifierKey,
546 secConvTokenId);
547 }
548
549
550
551 /**
552 * @return Returns the tokenStorage.
553 */
554 public TokenStorage getTokenStorage() throws RampartException {
555
556 if(this.tokenStorage != null) {
557 return this.tokenStorage;
558 }
559
560 TokenStorage storage = (TokenStorage) this.msgContext.getProperty(
561 TokenStorage.TOKEN_STORAGE_KEY);
562
563 if (storage != null) {
564 this.tokenStorage = storage;
565 } else {
566
567 if (this.policyData.getRampartConfig() != null &&
568 this.policyData.getRampartConfig().getTokenStoreClass() != null) {
569 Class stClass = null;
570 String storageClass = this.policyData.getRampartConfig()
571 .getTokenStoreClass();
572 try {
573 stClass = Loader.loadClass(msgContext.getAxisService()
574 .getClassLoader(), storageClass);
575 } catch (ClassNotFoundException e) {
576 throw new RampartException(
577 "WSHandler: cannot load token storage class: "
578 + storageClass, e);
579 }
580 try {
581 this.tokenStorage = (TokenStorage) stClass.newInstance();
582 } catch (java.lang.Exception e) {
583 throw new RampartException(
584 "Cannot create instance of token storage: "
585 + storageClass, e);
586 }
587 } else {
588 this.tokenStorage = new SimpleTokenStore();
589
590 }
591
592 //Set the storage instance
593 this.msgContext.getConfigurationContext().setProperty(
594 TokenStorage.TOKEN_STORAGE_KEY, this.tokenStorage);
595 }
596
597
598 return tokenStorage;
599 }
600
601 /**
602 * @param tokenStorage The tokenStorage to set.
603 */
604 public void setTokenStorage(TokenStorage tokenStorage) {
605 this.tokenStorage = tokenStorage;
606 }
607
608 /**
609 * @return Returns the wstVersion.
610 */
611 public int getWstVersion() {
612 return wstVersion;
613 }
614
615 /**
616 * @param wstVersion The wstVersion to set.
617 * @deprecated This is defined by the class.
618 */
619 public void setWstVersion(int wstVersion) {
620 this.wstVersion = wstVersion;
621 }
622
623 /**
624 * @return Returns the secConvVersion.
625 */
626 public int getSecConvVersion() {
627 return secConvVersion;
628 }
629
630 /**
631 * @return Returns the servicePolicy.
632 */
633 public Policy getServicePolicy() {
634 return servicePolicy;
635 }
636
637 /**
638 * @param servicePolicy The servicePolicy to set.
639 * @deprecated servicePolicy determined in constructor
640 */
641 public void setServicePolicy(Policy servicePolicy) {
642 this.servicePolicy = servicePolicy;
643 }
644
645 /**
646 * @return Returns the timestampId.
647 */
648 public String getTimestampId() {
649 return timestampId;
650 }
651
652 /**
653 * @param timestampId The timestampId to set.
654 */
655 public void setTimestampId(String timestampId) {
656 this.timestampId = timestampId;
657 }
658
659 /**
660 * @return Returns the Initiator value
661 */
662 public boolean isInitiator() {
663 return isInitiator;
664 }
665
666 /**
667 * Returns the custom class loader if we are using one
668 * @return Returns the custom class loader if we are using one
669 */
670 public ClassLoader getCustomClassLoader() {
671 return customClassLoader;
672 }
673
674 /**
675 * Returns an <code>org.apache.ws.security.SOAPConstants</code> instance
676 * with soap version information of this request.
677 * @return Returns soap version information of this request
678 */
679 public SOAPConstants getSoapConstants() {
680 return soapConstants;
681 }
682 }