ValidationTests.java revision 12016:5ad36a27ddf3
1/*
2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug 4635230 6365103 6366054 6824440 7131084 8046724 8079693
27 * @summary Basic unit tests for validating XML Signatures with JSR 105
28 * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java
29 *     X509KeySelector.java ValidationTests.java
30 * @run main/othervm ValidationTests
31 * @author Sean Mullan
32 */
33import java.io.File;
34import java.io.FileInputStream;
35import java.security.*;
36import javax.xml.crypto.Data;
37import javax.xml.crypto.KeySelector;
38import javax.xml.crypto.MarshalException;
39import javax.xml.crypto.OctetStreamData;
40import javax.xml.crypto.URIDereferencer;
41import javax.xml.crypto.URIReference;
42import javax.xml.crypto.URIReferenceException;
43import javax.xml.crypto.XMLCryptoContext;
44import javax.xml.crypto.dsig.XMLSignatureException;
45import javax.xml.crypto.dsig.XMLSignatureFactory;
46
47public class ValidationTests {
48
49    private static SignatureValidator validator;
50    private final static String DIR = System.getProperty("test.src", ".");
51    private final static String DATA_DIR =
52        DIR + System.getProperty("file.separator") + "data";
53    private final static String KEYSTORE =
54        DATA_DIR + System.getProperty("file.separator") + "certs" +
55        System.getProperty("file.separator") + "xmldsig.jks";
56    private final static String STYLESHEET =
57        "http://www.w3.org/TR/xml-stylesheet";
58    private final static String STYLESHEET_B64 =
59        "http://www.w3.org/Signature/2002/04/xml-stylesheet.b64";
60
61    static class Test {
62        String file;
63        KeySelector ks;
64        Class exception;
65
66        Test(String file, KeySelector ks, Class exception) {
67            this.file = file;
68            this.ks = ks;
69            this.exception = exception;
70        }
71
72        // XMLSignatureException is expected by default
73        Test(String file, KeySelector ks) {
74            this(file, ks, XMLSignatureException.class);
75        }
76    }
77
78    static KeySelector skks;
79    static {
80        try {
81            skks =
82                new KeySelectors.SecretKeySelector("secret".getBytes("ASCII"));
83        } catch (Exception e) {
84            //should not occur
85        }
86    }
87    private final static KeySelector SKKS = skks;
88    private final static KeySelector KVKS =
89        new KeySelectors.KeyValueKeySelector();
90    private final static KeySelector CKS =
91        new KeySelectors.CollectionKeySelector(new File(DATA_DIR));
92    private final static KeySelector RXKS =
93        new KeySelectors.RawX509KeySelector();
94    private final static KeySelector XKS = null;
95    private static URIDereferencer httpUd = null;
96
97    private final static Test[] VALID_TESTS = {
98        new Test("signature-enveloped-dsa.xml", KVKS),
99        new Test("signature-enveloping-b64-dsa.xml", KVKS),
100        new Test("signature-enveloping-dsa.xml", KVKS),
101        new Test("signature-enveloping-rsa.xml", KVKS),
102        new Test("signature-enveloping-p256-sha1.xml", KVKS),
103        new Test("signature-enveloping-p384-sha1.xml", KVKS),
104        new Test("signature-enveloping-p521-sha1.xml", KVKS),
105        new Test("signature-enveloping-hmac-sha1.xml", SKKS),
106        new Test("signature-external-dsa.xml", KVKS),
107        new Test("signature-external-b64-dsa.xml", KVKS),
108        new Test("signature-retrievalmethod-rawx509crt.xml", CKS),
109        new Test("signature-keyname.xml", CKS),
110        new Test("signature-x509-crt-crl.xml", RXKS),
111        new Test("signature-x509-crt.xml", RXKS),
112        new Test("signature-x509-is.xml", CKS),
113        new Test("signature-x509-ski.xml", CKS),
114        new Test("signature-x509-sn.xml", CKS),
115        new Test("signature.xml", XKS),
116        new Test("exc-signature.xml", KVKS),
117        new Test("sign-spec.xml", RXKS),
118        new Test("xmldsig-xfilter2.xml", KVKS)
119    };
120
121    private final static Test[] INVALID_TESTS = {
122        new Test("signature-enveloping-hmac-sha1-40.xml", SKKS),
123        new Test("signature-enveloping-hmac-sha1-trunclen-0-attack.xml", SKKS),
124        new Test("signature-enveloping-hmac-sha1-trunclen-8-attack.xml", SKKS),
125        new Test("signature-extra-text-in-signed-info.xml", SKKS,
126                MarshalException.class),
127        new Test("signature-wrong-canonicalization-method-algorithm.xml", SKKS,
128                MarshalException.class),
129        new Test("signature-wrong-transform-algorithm.xml", SKKS,
130                MarshalException.class),
131        new Test("signature-no-reference-uri.xml", SKKS),
132        new Test("signature-wrong-signature-method-algorithm.xml", SKKS,
133                MarshalException.class),
134        new Test("signature-wrong-tag-names.xml", SKKS, MarshalException.class)
135    };
136
137    public static void main(String args[]) throws Exception {
138        httpUd = new HttpURIDereferencer();
139
140        validator = new SignatureValidator(new File(DATA_DIR));
141
142        boolean atLeastOneFailed = false;
143        for (Test test : VALID_TESTS) {
144            System.out.println("Validating " + test.file);
145            if (test_signature(test)) {
146                System.out.println("PASSED");
147            } else {
148                System.out.println("FAILED");
149                atLeastOneFailed = true;
150            }
151        }
152        // test with reference caching enabled
153        System.out.println("Validating sign-spec.xml with caching enabled");
154        if (test_signature(new Test("sign-spec.xml", RXKS), true)) {
155            System.out.println("PASSED");
156        } else {
157            System.out.println("FAILED");
158            atLeastOneFailed = true;
159        }
160
161        for (Test test : INVALID_TESTS) {
162            System.out.println("Validating " + test.file);
163            try {
164                test_signature(test);
165                System.out.println("FAILED");
166                atLeastOneFailed = true;
167            } catch (Exception e) {
168                System.out.println("Exception: " + e);
169                if (e.getClass() != test.exception) {
170                    System.out.println("FAILED: unexpected exception");
171                    atLeastOneFailed = true;
172                } else {
173                    System.out.println("PASSED");
174                }
175            }
176        }
177
178        if (atLeastOneFailed) {
179            throw new Exception
180                ("At least one signature did not validate as expected");
181        }
182    }
183
184    public static boolean test_signature(Test test) throws Exception {
185        return test_signature(test, false);
186    }
187
188    public static boolean test_signature(Test test, boolean cache)
189        throws Exception
190    {
191        if (test.ks == null) {
192            KeyStore keystore = KeyStore.getInstance("JKS");
193            try (FileInputStream fis = new FileInputStream(KEYSTORE)) {
194                keystore.load(fis, "changeit".toCharArray());
195                test.ks = new X509KeySelector(keystore, false);
196            }
197        }
198        return validator.validate(test.file, test.ks, httpUd, cache);
199    }
200
201    /**
202     * This URIDereferencer returns locally cached copies of http content to
203     * avoid test failures due to network glitches, etc.
204     */
205    private static class HttpURIDereferencer implements URIDereferencer {
206        private URIDereferencer defaultUd;
207
208        HttpURIDereferencer() {
209            defaultUd = XMLSignatureFactory.getInstance().getURIDereferencer();
210        }
211
212        public Data dereference(final URIReference ref, XMLCryptoContext ctx)
213        throws URIReferenceException {
214            String uri = ref.getURI();
215            if (uri.equals(STYLESHEET) || uri.equals(STYLESHEET_B64)) {
216                try {
217                    FileInputStream fis = new FileInputStream(new File
218                        (DATA_DIR, uri.substring(uri.lastIndexOf('/'))));
219                    return new OctetStreamData(fis,ref.getURI(),ref.getType());
220                } catch (Exception e) { throw new URIReferenceException(e); }
221            }
222
223            // fallback on builtin deref
224            return defaultUd.dereference(ref, ctx);
225        }
226    }
227}
228