diff --git a/src/share/classes/javax/security/sasl/Sasl.java b/src/share/classes/javax/security/sasl/Sasl.java index 1ce36c743116f2b010f2b6ceedb718e8543c6c1e..7e0baf16eaa46ff6c715eeafb83fb0a37a99518d 100644 --- a/src/share/classes/javax/security/sasl/Sasl.java +++ b/src/share/classes/javax/security/sasl/Sasl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,15 +26,20 @@ package javax.security.sasl; import javax.security.auth.callback.CallbackHandler; - +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.HashSet; import java.util.Collections; import java.security.Provider; import java.security.Security; +import java.util.logging.Level; +import java.util.logging.Logger; /** * A static class for creating SASL clients and servers. @@ -62,6 +67,30 @@ import java.security.Security; * @author Rob Weltman */ public class Sasl { + + private static List disabledMechanisms = new ArrayList<>(); + + static { + String prop = AccessController.doPrivileged( + (PrivilegedAction) + () -> Security.getProperty("jdk.sasl.disabledMechanisms")); + + if (prop != null) { + for (String s : prop.split("\\s*,\\s*")) { + if (!s.isEmpty()) { + disabledMechanisms.add(s); + } + } + } + } + + private static final String SASL_LOGGER_NAME = "javax.security.sasl"; + + /** + * Logger for debug messages + */ + private static final Logger logger = Logger.getLogger(SASL_LOGGER_NAME); + // Cannot create one of these private Sasl() { } @@ -306,6 +335,9 @@ public class Sasl { * "Java Cryptography Architecture API Specification & Reference" * for information about how to install and configure security service * providers. + *

+ * If a mechanism is listed in the {@code jdk.sasl.disabledMechanisms} + * security property, it will be ignored and won't be negotiated. * * @param mechanisms The non-null list of mechanism names to try. Each is the * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5"). @@ -369,6 +401,10 @@ public class Sasl { "Mechanism name cannot be null"); } else if (mechName.length() == 0) { continue; + } else if (isDisabled(mechName)) { + logger.log(Level.FINE, + "Disabled " + mechName + " mechanism ignored"); + continue; } String mechFilter = "SaslClientFactory." + mechName; Provider[] provs = Security.getProviders(mechFilter); @@ -456,6 +492,9 @@ public class Sasl { * "Java Cryptography Architecture API Specification & Reference" * for information about how to install and configure security * service providers. + *

+ * If {@code mechanism} is listed in the {@code jdk.sasl.disabledMechanisms} + * security property, it will be ignored and this method returns {@code null}. * * @param mechanism The non-null mechanism name. It must be an * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5"). @@ -509,6 +548,10 @@ public class Sasl { throw new NullPointerException("Mechanism name cannot be null"); } else if (mechanism.length() == 0) { return null; + } else if (isDisabled(mechanism)) { + logger.log(Level.FINE, + "Disabled " + mechanism + " mechanism ignored"); + return null; } String mechFilter = "SaslServerFactory." + mechanism; @@ -618,4 +661,8 @@ public class Sasl { } return Collections.unmodifiableSet(result); } + + private static boolean isDisabled(String name) { + return disabledMechanisms.contains(name); + } } diff --git a/src/share/lib/security/java.security-aix b/src/share/lib/security/java.security-aix index 0f21179880f95bdda5ff71d8dca95e0c90841099..e078b6134fcec95398ef66ee888e9c447c388940 100644 --- a/src/share/lib/security/java.security-aix +++ b/src/share/lib/security/java.security-aix @@ -986,6 +986,23 @@ jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ # #jdk.jceks.iterationCount = 200000 +# +# Disabled mechanisms for the Simple Authentication and Security Layer (SASL) +# +# Disabled mechanisms will not be negotiated by both SASL clients and servers. +# These mechanisms will be ignored if they are specified in the mechanisms argument +# of `Sasl.createClient` or the mechanism argument of `Sasl.createServer`. +# +# The value of this property is a comma-separated list of SASL mechanisms. +# The mechanisms are case-sensitive. Whitespaces around the commas are ignored. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# Example: +# jdk.sasl.disabledMechanisms=PLAIN, CRAM-MD5, DIGEST-MD5 +jdk.sasl.disabledMechanisms= + # # Policies for distrusting Certificate Authorities (CAs). # diff --git a/src/share/lib/security/java.security-linux b/src/share/lib/security/java.security-linux index 3483921db186583345e7e6fe0a22f444fb9b874b..632716772edc5e2f62a22d19989841a8408411ab 100644 --- a/src/share/lib/security/java.security-linux +++ b/src/share/lib/security/java.security-linux @@ -992,6 +992,23 @@ jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ # #jdk.jceks.iterationCount = 200000 +# +# Disabled mechanisms for the Simple Authentication and Security Layer (SASL) +# +# Disabled mechanisms will not be negotiated by both SASL clients and servers. +# These mechanisms will be ignored if they are specified in the mechanisms argument +# of `Sasl.createClient` or the mechanism argument of `Sasl.createServer`. +# +# The value of this property is a comma-separated list of SASL mechanisms. +# The mechanisms are case-sensitive. Whitespaces around the commas are ignored. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# Example: +# jdk.sasl.disabledMechanisms=PLAIN, CRAM-MD5, DIGEST-MD5 +jdk.sasl.disabledMechanisms= + # # Policies for distrusting Certificate Authorities (CAs). # diff --git a/src/share/lib/security/java.security-macosx b/src/share/lib/security/java.security-macosx index aa3fe2d7cd02699d096bc4b1ddc7c9bd65269249..e41e4940d89629a5fc3d13ae6c58501063bba7af 100644 --- a/src/share/lib/security/java.security-macosx +++ b/src/share/lib/security/java.security-macosx @@ -990,6 +990,23 @@ jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ # #jdk.jceks.iterationCount = 200000 +# +# Disabled mechanisms for the Simple Authentication and Security Layer (SASL) +# +# Disabled mechanisms will not be negotiated by both SASL clients and servers. +# These mechanisms will be ignored if they are specified in the mechanisms argument +# of `Sasl.createClient` or the mechanism argument of `Sasl.createServer`. +# +# The value of this property is a comma-separated list of SASL mechanisms. +# The mechanisms are case-sensitive. Whitespaces around the commas are ignored. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# Example: +# jdk.sasl.disabledMechanisms=PLAIN, CRAM-MD5, DIGEST-MD5 +jdk.sasl.disabledMechanisms= + # # Policies for distrusting Certificate Authorities (CAs). # diff --git a/src/share/lib/security/java.security-solaris b/src/share/lib/security/java.security-solaris index 9fe33046752b250712d76b312240b1845d70f01a..6fab982f2dc40da7dcbb7c8170e4246bd84f89b7 100644 --- a/src/share/lib/security/java.security-solaris +++ b/src/share/lib/security/java.security-solaris @@ -989,6 +989,23 @@ jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ # #jdk.jceks.iterationCount = 200000 +# +# Disabled mechanisms for the Simple Authentication and Security Layer (SASL) +# +# Disabled mechanisms will not be negotiated by both SASL clients and servers. +# These mechanisms will be ignored if they are specified in the mechanisms argument +# of `Sasl.createClient` or the mechanism argument of `Sasl.createServer`. +# +# The value of this property is a comma-separated list of SASL mechanisms. +# The mechanisms are case-sensitive. Whitespaces around the commas are ignored. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# Example: +# jdk.sasl.disabledMechanisms=PLAIN, CRAM-MD5, DIGEST-MD5 +jdk.sasl.disabledMechanisms= + # # Policies for distrusting Certificate Authorities (CAs). # diff --git a/src/share/lib/security/java.security-windows b/src/share/lib/security/java.security-windows index 695c8bb5991b293272f4425ffcc2f33404957429..c777410e19871b4f62f0256a22dcbf3e27ab87b8 100644 --- a/src/share/lib/security/java.security-windows +++ b/src/share/lib/security/java.security-windows @@ -990,6 +990,23 @@ jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ # #jdk.jceks.iterationCount = 200000 +# +# Disabled mechanisms for the Simple Authentication and Security Layer (SASL) +# +# Disabled mechanisms will not be negotiated by both SASL clients and servers. +# These mechanisms will be ignored if they are specified in the mechanisms argument +# of `Sasl.createClient` or the mechanism argument of `Sasl.createServer`. +# +# The value of this property is a comma-separated list of SASL mechanisms. +# The mechanisms are case-sensitive. Whitespaces around the commas are ignored. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# Example: +# jdk.sasl.disabledMechanisms=PLAIN, CRAM-MD5, DIGEST-MD5 +jdk.sasl.disabledMechanisms= + # # Policies for distrusting Certificate Authorities (CAs). # diff --git a/test/javax/security/sasl/Sasl/DisabledMechanisms.java b/test/javax/security/sasl/Sasl/DisabledMechanisms.java new file mode 100644 index 0000000000000000000000000000000000000000..428cc3ad4896cbc2563bd51b1a086c5cb711e4bc --- /dev/null +++ b/test/javax/security/sasl/Sasl/DisabledMechanisms.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8200400 + * @library /lib/testlibrary + * @run main/othervm DisabledMechanisms + * DIGEST-MD5 DIGEST-MD5 + * @run main/othervm -DdisabledMechanisms= DisabledMechanisms + * DIGEST-MD5 DIGEST-MD5 + * @run main/othervm -DdisabledMechanisms=DIGEST-MD5,NTLM DisabledMechanisms + * null null + * @run main/othervm -DdisabledMechanisms=DIGEST-MD5 DisabledMechanisms + * NTLM null + * @run main/othervm -DdisabledMechanisms=NTLM DisabledMechanisms + * DIGEST-MD5 DIGEST-MD5 + */ + +import java.security.Security; +import java.util.Collections; +import java.util.Map; +import javax.security.auth.callback.PasswordCallback; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslClient; +import javax.security.sasl.SaslServer; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; + +import jdk.testlibrary.Asserts; + +public class DisabledMechanisms { + + public static void main(String[] args) throws Exception { + + String authorizationId = "username"; + String protocol = "ldap"; + String serverName = "server1"; + Map props = Collections.emptyMap(); + + String disabled = System.getProperty("disabledMechanisms"); + if (disabled != null) { + Security.setProperty("jdk.sasl.disabledMechanisms", disabled); + } + + CallbackHandler callbackHandler = callbacks -> { + for (Callback cb : callbacks) { + if (cb instanceof PasswordCallback) { + ((PasswordCallback) cb).setPassword("password".toCharArray()); + } + } + }; + + SaslClient client = Sasl.createSaslClient( + new String[]{"DIGEST-MD5", "NTLM"}, authorizationId, + protocol, serverName, props, callbackHandler); + Asserts.assertEQ(client == null ? null : client.getMechanismName(), + args[0].equals("null") ? null : args[0]); + + SaslServer server = Sasl.createSaslServer( + "DIGEST-MD5", protocol, serverName, props, callbackHandler); + Asserts.assertEQ(server == null ? null : server.getMechanismName(), + args[1].equals("null") ? null : args[1]); + } +}