blob: ecb7f2a1e2d32d7dee3c805d5e145d890c2ca734 [file] [log] [blame]
/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rahas;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axiom.util.base64.Base64Utils;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.context.MessageContext;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.apache.wss4j.dom.handler.WSHandlerResult;
import org.apache.wss4j.common.token.SecurityTokenReference;
import org.opensaml.saml.saml1.core.Assertion;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.List;
/**
* Common data items on WS-Trust request messages
*/
public class RahasData {
private MessageContext inMessageContext;
private OMElement rstElement;
private int version = -1;
private String wstNs;
private String requestType;
private String tokenType;
private String tokenId;
private int keySize = -1;
private String computedKeyAlgo;
private String keyType;
private String appliesToAddress;
private OMElement appliesToEpr;
private Principal principal;
private X509Certificate clientCert;
private byte[] ephmeralKey;
private byte[] requestEntropy;
private byte[] responseEntropy;
private String addressingNs;
private String soapNs;
private OMElement claimElem;
private String claimDialect;
private Assertion assertion;
private Date assertionCreatedDate;
private Date assertionExpiringDate;
/**
* Create a new RahasData instance and populate it with the information from
* the request.
*
* @throws TrustException <code>RequestSecurityToken</code> element is invalid.
*/
public RahasData(MessageContext inMessageContext) throws TrustException {
this.inMessageContext = inMessageContext;
//Check for an authenticated Principal
this.processWSS4JSecurityResults();
// Find out the incoming addressing version
this.addressingNs = (String) this.inMessageContext
.getProperty(AddressingConstants.WS_ADDRESSING_VERSION);
this.rstElement = this.inMessageContext.getEnvelope().getBody()
.getFirstElement();
this.soapNs = this.inMessageContext.getEnvelope().getNamespace()
.getNamespaceURI();
this.wstNs = this.rstElement.getNamespace().getNamespaceURI();
int ver = TrustUtil.getWSTVersion(this.wstNs);
if (ver == -1) {
throw new TrustException(TrustException.INVALID_REQUEST);
} else {
this.version = ver;
}
this.processRequestType();
this.processTokenType();
this.processKeyType();
this.processKeySize();
this.processAppliesTo();
this.processEntropy();
this.processClaims();
this.processValidateTarget();
this.processRenewTarget();
}
public RahasData() {
}
/**
* Processes the authenticated user information from the WSS4J security
* results.
*
* @throws TrustException
*/
private void processWSS4JSecurityResults() throws TrustException {
/*
* User can be identifier using a UsernameToken or a certificate - If a
* certificate is found then we use that to - identify the user and -
* encrypt the response (if required) - If a UsernameToken is found then
* we will not be encrypting the response
*/
List<WSHandlerResult> results;
if ((results = (List<WSHandlerResult>) this.inMessageContext
.getProperty(WSHandlerConstants.RECV_RESULTS)) == null) {
throw new TrustException(TrustException.REQUEST_FAILED);
} else {
for (WSHandlerResult result : results) {
List<WSSecurityEngineResult> wsSecEngineResults = result.getResults();
for (WSSecurityEngineResult wser : wsSecEngineResults) {
Object principalObject = wser.get(WSSecurityEngineResult.TAG_PRINCIPAL);
int act = (Integer) wser.get(WSSecurityEngineResult.TAG_ACTION);
if (act == WSConstants.SIGN && principalObject != null) {
this.clientCert = (X509Certificate) wser
.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
this.principal = (Principal) principalObject;
} else if (act == WSConstants.UT && principalObject != null) {
this.principal = (Principal) principalObject;
} else if (act == WSConstants.BST) {
final X509Certificate[] certificates =
(X509Certificate[]) wser
.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
this.clientCert = certificates[0];
this.principal = this.clientCert.getSubjectDN();
} else if (act == WSConstants.ST_UNSIGNED) {
this.assertion = (Assertion) wser
.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
}
}
}
// If the principal or a SAML assertion is missing
if (this.principal == null && this.assertion == null) {
throw new TrustException(TrustException.REQUEST_FAILED);
}
}
}
private void processAppliesTo() throws TrustException {
OMElement appliesToElem = this.rstElement
.getFirstChildWithName(new QName(RahasConstants.WSP_NS,
RahasConstants.IssuanceBindingLocalNames.
APPLIES_TO));
if (appliesToElem != null) {
OMElement eprElem = appliesToElem.getFirstElement();
this.appliesToEpr = eprElem;
// If there were no addressing headers
// The find the addressing version using the EPR element
if (this.addressingNs == null) {
this.addressingNs = eprElem.getNamespace()
.getNamespaceURI();
}
if (eprElem != null) {
//Of the epr is a web service then try to get the addr
OMElement addrElem = eprElem
.getFirstChildWithName(new QName(
this.addressingNs,
AddressingConstants.EPR_ADDRESS));
if (addrElem != null && addrElem.getText() != null
&& !"".equals(addrElem.getText().trim())) {
this.appliesToAddress = addrElem.getText().trim();
}
} else {
throw new TrustException("invalidAppliesToElem");
}
}
}
private void processRequestType() throws TrustException {
OMElement reqTypeElem = this.rstElement
.getFirstChildWithName(new QName(this.wstNs,
RahasConstants.LocalNames.REQUEST_TYPE));
if (reqTypeElem == null ||
reqTypeElem.getText() == null ||
reqTypeElem.getText().trim().length() == 0) {
throw new TrustException(TrustException.INVALID_REQUEST);
} else {
this.requestType = reqTypeElem.getText().trim();
}
}
private void processTokenType() {
OMElement tokTypeElem = this.rstElement
.getFirstChildWithName(new QName(this.wstNs,
RahasConstants.LocalNames.TOKEN_TYPE));
if (tokTypeElem != null && tokTypeElem.getText() != null
&& !"".equals(tokTypeElem.getText().trim())) {
this.tokenType = tokTypeElem.getText().trim();
}
}
/**
* Find the value of the KeyType element of the RST
*/
private void processKeyType() {
OMElement keyTypeElem = this.rstElement
.getFirstChildWithName(new QName(this.wstNs,
RahasConstants.IssuanceBindingLocalNames.KEY_TYPE));
if (keyTypeElem != null) {
String text = keyTypeElem.getText();
if (text != null && !"".equals(text.trim())) {
this.keyType = text.trim();
}
}
}
/**
* Finds the KeySize and creates an empty ephmeral key.
*
* @throws TrustException
*/
private void processKeySize() throws TrustException {
OMElement keySizeElem =
this.rstElement
.getFirstChildWithName(new QName(this.wstNs,
RahasConstants.IssuanceBindingLocalNames.
KEY_SIZE));
if (keySizeElem != null) {
String text = keySizeElem.getText();
if (text != null && !"".equals(text.trim())) {
try {
//Set key size
this.keySize = Integer.parseInt(text.trim());
//Create an empty array to hold the key
this.ephmeralKey = new byte[this.keySize/8];
} catch (NumberFormatException e) {
throw new TrustException(TrustException.INVALID_REQUEST,
new String[]{"invalid wst:Keysize value"}, e);
}
}
}
this.keySize = -1;
}
/**
* Processes a claims.
*
*/
private void processClaims() throws TrustException{
claimElem = this.rstElement
.getFirstChildWithName(new QName(this.wstNs,
RahasConstants.IssuanceBindingLocalNames.CLAIMS));
if(claimElem != null){
claimDialect = claimElem.getAttributeValue(new QName(this.wstNs,
RahasConstants.ATTR_CLAIMS_DIALECT));
}
}
private void processValidateTarget()throws TrustException{
OMElement validateTargetElem = this.rstElement
.getFirstChildWithName(new QName(this.wstNs,
RahasConstants.LocalNames.VALIDATE_TARGET));
if (validateTargetElem != null) {
OMElement strElem = validateTargetElem.getFirstChildWithName(new QName(WSConstants.WSSE_NS,
"SecurityTokenReference"));
Element elem = (Element)OMXMLBuilderFactory.createStAXOMBuilder(
OMAbstractFactory.getMetaFactory(OMAbstractFactory.FEATURE_DOM).getOMFactory(),
strElem.getXMLStreamReader()).getDocumentElement();
try {
Document doc = elem.getOwnerDocument();
SecurityTokenReference str = new SecurityTokenReference(doc);
if (str.containsReference()) {
tokenId = str.getReference().getURI();
} else if(str.containsKeyIdentifier()){
tokenId = str.getKeyIdentifierValue();
}
} catch (WSSecurityException e) {
throw new TrustException("errorExtractingTokenId",e);
}
}
}
private void processRenewTarget()throws TrustException{
OMElement renewTargetElem = this.rstElement
.getFirstChildWithName(new QName(this.wstNs,
RahasConstants.LocalNames.RENEW_TARGET));
if (renewTargetElem != null) {
OMElement strElem = renewTargetElem.getFirstChildWithName(new QName(WSConstants.WSSE_NS,
"SecurityTokenReference"));
Element elem = (Element)OMXMLBuilderFactory.createStAXOMBuilder(
OMAbstractFactory.getMetaFactory(OMAbstractFactory.FEATURE_DOM).getOMFactory(),
strElem.getXMLStreamReader()).getDocumentElement();
try {
Document doc = elem.getOwnerDocument();
SecurityTokenReference str = new SecurityTokenReference(doc);
if (str.containsReference()) {
tokenId = str.getReference().getURI();
} else if(str.containsKeyIdentifier()){
tokenId = str.getKeyIdentifierValue();
}
if(tokenId == null){
if(str.containsKeyIdentifier()){
tokenId = str.getKeyIdentifierValue();
}
}
} catch (WSSecurityException e) {
throw new TrustException("errorExtractingTokenId",e);
}
}
}
/**
* Process wst:Entropy element in the request.
*/
private void processEntropy() throws TrustException {
OMElement entropyElem = this.rstElement
.getFirstChildWithName(new QName(this.wstNs,
RahasConstants.IssuanceBindingLocalNames.ENTROPY));
if (entropyElem != null) {
OMElement binSecElem = entropyElem.getFirstElement();
if (binSecElem != null && binSecElem.getText() != null
&& !"".equals(binSecElem.getText())) {
this.requestEntropy = Base64Utils.decode(binSecElem.getText());
} else {
throw new TrustException("malformedEntropyElement",
new String[]{entropyElem.toString()});
}
}
}
/**
* @return Returns the appliesToAddress.
*/
public String getAppliesToAddress() {
return appliesToAddress;
}
/**
* @return Returns the clientCert.
*/
public X509Certificate getClientCert() {
return clientCert;
}
/**
* @return Returns the computedKeyAlgo.
*/
public String getComputedKeyAlgo() {
return computedKeyAlgo;
}
/**
* @return Returns the ephmeralKey.
*/
public byte[] getEphmeralKey() {
return ephmeralKey;
}
/**
* @return Returns the inMessageContext.
*/
public MessageContext getInMessageContext() {
return inMessageContext;
}
/**
* Sets the given message context as in message context.
* @param context The message context.
*/
public void setInMessageContext(MessageContext context) {
this.inMessageContext = context;
}
/**
* @deprecated As of Rampart 1.7. Use {@code getKeySize}.
* @return Returns the keysize.
*/
@Deprecated
public int getKeysize() {
return keySize;
}
/**
* @return Returns the keySize.
*/
public int getKeySize() {
return keySize;
}
/**
* Sets the key size.
* @param size Size of the key.
*/
public void setKeySize(int size) {
this.keySize = size;
}
/**
* // TODO changes this keytype to an enumeration
* @return Returns the keyType.
*/
public String getKeyType() {
return keyType;
}
/**
* @return Returns the principal.
*/
public Principal getPrincipal() {
return principal;
}
/**
* @return Returns the requestEntropy.
*/
public byte[] getRequestEntropy() {
return requestEntropy;
}
/**
* @return Returns the requestType.
*/
public String getRequestType() {
return requestType;
}
/**
* @return Returns the responseEntropy.
*/
public byte[] getResponseEntropy() {
return responseEntropy;
}
/**
* @return Returns the rstElement.
*/
public OMElement getRstElement() {
return rstElement;
}
/**
* @return Returns the tokenType.
*/
public String getTokenType() {
return tokenType;
}
/**
* @return Returns the version.
*/
public int getVersion() {
return version;
}
/**
* @return Returns the addressingNs.
*/
public String getAddressingNs() {
return addressingNs;
}
/**
* @return Returns the wstNs.
*/
public String getWstNs() {
return wstNs;
}
/**
* @return Returns the soapNs.
*/
public String getSoapNs() {
return soapNs;
}
/**
* @return Returns the tokenId.
*/
public String getTokenId() {
return tokenId;
}
/**
* @param responseEntropy The responseEntropy to set.
*/
public void setResponseEntropy(byte[] responseEntropy) {
this.responseEntropy = responseEntropy;
}
/**
* @param ephmeralKey The ephmeralKey to set.
*/
public void setEphmeralKey(byte[] ephmeralKey) {
this.ephmeralKey = ephmeralKey;
}
public String getClaimDialect() {
return claimDialect;
}
public OMElement getClaimElem() {
return claimElem;
}
public OMElement getAppliesToEpr() {
return appliesToEpr;
}
public Date getAssertionCreatedDate() {
return assertionCreatedDate;
}
public void setAssertionCreatedDate(Date assertionCreatedDate) {
this.assertionCreatedDate = assertionCreatedDate;
}
public Date getAssertionExpiringDate() {
return assertionExpiringDate;
}
public void setAssertionExpiringDate(Date assertionExpiringDate) {
this.assertionExpiringDate = assertionExpiringDate;
}
}