diff --git a/jdk/src/java.base/share/classes/javax/security/auth/AuthPermission.java b/jdk/src/java.base/share/classes/javax/security/auth/AuthPermission.java index 889d14af979..6cbff526932 100644 --- a/jdk/src/java.base/share/classes/javax/security/auth/AuthPermission.java +++ b/jdk/src/java.base/share/classes/javax/security/auth/AuthPermission.java @@ -101,6 +101,18 @@ package javax.security.auth; * login Configuration. * * + *
Please note that granting this permission with the "modifyPrincipals", + * "modifyPublicCredentials" or "modifyPrivateCredentials" target allows + * a JAAS login module to populate principal or credential objects into + * the Subject. Although reading information inside the private credentials + * set requires a {@link PrivateCredentialPermission} of the credential type to + * be granted, reading information inside the principals set and the public + * credentials set requires no additional permission. These objects can contain + * potentially sensitive information. For example, login modules that read + * local user information or perform a Kerberos login are able to add + * potentially sensitive information such as user ids, groups and domain names + * to the principals set. + * *
The following target name has been deprecated in favor of * {@code createLoginContext.{name}}. * diff --git a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java index 3a1c2c4c41b..8e03a365c3a 100644 --- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java +++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java @@ -100,9 +100,16 @@ public final class KerberosPrincipal *
If the input name does not contain a realm, the default realm * is used. The default realm can be specified either in a Kerberos * configuration file or via the java.security.krb5.realm - * system property. For more information, + * system property. For more information, see * - * Kerberos Requirements + * Kerberos Requirements. Additionally, if a security manager is + * installed, a {@link ServicePermission} must be granted and the service + * principal of the permission must minimally be inside the + * {@code KerberosPrincipal}'s realm. For example, if the result of + * {@code new KerberosPrincipal("user")} is {@code user@EXAMPLE.COM}, + * then a {@code ServicePermission} with service principal + * {@code host/www.example.com@EXAMPLE.COM} (and any action) + * must be granted. * * @param name the principal name * @throws IllegalArgumentException if name is improperly @@ -110,20 +117,12 @@ public final class KerberosPrincipal * the realm to use and the default realm is not specified * in either a Kerberos configuration file or via the * java.security.krb5.realm system property. + * @throws SecurityException if a security manager is installed and + * {@code name} does not contain the realm to use, and a proper + * {@link ServicePermission} as described above is not granted. */ public KerberosPrincipal(String name) { - - PrincipalName krb5Principal = null; - - try { - // Appends the default realm if it is missing - krb5Principal = new PrincipalName(name, KRB_NT_PRINCIPAL); - } catch (KrbException e) { - throw new IllegalArgumentException(e.getMessage()); - } - nameType = KRB_NT_PRINCIPAL; // default name type - fullName = krb5Principal.toString(); - realm = krb5Principal.getRealmString(); + this(name, KRB_NT_PRINCIPAL); } /** @@ -138,12 +137,19 @@ public final class KerberosPrincipal * name type, KRB_NT_PRINCIPAL where duke * represents a principal, and FOO.COM represents a realm). * - *
If the input name does not contain a realm, the default realm + *
If the input name does not contain a realm, the default realm * is used. The default realm can be specified either in a Kerberos * configuration file or via the java.security.krb5.realm * system property. For more information, see * - * Kerberos Requirements. + * Kerberos Requirements. Additionally, if a security manager is + * installed, a {@link ServicePermission} must be granted and the service + * principal of the permission must minimally be inside the + * {@code KerberosPrincipal}'s realm. For example, if the result of + * {@code new KerberosPrincipal("user")} is {@code user@EXAMPLE.COM}, + * then a {@code ServicePermission} with service principal + * {@code host/www.example.com@EXAMPLE.COM} (and any action) + * must be granted. * * @param name the principal name * @param nameType the name type of the principal @@ -152,6 +158,9 @@ public final class KerberosPrincipal * or if name does not contain the realm to use and the default * realm is not specified in either a Kerberos configuration * file or via the java.security.krb5.realm system property. + * @throws SecurityException if a security manager is installed and + * {@code name} does not contain the realm to use, and a proper + * {@link ServicePermission} as described above is not granted. */ public KerberosPrincipal(String name, int nameType) { @@ -165,6 +174,18 @@ public final class KerberosPrincipal throw new IllegalArgumentException(e.getMessage()); } + if (krb5Principal.isRealmDeduced() && !Realm.AUTODEDUCEREALM) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + try { + sm.checkPermission(new ServicePermission( + "@" + krb5Principal.getRealmAsString(), "-")); + } catch (SecurityException se) { + // Swallow the actual exception to hide info + throw new SecurityException("Cannot read realm info"); + } + } + } this.nameType = nameType; fullName = krb5Principal.toString(); realm = krb5Principal.getRealmString(); diff --git a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java index f20d2a47339..19629b06a86 100644 --- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java +++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java @@ -51,7 +51,7 @@ import java.util.concurrent.ConcurrentHashMap; * used within. *
* The service principal name is the canonical name of the - * {@code KereberosPrincipal} supplying the service, that is + * {@code KerberosPrincipal} supplying the service, that is * the KerberosPrincipal represents a Kerberos service * principal. This name is treated in a case sensitive manner. * An asterisk may appear by itself, to signify any service principal. @@ -62,6 +62,10 @@ import java.util.concurrent.ConcurrentHashMap; * permission also implies that the TGT can be obtained by an * Authentication Service exchange. *
+ * Granting this permission also implies creating {@link KerberosPrincipal} + * or {@link org.ietf.jgss.GSSName GSSName} without providing a Kerberos + * realm, as long as the permission's service principal is in this realm. + *
* The possible actions are: * *
@@ -146,6 +150,9 @@ public final class ServicePermission extends Permission * @param action the action string */ public ServicePermission(String servicePrincipal, String action) { + // Note: servicePrincipal can be "@REALM" which means any principal in + // this realm implies it. action can be "-" which means any + // action implies it. super(servicePrincipal); init(servicePrincipal, getMask(action)); } @@ -208,7 +215,9 @@ public final class ServicePermission extends Permission boolean impliesIgnoreMask(ServicePermission p) { return ((this.getName().equals("*")) || - this.getName().equals(p.getName())); + this.getName().equals(p.getName()) || + (p.getName().startsWith("@") && + this.getName().endsWith(p.getName()))); } /** @@ -318,7 +327,10 @@ public final class ServicePermission extends Permission /** * Convert an action string to an integer actions mask. * - * @param action the action string + * Note: if action is "-", action will be NONE, which means any + * action implies it. + * + * @param action the action string. * @return the action mask */ private static int getMask(String action) { @@ -335,9 +347,11 @@ public final class ServicePermission extends Permission char[] a = action.toCharArray(); - int i = a.length - 1; - if (i < 0) + if (a.length == 1 && a[0] == '-') { return mask; + } + + int i = a.length - 1; while (i != -1) { char c; @@ -501,6 +515,17 @@ final class KrbServicePermissionCollection extends PermissionCollection ServicePermission np = (ServicePermission) permission; int desired = np.getMask(); + if (desired == 0) { + for (Permission p: perms.values()) { + ServicePermission sp = (ServicePermission)p; + if (sp.impliesIgnoreMask(np)) { + return true; + } + } + return false; + } + + // first, check for wildcard principal ServicePermission x = (ServicePermission)perms.get("*"); if (x != null) { diff --git a/jdk/src/java.security.jgss/share/classes/org/ietf/jgss/GSSName.java b/jdk/src/java.security.jgss/share/classes/org/ietf/jgss/GSSName.java index 185a6c2f7b4..d55bd6abb47 100644 --- a/jdk/src/java.security.jgss/share/classes/org/ietf/jgss/GSSName.java +++ b/jdk/src/java.security.jgss/share/classes/org/ietf/jgss/GSSName.java @@ -81,6 +81,18 @@ package org.ietf.jgss; * GSSName.NT_EXPORT_NAME); * *+ * If a security manager is installed, in order to create a {@code GSSName} + * that contains a Kerberos name element without providing its realm, + * a {@link javax.security.auth.kerberos.ServicePermission ServicePermission} + * must be granted and the service principal of the permission must minimally + * be inside the Kerberos name element's realm. For example, if the result of + * {@link GSSManager#createName(String, Oid) createName("user", NT_USER_NAME)} + * contains a Kerberos name element {@code user@EXAMPLE.COM}, then + * a {@code ServicePermission} with service principal + * {@code host/www.example.com@EXAMPLE.COM} (and any action) must be granted. + * Otherwise, the creation will throw a {@link GSSException} containing the + * {@code GSSException.FAILURE} error code. + * * @see #export() * @see #equals(GSSName) * @see GSSManager#createName(String, Oid) diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5NameElement.java b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5NameElement.java index 964d8890070..1d0217e9187 100644 --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5NameElement.java +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5NameElement.java @@ -28,7 +28,10 @@ package sun.security.jgss.krb5; import org.ietf.jgss.*; import sun.security.jgss.spi.*; import sun.security.krb5.PrincipalName; +import sun.security.krb5.Realm; import sun.security.krb5.KrbException; + +import javax.security.auth.kerberos.ServicePermission; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.UnknownHostException; @@ -126,6 +129,18 @@ public class Krb5NameElement throw new GSSException(GSSException.BAD_NAME, -1, e.getMessage()); } + if (principalName.isRealmDeduced() && !Realm.AUTODEDUCEREALM) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + try { + sm.checkPermission(new ServicePermission( + "@" + principalName.getRealmAsString(), "-")); + } catch (SecurityException se) { + // Do not chain the actual exception to hide info + throw new GSSException(GSSException.FAILURE); + } + } + } return new Krb5NameElement(principalName, gssNameStr, gssNameType); } diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java index 8030a209697..d09ca8d6a16 100644 --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java @@ -30,6 +30,7 @@ import java.security.Provider; import java.security.Security; import java.io.IOException; import java.io.UnsupportedEncodingException; +import sun.security.krb5.Realm; import sun.security.jgss.GSSUtil; import sun.security.util.ObjectIdentifier; import sun.security.util.DerInputStream; @@ -38,6 +39,8 @@ import sun.security.jgss.GSSUtil; import sun.security.jgss.GSSExceptionImpl; import sun.security.jgss.spi.GSSNameSpi; +import javax.security.auth.kerberos.ServicePermission; + /** * This class is essentially a wrapper class for the gss_name_t * structure of the native GSS library. @@ -150,6 +153,26 @@ public class GSSNameElement implements GSSNameSpi { pName = cStub.importName(name, nameType); setPrintables(); + SecurityManager sm = System.getSecurityManager(); + if (sm != null && !Realm.AUTODEDUCEREALM) { + String krbName = getKrbName(); + int atPos = krbName.lastIndexOf('@'); + if (atPos != -1) { + String atRealm = krbName.substring(atPos); + if (nameType.equals(GSSUtil.NT_GSS_KRB5_PRINCIPAL) + && new String(nameBytes).endsWith(atRealm)) { + // Created from Kerberos name with realm, no need to check + } else { + try { + sm.checkPermission(new ServicePermission(atRealm, "-")); + } catch (SecurityException se) { + // Do not chain the actual exception to hide info + throw new GSSException(GSSException.FAILURE); + } + } + } + } + SunNativeProvider.debug("Imported " + printableName + " w/ type " + printableType); } diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbServiceLocator.java b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbServiceLocator.java index fa557c3507d..b6bc8fd8181 100644 --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbServiceLocator.java +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbServiceLocator.java @@ -25,6 +25,11 @@ package sun.security.krb5; +import sun.security.krb5.internal.Krb5; + +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.util.Arrays; import java.util.Hashtable; import java.util.Random; @@ -52,6 +57,8 @@ class KrbServiceLocator { private static final Random random = new Random(); + private static final boolean DEBUG = Krb5.DEBUG; + private KrbServiceLocator() { } @@ -62,8 +69,7 @@ class KrbServiceLocator { * Information on the mapping of DNS hostnames and domain names * to Kerberos realms is stored using DNS TXT records * - * @param domainName A string domain name. - * @param environment The possibly null environment of the context. + * @param realmName A string realm name. * @return An ordered list of hostports for the Kerberos service or null if * the service has not been located. */ @@ -81,8 +87,18 @@ class KrbServiceLocator { if (!(ctx instanceof DirContext)) { return null; // cannot create a DNS context } - Attributes attrs = - ((DirContext)ctx).getAttributes(dnsUrl, SRV_TXT_ATTR); + Attributes attrs = null; + try { + // both connect and accept are needed since DNS is thru UDP + attrs = AccessController.doPrivileged( + (PrivilegedExceptionAction