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  
20  package org.apache.wss4j.dom.message;
21  
22  import java.security.cert.X509Certificate;
23  import java.util.Collections;
24  import java.util.List;
25  
26  import org.apache.wss4j.common.WSEncryptionPart;
27  import org.apache.wss4j.common.crypto.Crypto;
28  import org.apache.wss4j.common.crypto.CryptoFactory;
29  import org.apache.wss4j.common.crypto.CryptoType;
30  import org.apache.wss4j.common.token.X509Security;
31  import org.apache.wss4j.common.util.SOAPUtil;
32  import org.apache.wss4j.common.util.XMLUtils;
33  import org.apache.wss4j.dom.WSConstants;
34  import org.apache.wss4j.dom.common.CustomHandler;
35  
36  import org.apache.wss4j.dom.engine.WSSConfig;
37  import org.apache.wss4j.dom.engine.WSSecurityEngine;
38  import org.apache.wss4j.dom.handler.HandlerAction;
39  import org.apache.wss4j.dom.handler.RequestData;
40  import org.apache.wss4j.dom.handler.WSHandlerConstants;
41  import org.apache.wss4j.dom.handler.WSHandlerResult;
42  import org.apache.wss4j.dom.util.WSSecurityUtil;
43  
44  import org.junit.jupiter.api.Test;
45  import org.w3c.dom.Document;
46  
47  import static org.junit.jupiter.api.Assertions.assertNotNull;
48  import static org.junit.jupiter.api.Assertions.assertTrue;
49  
50  /**
51   * This is a test for signing the SOAP Body as well as the BinarySecurityToken that contains the certificate
52   * used to verify the signature.
53   */
54  public class SignedBSTTest {
55      private static final org.slf4j.Logger LOG =
56          org.slf4j.LoggerFactory.getLogger(SignedBSTTest.class);
57      private WSSecurityEngine secEngine = new WSSecurityEngine();
58      private Crypto crypto;
59  
60      public SignedBSTTest() throws Exception {
61          WSSConfig.init();
62          crypto = CryptoFactory.getInstance("wss40.properties");
63      }
64  
65      /**
66       */
67      @Test
68      public void testSignedBST() throws Exception {
69          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
70          WSSecHeader secHeader = new WSSecHeader(doc);
71          secHeader.insertSecurityHeader();
72  
73          // Get a certificate, convert it into a BinarySecurityToken and add it to the security header
74          CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
75          cryptoType.setAlias("wss40");
76          X509Certificate[] certs = crypto.getX509Certificates(cryptoType);
77          assertNotNull(certs);
78  
79          X509Security bst = new X509Security(doc);
80          String certUri = WSSConfig.getNewInstance().getIdAllocator().createSecureId("X509-", certs[0]);
81          bst.setX509Certificate(certs[0]);
82          bst.setID(certUri);
83          WSSecurityUtil.prependChildElement(secHeader.getSecurityHeaderElement(), bst.getElement());
84  
85          // Add the signature
86          WSSecSignature sign = new WSSecSignature(secHeader);
87          sign.setUserInfo("wss40", "security");
88          sign.setSignatureAlgorithm(WSConstants.RSA);
89          sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
90          sign.setX509Certificate(certs[0]);
91  
92          // Add SOAP Body
93          String soapNamespace = WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement());
94          WSEncryptionPart encP =
95              new WSEncryptionPart(
96                  WSConstants.ELEM_BODY, soapNamespace, "Content"
97              );
98          sign.getParts().add(encP);
99          // Add BST
100         encP =
101             new WSEncryptionPart(
102                 WSConstants.BINARY_TOKEN_LN, WSConstants.WSSE_NS, "Element"
103             );
104         encP.setElement(bst.getElement());
105         sign.getParts().add(encP);
106 
107         sign.setCustomTokenId(bst.getID());
108         sign.setCustomTokenValueType(bst.getValueType());
109         sign.prepare(crypto);
110 
111         List<javax.xml.crypto.dsig.Reference> referenceList =
112             sign.addReferencesToSign(sign.getParts());
113         sign.computeSignature(referenceList, false, null);
114 
115         if (LOG.isDebugEnabled()) {
116             String outputString =
117                 XMLUtils.prettyDocumentToString(doc);
118             LOG.debug(outputString);
119         }
120 
121         verify(doc);
122     }
123 
124     @Test
125     public void testSignedBSTAction() throws Exception {
126         final WSSConfig cfg = WSSConfig.getNewInstance();
127         final RequestData reqData = new RequestData();
128         reqData.setWssConfig(cfg);
129         reqData.setUsername("wss40");
130 
131         java.util.Map<String, Object> config = new java.util.TreeMap<>();
132         config.put(WSHandlerConstants.SIG_PROP_FILE, "wss40.properties");
133         config.put("password", "security");
134         config.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
135         config.put(
136             WSHandlerConstants.SIGNATURE_PARTS,
137             "{}{" + WSConstants.WSSE_NS + "}BinarySecurityToken"
138         );
139         reqData.setMsgContext(config);
140 
141         final Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
142         CustomHandler handler = new CustomHandler();
143         HandlerAction action = new HandlerAction(WSConstants.SIGN);
144         handler.send(
145             doc,
146             reqData,
147             Collections.singletonList(action),
148             true
149         );
150         String outputString =
151             XMLUtils.prettyDocumentToString(doc);
152         if (LOG.isDebugEnabled()) {
153             LOG.debug("Signed message:");
154             LOG.debug(outputString);
155         }
156 
157         WSHandlerResult results = verify(doc);
158         assertTrue(handler.checkResults(results.getResults(),
159                                         Collections.singletonList(WSConstants.SIGN)));
160     }
161 
162     /**
163      * Verifies the soap envelope
164      * <p/>
165      *
166      * @param doc
167      * @throws Exception Thrown when there is a problem in verification
168      */
169     private WSHandlerResult verify(Document doc) throws Exception {
170         WSHandlerResult results =
171             secEngine.processSecurityHeader(doc, null, null, crypto);
172         if (LOG.isDebugEnabled()) {
173             LOG.debug("Verfied and decrypted message:");
174             String outputString =
175                 XMLUtils.prettyDocumentToString(doc);
176             LOG.debug(outputString);
177         }
178         return results;
179     }
180 
181 }