1 /* 2 * Copyright (c) 2019, Red Hat, Inc. 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 8215032 27 * @library /test/lib 28 * @run main/othervm/timeout=120 -Dsun.security.krb5.debug=true ReferralsTest 29 * @summary Test Kerberos cross-realm referrals (RFC 6806) 30 */ 31 32 import java.io.File; 33 import sun.security.krb5.Credentials; 34 import sun.security.krb5.internal.CredentialsUtil; 35 import sun.security.krb5.KrbAsReqBuilder; 36 import sun.security.krb5.PrincipalName; 37 38 public class ReferralsTest { 39 private static final boolean DEBUG = true; 40 private static final String krbConfigName = "krb5-localkdc.conf"; 41 private static final String realmKDC1 = "RABBIT.HOLE"; 42 private static final String realmKDC2 = "DEV.RABBIT.HOLE"; 43 private static final char[] password = "123qwe@Z".toCharArray(); 44 private static final String clientName = "test"; 45 46 private static final String clientAlias = clientName + 47 PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1; 48 49 private static final String clientKDC1QueryName = clientAlias.replaceAll( 50 PrincipalName.NAME_REALM_SEPARATOR_STR, "\\\\" + 51 PrincipalName.NAME_REALM_SEPARATOR_STR) + 52 PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1; 53 private static PrincipalName clientKDC1QueryPrincipal = null; 54 static { 55 try { 56 clientKDC1QueryPrincipal = new PrincipalName( 57 clientKDC1QueryName, PrincipalName.KRB_NT_ENTERPRISE, 58 null); 59 } catch (Throwable t) {} 60 } 61 62 private static final String clientKDC2Name = clientName + 63 PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC2; 64 65 private static final String serviceName = "http" + 66 PrincipalName.NAME_COMPONENT_SEPARATOR_STR + 67 "server.dev.rabbit.hole"; 68 69 private static Credentials tgt; 70 private static Credentials tgs; 71 72 public static void main(String[] args) throws Exception { 73 try { 74 initializeKDCs(); 75 getTGT(); 76 getTGS(); 77 } finally { 78 cleanup(); 79 } 80 } 81 82 private static void initializeKDCs() throws Exception { 83 KDC kdc1 = KDC.create(realmKDC1, "localhost", 0, true); 84 kdc1.addPrincipalRandKey(PrincipalName.TGS_DEFAULT_SRV_NAME + 85 PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC1); 86 kdc1.addPrincipal(PrincipalName.TGS_DEFAULT_SRV_NAME + 87 PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC1 + 88 PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC2, 89 password); 90 kdc1.addPrincipal(PrincipalName.TGS_DEFAULT_SRV_NAME + 91 PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC2, 92 password); 93 94 KDC kdc2 = KDC.create(realmKDC2, "localhost", 0, true); 95 kdc2.addPrincipalRandKey(PrincipalName.TGS_DEFAULT_SRV_NAME + 96 PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC2); 97 kdc2.addPrincipal(clientKDC2Name, password); 98 kdc2.addPrincipal(serviceName, password); 99 kdc2.addPrincipal(PrincipalName.TGS_DEFAULT_SRV_NAME + 100 PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC1, 101 password); 102 kdc2.addPrincipal(PrincipalName.TGS_DEFAULT_SRV_NAME + 103 PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC2 + 104 PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1, 105 password); 106 107 kdc1.registerAlias(clientAlias, kdc2); 108 kdc1.registerAlias(serviceName, kdc2); 109 kdc2.registerAlias(clientAlias, clientKDC2Name); 110 111 KDC.saveConfig(krbConfigName, kdc1, kdc2, 112 "forwardable=true"); 113 System.setProperty("java.security.krb5.conf", krbConfigName); 114 } 115 116 private static void cleanup() { 117 File f = new File(krbConfigName); 118 if (f.exists()) { 119 f.delete(); 120 } 121 } 122 123 private static void getTGT() throws Exception { 124 KrbAsReqBuilder builder = new KrbAsReqBuilder(clientKDC1QueryPrincipal, 125 password); 126 tgt = builder.action().getCreds(); 127 builder.destroy(); 128 if (DEBUG) { 129 System.out.println("TGT"); 130 System.out.println("----------------------"); 131 System.out.println(tgt); 132 System.out.println("----------------------"); 133 } 134 if (tgt == null) { 135 throw new Exception("TGT is null"); 136 } 137 if (!tgt.getClient().getName().equals(clientKDC2Name)) { 138 throw new Exception("Unexpected TGT client"); 139 } 140 String[] tgtServerNames = tgt.getServer().getNameStrings(); 141 if (tgtServerNames.length != 2 || !tgtServerNames[0].equals( 142 PrincipalName.TGS_DEFAULT_SRV_NAME) || 143 !tgtServerNames[1].equals(realmKDC2) || 144 !tgt.getServer().getRealmString().equals(realmKDC2)) { 145 throw new Exception("Unexpected TGT server"); 146 } 147 } 148 149 private static void getTGS() throws Exception { 150 tgs = CredentialsUtil.acquireServiceCreds(serviceName + 151 PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1, tgt); 152 if (DEBUG) { 153 System.out.println("TGS"); 154 System.out.println("----------------------"); 155 System.out.println(tgs); 156 System.out.println("----------------------"); 157 } 158 if (tgs == null) { 159 throw new Exception("TGS is null"); 160 } 161 if (!tgs.getClient().getName().equals(clientKDC2Name)) { 162 throw new Exception("Unexpected TGS client"); 163 } 164 if (!tgs.getServer().getNameString().equals(serviceName) || 165 !tgs.getServer().getRealmString().equals(realmKDC2)) { 166 throw new Exception("Unexpected TGS server"); 167 } 168 } 169 }