From 2be20a1a550aa2d38f61683ad7afcd9bde15a3f9 Mon Sep 17 00:00:00 2001 From: Sergius Mohr Date: Fri, 13 Mar 2020 09:31:44 +0100 Subject: [PATCH] [CXF-8236] add support of signature challenges in the STSClient --- .../ws/security/trust/AbstractSTSClient.java | 10 +++ .../cxf/ws/security/trust/STSClient.java | 76 +++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/AbstractSTSClient.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/AbstractSTSClient.java index 39865769977..bd0d7d8bd9b 100755 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/AbstractSTSClient.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/AbstractSTSClient.java @@ -1491,6 +1491,16 @@ protected SecurityToken createSecurityToken(Element el, byte[] requestorEntropy) tt = DOMUtils.getContent(el); } else if ("KeySize".equals(ln)) { retKeySize = DOMUtils.getContent(el); + } else if ("SignChallenge".equals(ln)) { + el = DOMUtils.getFirstElement(el); + if ("Challenge".equals(el.getLocalName())) { + // maybe another implementation of the return object is more useful. + // We need to transport only two values: + // challengeValue and a marker for the kind of response (SignChallenge response) + SecurityToken token = new SecurityToken(DOMUtils.getContent(el)); + token.setTokenType("SignChallenge"); + return token; + } } } el = DOMUtils.getNextElement(el); diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java index a160b4cd673..329ee624c03 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java @@ -25,17 +25,23 @@ import java.util.logging.Level; import java.util.logging.Logger; +import javax.xml.transform.dom.DOMSource; + import org.w3c.dom.Element; import org.apache.cxf.Bus; import org.apache.cxf.attachment.AttachmentUtil; +import org.apache.cxf.binding.soap.SoapBindingConstants; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.Attachment; import org.apache.cxf.message.Message; import org.apache.cxf.phase.PhaseInterceptorChain; +import org.apache.cxf.service.model.BindingOperationInfo; +import org.apache.cxf.staxutils.W3CDOMStreamWriter; import org.apache.cxf.ws.security.tokenstore.SecurityToken; +import org.apache.cxf.ws.security.trust.AbstractSTSClient.STSResponse; import org.apache.cxf.ws.security.wss4j.AttachmentCallbackHandler; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.util.XMLUtils; @@ -87,6 +93,76 @@ public SecurityToken requestSecurityToken( } return token; } + + /** + * see WS-Trust 1.4 chapter 8: + * http://docs.oasis-open.org/ws-sx/ws-trust/v1.4/errata01/os/ws-trust-1.4-errata01-os-complete.html#_Toc325658962 + * + * Creating of (manually triggered second) request with a + * RequestSecurityTokenResponse Object + * + * 4451658898 + * + * + * @param action + * @param challengeValue the challenge value that was received by first + * issue-response + * @return SecurityToken + * @throws Exception + */ + public SecurityToken requestSecurityTokenResponse(String action, String challengeValue) throws Exception { + //mostly copied from issue() and requestSecurityToken() methods => needs bigger refactoring + createClient(); + BindingOperationInfo boi = findOperation("/RSTR/Issue"); + + //we need only /RSTR/Issue + client.getRequestContext().putAll(ctx); + if (action != null) { + client.getRequestContext().put(SoapBindingConstants.SOAP_ACTION, action); + // nothing found about this in WS-Trust spec: +// } else if (isSecureConv) { +// client.getRequestContext().put(SoapBindingConstants.SOAP_ACTION, +// namespace + "/RST/SCT"); + } else { + client.getRequestContext().put(SoapBindingConstants.SOAP_ACTION, + namespace + "/RSTR/Issue"); + } + + //deviation from issue: first element must be RequestSecurityTokenResponse + W3CDOMStreamWriter writer = new W3CDOMStreamWriter(); + writer.writeStartElement("wst", "RequestSecurityTokenResponse", namespace); + writer.writeNamespace("wst", namespace); + if (context != null) { + writer.writeAttribute(null, "Context", context); + } + + writer.writeStartElement("wst", "SignChallengeResponse", namespace); + + writer.writeStartElement("wst", "Challenge", namespace); + writer.writeCharacters(challengeValue); + writer.writeEndElement(); + + writer.writeEndElement(); + writer.writeEndElement(); + + Object[] obj = client.invoke(boi, new DOMSource(writer.getDocument().getDocumentElement())); + + @SuppressWarnings("unchecked") + Collection attachments = + (Collection)client.getResponseContext().get(Message.ATTACHMENTS); + STSResponse stsResponse = new STSResponse((DOMSource)obj[0], null, null, null, attachments); + + SecurityToken token = + createSecurityToken(getDocumentElement(stsResponse.getResponse()), stsResponse.getEntropy()); + inlineAttachments(token, stsResponse.getAttachments()); + + if (stsResponse.getCert() != null) { + token.setX509Certificate(stsResponse.getCert(), stsResponse.getCrypto()); + } + return token; + } public SecurityToken renewSecurityToken(SecurityToken tok) throws Exception { STSResponse response = renew(tok);