1/*
2 * Copyright (c) 2001, 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 4458951
27 * @summary Check that Sun's PKIX implementation of
28 *      CertPathValidator.validate() and CertPathBuilder.build() throw an
29 *      InvalidAlgorithmParameterException if any of the TrustAnchors specified
30 *      contain nameConstraints
31 * @modules java.base/sun.security.util
32 */
33import java.io.File;
34import java.io.FileInputStream;
35import java.io.IOException;
36
37import java.security.InvalidAlgorithmParameterException;
38import java.security.cert.CertificateFactory;
39import java.security.cert.CertPath;
40import java.security.cert.CertPathBuilder;
41import java.security.cert.CertPathBuilderResult;
42import java.security.cert.CertPathValidator;
43import java.security.cert.CertPathValidatorResult;
44import java.security.cert.PKIXParameters;
45import java.security.cert.PKIXBuilderParameters;
46import java.security.cert.TrustAnchor;
47import java.security.cert.X509Certificate;
48import java.security.cert.X509CertSelector;
49
50import java.util.ArrayList;
51import java.util.Collections;
52import java.util.List;
53import java.util.Set;
54
55import sun.security.util.DerInputStream;
56
57/**
58 * ValidateNC performs a validation and build of a certification path, using any
59 * name constraints provided in the trust anchor's certificate. Using
60 * Sun's provider, the validation and build should fail because name constraints
61 * on trust anchors are not supported.
62 *
63 * @author      Steve Hanna
64 * @author      Sean Mullan
65 */
66public final class ValidateNC {
67
68    private static CertPath path;
69    private static PKIXParameters params;
70    private static Set anchors;
71
72    public static void main(String[] args) throws Exception {
73
74        String[] certs = { "sun2labs2.cer", "labs2isrg2.cer" };
75
76        createPath(certs);
77        try {
78            validate(path, params);
79            throw new Exception("CertPathValidator should have thrown an " +
80              "InvalidAlgorithmParameterException");
81        } catch (InvalidAlgorithmParameterException iape) {
82            // success!
83        }
84
85        try {
86            X509CertSelector sel = new X509CertSelector();
87            sel.setSubject("cn=sean");
88            PKIXBuilderParameters bparams =
89                new PKIXBuilderParameters(anchors, sel);
90            build(bparams);
91            throw new Exception("CertPathBuilder should have thrown an " +
92              "InvalidAlgorithmParameterException");
93        } catch (InvalidAlgorithmParameterException iape) {
94            // success!
95        }
96    }
97
98    public static void createPath(String[] certs) throws Exception {
99
100        X509Certificate anchorCert = getCertFromFile(certs[0]);
101        byte [] nameConstraints = anchorCert.getExtensionValue("2.5.29.30");
102        if (nameConstraints != null) {
103            DerInputStream in = new DerInputStream(nameConstraints);
104            nameConstraints = in.getOctetString();
105        }
106        TrustAnchor anchor = new TrustAnchor(anchorCert, nameConstraints);
107        List list = new ArrayList();
108        for (int i = 1; i < certs.length; i++) {
109            list.add(0, getCertFromFile(certs[i]));
110        }
111        CertificateFactory cf = CertificateFactory.getInstance("X509");
112        path = cf.generateCertPath(list);
113
114        anchors = Collections.singleton(anchor);
115        params = new PKIXParameters(anchors);
116        params.setRevocationEnabled(false);
117    }
118
119    /**
120     * Get a DER-encoded X.509 certificate from a file.
121     *
122     * @param certFilePath path to file containing DER-encoded certificate
123     * @return X509Certificate
124     * @throws IOException on error
125     */
126    public static X509Certificate getCertFromFile(String certFilePath)
127        throws IOException {
128            X509Certificate cert = null;
129            try {
130                File certFile = new File(System.getProperty("test.src", "."),
131                    certFilePath);
132                FileInputStream certFileInputStream =
133                    new FileInputStream(certFile);
134                CertificateFactory cf = CertificateFactory.getInstance("X509");
135                cert = (X509Certificate)
136                    cf.generateCertificate(certFileInputStream);
137            } catch (Exception e) {
138                e.printStackTrace();
139                throw new IOException("Can't construct X509Certificate: " +
140                                      e.getMessage());
141            }
142            return cert;
143    }
144
145    /**
146     * Perform a PKIX validation.
147     *
148     * @param path CertPath to validate
149     * @param params PKIXParameters to use in validation
150     * @throws Exception on error
151     */
152    public static void validate(CertPath path, PKIXParameters params)
153        throws Exception {
154        CertPathValidator validator =
155            CertPathValidator.getInstance("PKIX", "SUN");
156        CertPathValidatorResult cpvr = validator.validate(path, params);
157    }
158
159    /**
160     * Perform a PKIX build.
161     *
162     * @param params PKIXBuilderParameters to use in the build
163     * @throws Exception on error
164     */
165    public static void build(PKIXBuilderParameters params)
166        throws Exception {
167        CertPathBuilder builder =
168            CertPathBuilder.getInstance("PKIX", "SUN");
169        CertPathBuilderResult cpbr = builder.build(params);
170    }
171}
172