1 /*
2  * Copyright (c) 2017, 2018, 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 8029994 8177085 8177398
27  * @summary Support "include" and "includedir" in krb5.conf
28  * @modules java.security.jgss/sun.security.krb5
29  * @compile -XDignore.symbol.file Include.java
30  * @run main/othervm Include
31  */
32 import sun.security.krb5.Config;
33 import sun.security.krb5.KrbException;
34 
35 import java.nio.file.Files;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38 import java.util.Arrays;
39 
40 public class Include {
main(String[] args)41     public static void main(String[] args) throws Exception {
42 
43         String krb5Conf = "[section]\nkey=";        // Skeleton of a section
44 
45         Path conf = Paths.get("krb5.conf");         // base krb5.conf
46 
47         Path f = Paths.get("f");            // include
48         Path f2 = Paths.get("f2");          // f include f2
49         Path d = Paths.get("d");            // includedir
50         Path dd = Paths.get("d/dd");        // sub dir, ignore
51         Path ddf = Paths.get("d/dd/ddf");   // file in sub dir, ignore
52         Path df1 = Paths.get("d/f1");       // one file in dir
53         Path df2 = Paths.get("d/f2");       // another file
54         Path df3 = Paths.get("d/f.3");      // third file bad name
55         Path df4 = Paths.get("d/f4.conf");  // fourth file
56         Path df5 = Paths.get("d/.f5.conf"); // fifth file is dotfile
57 
58         // OK: The base file can be missing
59         System.setProperty("java.security.krb5.conf", "no-such-file");
60         tryReload(true);
61 
62         System.setProperty("java.security.krb5.conf", conf.toString());
63 
64         // Write base file
65         Files.write(conf,
66                 ("include " + f.toAbsolutePath() + "\n" +
67                         "includedir " + d.toAbsolutePath() + "\n" +
68                         krb5Conf + "base").getBytes()
69         );
70 
71         // Error: Neither include nor includedir exists
72         tryReload(false);
73 
74         // Error: Only includedir exists
75         Files.createDirectory(d);
76         tryReload(false);
77 
78         // Error: Both exists, but include is a cycle
79         Files.write(f,
80                 ("include " + conf.toAbsolutePath() + "\n" +
81                     krb5Conf + "f").getBytes());
82         tryReload(false);
83 
84         // Error: A good include exists, but no includedir yet
85         Files.delete(d);
86         Files.write(f, (krb5Conf + "f").getBytes());
87         tryReload(false);
88 
89         // OK: Everything is set
90         Files.createDirectory(d);
91         tryReload(true);   // Now OK
92 
93         // make f include f2
94         Files.write(f,
95                 ("include " + f2.toAbsolutePath() + "\n" +
96                         krb5Conf + "f").getBytes());
97         Files.write(f2, (krb5Conf + "f2").getBytes());
98         // fx1 and fx2 will be loaded
99         Files.write(df1, (krb5Conf + "df1").getBytes());
100         Files.write(df2, (krb5Conf + "df2").getBytes());
101         // fx3 and fxs (and file inside it) will be ignored
102         Files.write(df3, (krb5Conf + "df3").getBytes());
103         Files.createDirectory(dd);
104         Files.write(ddf, (krb5Conf + "ddf").getBytes());
105         // fx4 will be loaded
106         Files.write(df4, (krb5Conf + "df4").getBytes());
107         // fx5 will be excluded
108         Files.write(df5, (krb5Conf + "df5").getBytes());
109 
110         // OK: All good files read
111         tryReload(true);
112 
113         String[] v = Config.getInstance().getAll("section", "key") .split(" ");
114         // v will contain f2, f, df[124], and base.
115         // Order of df[124] is not determined. Sort them first.
116         Arrays.sort(v, 2, 5);
117         String longv = Arrays.toString(v);
118         if (!longv.equals("[f2, f, df1, df2, df4, base]")) {
119             throw new Exception(longv);
120         }
121 
122         // Error: include file not absolute
123         Files.write(conf,
124                 ("include " + f + "\n" +
125                         "includedir " + d.toAbsolutePath() + "\n" +
126                         krb5Conf + "base").getBytes()
127         );
128         tryReload(false);
129 
130         // Error: includedir not absolute
131         Files.write(conf,
132                 ("include " + f.toAbsolutePath() + "\n" +
133                         "includedir " + d + "\n" +
134                         krb5Conf + "base").getBytes()
135         );
136         tryReload(false);
137 
138         // OK: unsupported directive
139         Files.write(conf,
140                 ("module /lib/lib.so\n" +
141                         krb5Conf + "base").getBytes()
142         );
143         tryReload(true);
144     }
145 
tryReload(boolean expected)146     private static void tryReload(boolean expected) throws Exception {
147         if (expected) {
148             Config.refresh();
149         } else {
150             try {
151                 Config.refresh();
152                 throw new Exception("Should be illegal");
153             } catch (KrbException ke) {
154                 // OK
155             }
156         }
157     }
158 }
159