1 /* 2 * Copyright (c) 2011, 2021, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.krb5; 27 28 import java.io.IOException; 29 import java.util.Hashtable; 30 import java.util.Iterator; 31 import java.util.List; 32 import java.util.Vector; 33 34 35 public class SCDynamicStoreConfig { 36 private static native void installNotificationCallback(); 37 38 /** 39 * Returns the dynamic store setting for kerberos in a string array. 40 * (realm kdc* null) null (mapping-domain mapping-realm)* 41 */ 42 private static native List<String> getKerberosConfig(); 43 private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG; 44 45 static { 46 boolean isMac = java.security.AccessController.doPrivileged( 47 new java.security.PrivilegedAction<Boolean>() { 48 public Boolean run() { 49 String osname = System.getProperty("os.name"); 50 if (osname.contains("OS X")) { 51 System.loadLibrary("osxkrb5"); 52 return true; 53 } 54 return false; 55 } 56 }); 57 if (isMac) installNotificationCallback(); 58 } 59 60 /** 61 * Calls down to JNI to get the raw Kerberos Config and maps the object 62 * graph to the one that Kerberos Config in Java expects 63 * 64 * @return 65 * @throws IOException 66 */ 67 public static Hashtable<String, Object> getConfig() throws IOException { 68 List<String> list = getKerberosConfig(); 69 if (list == null) { 70 throw new IOException( 71 "Could not load configuration from SCDynamicStore"); 72 } 73 if (DEBUG) System.out.println("Raw map from JNI: " + list); 74 75 Hashtable<String,Object> v = new Hashtable<>(); 76 Hashtable<String,Object> realms = new Hashtable<>(); 77 Iterator<String> iterator = list.iterator(); 78 String defaultRealm = null; 79 80 while (true) { 81 String nextRealm = iterator.next(); 82 if (nextRealm == null) { 83 break; 84 } 85 if (defaultRealm == null) { 86 defaultRealm = nextRealm; 87 Hashtable<String,Object> dr = new Hashtable<>(); 88 dr.put("default_realm", v1(defaultRealm)); 89 v.put("libdefaults", dr); 90 } 91 Vector<String> kdcs = new Vector<>(); 92 while (true) { 93 String nextKdc = iterator.next(); 94 if (nextKdc == null) { 95 break; 96 } 97 kdcs.add(nextKdc); 98 } 99 if (!kdcs.isEmpty()) { 100 Hashtable<String,Object> ri = new Hashtable<>(); 101 ri.put("kdc", kdcs); 102 realms.put(nextRealm, ri); 103 } 104 } 105 if (!realms.isEmpty()) { 106 v.put("realms", realms); 107 } 108 Hashtable<String,Object> mapping = new Hashtable<>(); 109 while (true) { 110 if (!iterator.hasNext()) { 111 break; 112 } 113 mapping.put(iterator.next(), v1(iterator.next())); 114 } 115 if (!mapping.isEmpty()) { 116 v.put("domain_realm", mapping); 117 } 118 return v; 119 } 120 121 // Make a single value Vector. Config's stanzaTable always 122 // use Vector as end values. 123 private static Vector<String> v1(String s) { 124 Vector<String> out = new Vector<>(); 125 out.add(s); 126 return out; 127 } 128 }