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  
24  import org.apache.wss4j.common.util.SOAPUtil;
25  import org.apache.wss4j.dom.WSConstants;
26  
27  import org.apache.wss4j.dom.engine.WSSConfig;
28  import org.apache.wss4j.dom.engine.WSSecurityEngine;
29  import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
30  import org.apache.wss4j.common.crypto.Crypto;
31  import org.apache.wss4j.common.crypto.CryptoFactory;
32  import org.apache.wss4j.common.ext.WSSecurityException;
33  import org.apache.wss4j.common.util.XMLUtils;
34  import org.apache.wss4j.dom.handler.RequestData;
35  import org.apache.wss4j.dom.handler.WSHandlerResult;
36  import org.apache.wss4j.dom.util.WSSecurityUtil;
37  
38  import org.junit.jupiter.api.Test;
39  import org.w3c.dom.Document;
40  import org.w3c.dom.Element;
41  
42  import static org.junit.jupiter.api.Assertions.assertNotNull;
43  import static org.junit.jupiter.api.Assertions.assertTrue;
44  import static org.junit.jupiter.api.Assertions.fail;
45  
46  /**
47   * This is a test for Certificate Revocation List checking. A message is signed and sent to the
48   * receiver. If Certificate Revocation is enabled, then signature trust verification should
49   * fail as the message has been signed by the private key corresponding to a revoked signature.
50   *
51   * Generate the client keypair, make a csr, sign it with the CA key
52   *
53   * keytool -genkey -validity 3650 -alias wss40rev -keyalg RSA -keystore wss40rev.jks
54   * -dname "CN=Colm,OU=WSS4J,O=Apache,L=Dublin,ST=Leinster,C=IE"
55   * keytool -certreq -alias wss40rev -keystore wss40rev.jks -file wss40rev.cer
56   * openssl ca -config ca.config -policy policy_anything -days 3650 -out wss40rev.pem -infiles wss40rev.cer
57   * openssl x509 -outform DER -in wss40rev.pem -out wss40rev.crt
58   *
59   * Import the CA cert into wss40.jks and import the new signed certificate
60   *
61   * keytool -import -file wss40CA.crt -alias wss40CA -keystore wss40rev.jks
62   * keytool -import -file wss40rev.crt -alias wss40rev -keystore wss40rev.jks
63   *
64   * Generate a Revocation list
65   *
66   * openssl ca -gencrl -keyfile wss40CAKey.pem -cert wss40CA.pem -out wss40CACRL.pem
67   * -config ca.config -crldays 3650
68   * openssl ca -revoke wss40rev.pem -keyfile wss40CAKey.pem -cert wss40CA.pem -config ca.config
69   * openssl ca -gencrl -keyfile wss40CAKey.pem -cert wss40CA.pem -out wss40CACRL.pem
70   * -config ca.config -crldays 3650
71   */
72  public class SignatureCRLTest {
73      private static final org.slf4j.Logger LOG =
74          org.slf4j.LoggerFactory.getLogger(SignatureCRLTest.class);
75      private Crypto crypto;
76      private Crypto cryptoCA;
77  
78      public SignatureCRLTest() throws Exception {
79          WSSConfig.init();
80          crypto = CryptoFactory.getInstance("wss40rev.properties");
81          cryptoCA = CryptoFactory.getInstance("wss40CA.properties");
82      }
83  
84      /**
85       * Test signing a SOAP message using a BST. Revocation is not enabled and so the test
86       * should pass.
87       * TODO Re-enable once CRL issue fixed
88       */
89      @Test
90      @org.junit.jupiter.api.Disabled
91      public void testSignatureDirectReference() throws Exception {
92          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
93          WSSecHeader secHeader = new WSSecHeader(doc);
94          secHeader.insertSecurityHeader();
95  
96          WSSecSignature sign = new WSSecSignature(secHeader);
97          sign.setUserInfo("wss40rev", "security");
98          sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
99  
100         Document signedDoc = sign.build(crypto);
101 
102         if (LOG.isDebugEnabled()) {
103             String outputString =
104                 XMLUtils.prettyDocumentToString(signedDoc);
105             LOG.debug(outputString);
106         }
107         //
108         // Verify the signature
109         //
110         WSHandlerResult results = verify(signedDoc, cryptoCA, false);
111         WSSecurityEngineResult result =
112             results.getActionResults().get(WSConstants.SIGN).get(0);
113         X509Certificate cert =
114             (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
115         assertNotNull(cert);
116     }
117 
118     /**
119      * Test signing a SOAP message using a BST. Revocation is enabled and so the test
120      * should fail.
121      * TODO Re-enable once CRL issue fixed
122      */
123     @Test
124     @org.junit.jupiter.api.Disabled
125     public void testSignatureDirectReferenceRevocation() throws Exception {
126         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
127         WSSecHeader secHeader = new WSSecHeader(doc);
128         secHeader.insertSecurityHeader();
129 
130         WSSecSignature sign = new WSSecSignature(secHeader);
131         sign.setUserInfo("wss40rev", "security");
132         sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
133 
134         Document signedDoc = sign.build(crypto);
135 
136         if (LOG.isDebugEnabled()) {
137             String outputString =
138                 XMLUtils.prettyDocumentToString(signedDoc);
139             LOG.debug(outputString);
140         }
141         //
142         // Verify the signature
143         //
144         try {
145             verify(signedDoc, cryptoCA, true);
146             fail ("Failure expected on a revoked certificate");
147         } catch (WSSecurityException ex) {
148             assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
149         }
150     }
151 
152 
153     /**
154      * Test signing a SOAP message using a BST. Revocation is enabled and so the test
155      * should fail. The trust store that is used is the keystore that contains the revoked
156      * certificate. See WSS-341:
157      * https://issues.apache.org/jira/browse/WSS-341
158      *
159      * TODO Re-enable once CRL issue fixed
160      */
161     @Test
162     @org.junit.jupiter.api.Disabled
163     public void testSignatureDirectReferenceRevocationKeyStore() throws Exception {
164         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
165         WSSecHeader secHeader = new WSSecHeader(doc);
166         secHeader.insertSecurityHeader();
167 
168         WSSecSignature sign = new WSSecSignature(secHeader);
169         sign.setUserInfo("wss40rev", "security");
170         sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
171 
172         Document signedDoc = sign.build(crypto);
173 
174         if (LOG.isDebugEnabled()) {
175             String outputString =
176                 XMLUtils.prettyDocumentToString(signedDoc);
177             LOG.debug(outputString);
178         }
179         //
180         // Verify the signature
181         //
182         try {
183             verify(signedDoc, crypto, true);
184             fail ("Failure expected on a revoked certificate");
185         } catch (WSSecurityException ex) {
186             assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
187         }
188     }
189 
190     /**
191      * Verifies the soap envelope
192      * <p/>
193      *
194      * @param doc
195      * @throws Exception Thrown when there is a problem in verification
196      */
197     private WSHandlerResult verify(Document doc, Crypto crypto, boolean revocationEnabled) throws Exception {
198         WSSecurityEngine secEngine = new WSSecurityEngine();
199         RequestData reqData = new RequestData();
200         reqData.setSigVerCrypto(crypto);
201         reqData.setEnableRevocation(revocationEnabled);
202         Element securityHeader = WSSecurityUtil.getSecurityHeader(doc, null);
203         WSHandlerResult results =
204             secEngine.processSecurityHeader(securityHeader, reqData);
205         if (LOG.isDebugEnabled()) {
206             LOG.debug("Verfied and decrypted message:");
207             String outputString =
208                 XMLUtils.prettyDocumentToString(doc);
209             LOG.debug(outputString);
210         }
211         return results;
212     }
213 
214 
215 }