1 /* 2 * Copyright (c) 2003, 2019, 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.jgss.krb5; 27 28 import javax.security.auth.kerberos.KerberosTicket; 29 import javax.security.auth.kerberos.KerberosPrincipal; 30 import javax.security.auth.kerberos.KeyTab; 31 import javax.security.auth.Subject; 32 import javax.security.auth.login.LoginException; 33 import java.security.AccessControlContext; 34 35 import sun.security.action.GetBooleanAction; 36 import sun.security.jgss.GSSUtil; 37 import sun.security.jgss.GSSCaller; 38 39 import sun.security.krb5.Credentials; 40 import sun.security.krb5.EncryptionKey; 41 import sun.security.krb5.KrbException; 42 import java.io.IOException; 43 import sun.security.krb5.KerberosSecrets; 44 import sun.security.krb5.PrincipalName; 45 46 /** 47 * Utilities for obtaining and converting Kerberos tickets. 48 */ 49 public class Krb5Util { 50 51 static final boolean DEBUG = GetBooleanAction 52 .privilegedGetProperty("sun.security.krb5.debug"); 53 54 /** 55 * Default constructor 56 */ Krb5Util()57 private Krb5Util() { // Cannot create one of these 58 } 59 60 /** 61 * Retrieves the ticket corresponding to the client/server principal 62 * pair from the Subject in the specified AccessControlContext. 63 */ getServiceTicket(GSSCaller caller, String clientPrincipal, String serverPrincipal, AccessControlContext acc)64 static KerberosTicket getServiceTicket(GSSCaller caller, 65 String clientPrincipal, String serverPrincipal, 66 AccessControlContext acc) throws LoginException { 67 68 // Try to get ticket from acc's Subject 69 Subject accSubj = Subject.getSubject(acc); 70 KerberosTicket ticket = 71 SubjectComber.find(accSubj, serverPrincipal, clientPrincipal, 72 KerberosTicket.class); 73 74 return ticket; 75 } 76 77 /** 78 * Retrieves the initial TGT corresponding to the client principal 79 * from the Subject in the specified AccessControlContext. 80 * If the ticket can not be found in the Subject, and if 81 * useSubjectCredsOnly is false, then obtain ticket from 82 * a LoginContext. 83 */ getInitialTicket(GSSCaller caller, String clientPrincipal, AccessControlContext acc)84 static KerberosTicket getInitialTicket(GSSCaller caller, 85 String clientPrincipal, 86 AccessControlContext acc) throws LoginException { 87 88 // Try to get ticket from acc's Subject 89 Subject accSubj = Subject.getSubject(acc); 90 KerberosTicket ticket = 91 SubjectComber.find(accSubj, null, clientPrincipal, 92 KerberosTicket.class); 93 94 // Try to get ticket from Subject obtained from GSSUtil 95 if (ticket == null && !GSSUtil.useSubjectCredsOnly(caller)) { 96 Subject subject = GSSUtil.login(caller, GSSUtil.GSS_KRB5_MECH_OID); 97 ticket = SubjectComber.find(subject, 98 null, clientPrincipal, KerberosTicket.class); 99 } 100 return ticket; 101 } 102 103 /** 104 * Retrieves the caller's Subject, or Subject obtained by logging in 105 * via the specified caller. 106 * 107 * Caller must have permission to: 108 * - access the Subject 109 * - create LoginContext 110 * - read the auth.login.defaultCallbackHandler security property 111 * 112 * NOTE: This method is used by JSSE Kerberos Cipher Suites 113 */ getSubject(GSSCaller caller, AccessControlContext acc)114 public static Subject getSubject(GSSCaller caller, 115 AccessControlContext acc) throws LoginException { 116 117 // Try to get the Subject from acc 118 Subject subject = Subject.getSubject(acc); 119 120 // Try to get Subject obtained from GSSUtil 121 if (subject == null && !GSSUtil.useSubjectCredsOnly(caller)) { 122 subject = GSSUtil.login(caller, GSSUtil.GSS_KRB5_MECH_OID); 123 } 124 return subject; 125 } 126 127 /** 128 * Retrieves the ServiceCreds for the specified server principal from 129 * the Subject in the specified AccessControlContext. If not found, and if 130 * useSubjectCredsOnly is false, then obtain from a LoginContext. 131 * 132 * NOTE: This method is also used by JSSE Kerberos Cipher Suites 133 */ getServiceCreds(GSSCaller caller, String serverPrincipal, AccessControlContext acc)134 public static ServiceCreds getServiceCreds(GSSCaller caller, 135 String serverPrincipal, AccessControlContext acc) 136 throws LoginException { 137 138 Subject accSubj = Subject.getSubject(acc); 139 ServiceCreds sc = null; 140 if (accSubj != null) { 141 sc = ServiceCreds.getInstance(accSubj, serverPrincipal); 142 } 143 if (sc == null && !GSSUtil.useSubjectCredsOnly(caller)) { 144 Subject subject = GSSUtil.login(caller, GSSUtil.GSS_KRB5_MECH_OID); 145 sc = ServiceCreds.getInstance(subject, serverPrincipal); 146 } 147 return sc; 148 } 149 credsToTicket(Credentials serviceCreds)150 public static KerberosTicket credsToTicket(Credentials serviceCreds) { 151 EncryptionKey sessionKey = serviceCreds.getSessionKey(); 152 KerberosTicket kt = new KerberosTicket( 153 serviceCreds.getEncoded(), 154 new KerberosPrincipal(serviceCreds.getClient().getName()), 155 new KerberosPrincipal(serviceCreds.getServer().getName(), 156 KerberosPrincipal.KRB_NT_SRV_INST), 157 sessionKey.getBytes(), 158 sessionKey.getEType(), 159 serviceCreds.getFlags(), 160 serviceCreds.getAuthTime(), 161 serviceCreds.getStartTime(), 162 serviceCreds.getEndTime(), 163 serviceCreds.getRenewTill(), 164 serviceCreds.getClientAddresses()); 165 PrincipalName clientAlias = serviceCreds.getClientAlias(); 166 PrincipalName serverAlias = serviceCreds.getServerAlias(); 167 if (clientAlias != null) { 168 KerberosSecrets.getJavaxSecurityAuthKerberosAccess() 169 .kerberosTicketSetClientAlias(kt, new KerberosPrincipal( 170 clientAlias.getName(), clientAlias.getNameType())); 171 } 172 if (serverAlias != null) { 173 KerberosSecrets.getJavaxSecurityAuthKerberosAccess() 174 .kerberosTicketSetServerAlias(kt, new KerberosPrincipal( 175 serverAlias.getName(), serverAlias.getNameType())); 176 } 177 return kt; 178 }; 179 ticketToCreds(KerberosTicket kerbTicket)180 public static Credentials ticketToCreds(KerberosTicket kerbTicket) 181 throws KrbException, IOException { 182 KerberosPrincipal clientAlias = KerberosSecrets 183 .getJavaxSecurityAuthKerberosAccess() 184 .kerberosTicketGetClientAlias(kerbTicket); 185 KerberosPrincipal serverAlias = KerberosSecrets 186 .getJavaxSecurityAuthKerberosAccess() 187 .kerberosTicketGetServerAlias(kerbTicket); 188 return new Credentials( 189 kerbTicket.getEncoded(), 190 kerbTicket.getClient().getName(), 191 (clientAlias != null ? clientAlias.getName() : null), 192 kerbTicket.getServer().getName(), 193 (serverAlias != null ? serverAlias.getName() : null), 194 kerbTicket.getSessionKey().getEncoded(), 195 kerbTicket.getSessionKeyType(), 196 kerbTicket.getFlags(), 197 kerbTicket.getAuthTime(), 198 kerbTicket.getStartTime(), 199 kerbTicket.getEndTime(), 200 kerbTicket.getRenewTill(), 201 kerbTicket.getClientAddresses()); 202 } 203 204 /** 205 * A helper method to get a sun..KeyTab from a javax..KeyTab 206 * @param ktab the javax..KeyTab object 207 * @return the sun..KeyTab object 208 */ 209 public static sun.security.krb5.internal.ktab.KeyTab snapshotFromJavaxKeyTab(KeyTab ktab)210 snapshotFromJavaxKeyTab(KeyTab ktab) { 211 return KerberosSecrets.getJavaxSecurityAuthKerberosAccess() 212 .keyTabTakeSnapshot(ktab); 213 } 214 215 /** 216 * A helper method to get EncryptionKeys from a javax..KeyTab 217 * @param ktab the javax..KeyTab object 218 * @param cname the PrincipalName 219 * @return the EKeys, never null, might be empty 220 */ keysFromJavaxKeyTab( KeyTab ktab, PrincipalName cname)221 public static EncryptionKey[] keysFromJavaxKeyTab( 222 KeyTab ktab, PrincipalName cname) { 223 return snapshotFromJavaxKeyTab(ktab).readServiceKeys(cname); 224 } 225 } 226