View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.wss4j.stax.test.saml;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.InputStream;
24  import java.util.Properties;
25  
26  import javax.xml.stream.XMLStreamException;
27  import javax.xml.stream.XMLStreamReader;
28  import javax.xml.transform.dom.DOMSource;
29  import javax.xml.transform.stream.StreamResult;
30  
31  import org.apache.wss4j.common.saml.builder.SAML1Constants;
32  import org.apache.wss4j.common.saml.builder.SAML2Constants;
33  import org.apache.wss4j.dom.WSConstants;
34  import org.apache.wss4j.dom.handler.WSHandlerConstants;
35  import org.apache.wss4j.stax.ext.WSSConstants;
36  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
37  import org.apache.wss4j.stax.setup.InboundWSSec;
38  import org.apache.wss4j.stax.setup.WSSec;
39  import org.apache.wss4j.stax.test.AbstractTestBase;
40  import org.apache.wss4j.stax.test.utils.StAX2DOM;
41  import org.junit.jupiter.api.Test;
42  import org.w3c.dom.Document;
43  import org.w3c.dom.Element;
44  import org.w3c.dom.NodeList;
45  
46  import static org.junit.jupiter.api.Assertions.assertEquals;
47  import static org.junit.jupiter.api.Assertions.assertNotNull;
48  import static org.junit.jupiter.api.Assertions.fail;
49  
50  public class SAMLTokenNegativeTest extends AbstractTestBase {
51  
52      @Test
53      public void testSAML2AuthnAssertionModifiedInbound() throws Exception {
54  
55          ByteArrayOutputStream baos = new ByteArrayOutputStream();
56          {
57              SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
58              callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
59              callbackHandler.setConfirmationMethod(SAML2Constants.CONF_SENDER_VOUCHES);
60              callbackHandler.setIssuer("www.example.com");
61  
62              InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
63              String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
64              Properties properties = new Properties();
65              properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
66              properties.setProperty(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
67              Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
68  
69              //some test that we can really sure we get what we want from WSS4J
70              NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
71              assertEquals(nodeList.getLength(), 2);
72  
73              NodeList list = securedDocument.getElementsByTagNameNS(WSConstants.SAML2_NS, "Assertion");
74              Element assertionElement = (Element) list.item(0);
75              assertionElement.setAttributeNS(null, "MinorVersion", "5");
76  
77              javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
78              transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
79          }
80  
81          //done signature; now test sig-verification:
82          {
83              WSSSecurityProperties securityProperties = new WSSSecurityProperties();
84              securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("saml/issuer.jks"), "default".toCharArray());
85              InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);WSSec.getInboundWSSec(securityProperties, false, true);
86              XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
87  
88              try {
89                  StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
90                  fail("XMLStreamException expected");
91              } catch (XMLStreamException e) {
92                  assertNotNull(e.getCause());
93                  assertNotNull(e.getCause().getCause());
94              }
95          }
96      }
97  
98      @Test
99      public void testSAML1SignedKeyHolderSigModifiedInbound() throws Exception {
100 
101         ByteArrayOutputStream baos = new ByteArrayOutputStream();
102         {
103             SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
104             callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
105             callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
106             callbackHandler.setIssuer("www.example.com");
107 
108             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
109             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
110             Properties properties = new Properties();
111             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
112             properties.setProperty(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
113             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
114 
115             //some test that we can really sure we get what we want from WSS4J
116             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
117             assertEquals(nodeList.getLength(), 2);
118 
119             Element envelope = securedDocument.getDocumentElement();
120             NodeList list = envelope.getElementsByTagNameNS(WSConstants.SAML_NS, "Assertion");
121             Element assertionElement = (Element) list.item(0);
122             list = assertionElement.getElementsByTagNameNS(WSConstants.SIG_NS, "Signature");
123             Element sigElement = (Element) list.item(0);
124             list = sigElement.getElementsByTagNameNS(WSConstants.SIG_NS, "Transform");
125             Element transformElement = (Element) list.item(0);
126             transformElement.setAttributeNS(null, "Algorithm", WSConstants.C14N_EXCL_OMIT_COMMENTS);
127 
128             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
129             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
130         }
131 
132         //done signature; now test sig-verification:
133         {
134             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
135             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("saml/issuer.jks"), "default".toCharArray());
136             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
137             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
138 
139             try {
140                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
141                 fail("XMLStreamException expected");
142             } catch (XMLStreamException e) {
143                 assertNotNull(e.getCause());
144                 assertNotNull(e.getCause().getCause());
145             }
146         }
147     }
148 
149     @Test
150     public void testSAML2SignedKeyHolderKeyModifiedInbound() throws Exception {
151 
152         ByteArrayOutputStream baos = new ByteArrayOutputStream();
153         {
154             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
155             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
156             callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
157             callbackHandler.setIssuer("www.example.com");
158 
159             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
160             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
161             Properties properties = new Properties();
162             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
163             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
164 
165             //some test that we can really sure we get what we want from WSS4J
166             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
167             assertEquals(nodeList.getLength(), 2);
168 
169             NodeList list = securedDocument.getElementsByTagNameNS(WSConstants.SAML2_NS, "Assertion");
170             Element assertionElement = (Element) list.item(0);
171             assertionElement.setAttributeNS(null, "MinorVersion", "5");
172 
173             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
174             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
175         }
176 
177         //done signature; now test sig-verification:
178         {
179             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
180             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
181             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
182             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
183 
184             try {
185                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
186                 fail("XMLStreamException expected");
187             } catch (XMLStreamException e) {
188                 assertNotNull(e.getCause());
189                 assertNotNull(e.getCause().getCause());
190             }
191         }
192     }
193 
194     @Test
195     public void testHOKNotSignedInbound() throws Exception {
196 
197         ByteArrayOutputStream baos = new ByteArrayOutputStream();
198         {
199             SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
200             callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
201             callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
202             callbackHandler.setIssuer("www.example.com");
203             callbackHandler.setSignAssertion(false);
204 
205             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
206             String action = WSHandlerConstants.SAML_TOKEN_UNSIGNED;
207             Properties properties = new Properties();
208             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
209             //properties.setProperty(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
210             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
211 
212             //some test that we can really sure we get what we want from WSS4J
213             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
214             assertEquals(nodeList.getLength(), 0);
215 
216             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
217             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
218         }
219 
220         //done signature; now test sig-verification:
221         {
222             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
223             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("saml/issuer.jks"), "default".toCharArray());
224             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
225             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
226 
227             try {
228                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
229                 fail("XMLStreamException expected");
230             } catch (XMLStreamException e) {
231                 assertNotNull(e.getCause());
232             }
233         }
234     }
235 
236     @Test
237     public void testSAML2TrustFailureInbound() throws Exception {
238 
239         ByteArrayOutputStream baos = new ByteArrayOutputStream();
240         {
241             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
242             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
243             callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
244             callbackHandler.setIssuer("www.example.com");
245 
246             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
247             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
248             Properties properties = new Properties();
249             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
250             properties.setProperty(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
251             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
252 
253             //some test that we can really sure we get what we want from WSS4J
254             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
255             assertEquals(nodeList.getLength(), 2);
256 
257             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
258             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
259         }
260 
261         //done signature; now test sig-verification:
262         {
263             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
264             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
265             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
266             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
267 
268             try {
269                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
270                 fail("XMLStreamException expected");
271             } catch (XMLStreamException e) {
272                 assertNotNull(e.getCause());
273             }
274         }
275     }
276 }