From 4cefd50f0c7fa98c3d55eee6e933da6f4e083840 Mon Sep 17 00:00:00 2001 From: mbalao Date: Fri, 10 May 2019 09:39:49 +0800 Subject: [PATCH] 8200400: Restrict Sasl mechanisms Reviewed-by: andrew --- .../classes/javax/security/sasl/Sasl.java | 51 ++++++++++- src/share/lib/security/java.security-aix | 17 ++++ src/share/lib/security/java.security-linux | 17 ++++ src/share/lib/security/java.security-macosx | 17 ++++ src/share/lib/security/java.security-solaris | 17 ++++ src/share/lib/security/java.security-windows | 17 ++++ .../sasl/Sasl/DisabledMechanisms.java | 85 +++++++++++++++++++ 7 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 test/javax/security/sasl/Sasl/DisabledMechanisms.java diff --git a/src/share/classes/javax/security/sasl/Sasl.java b/src/share/classes/javax/security/sasl/Sasl.java index 1ce36c743..7e0baf16e 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 0f2117988..e078b6134 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 3483921db..632716772 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 aa3fe2d7c..e41e4940d 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 9fe330467..6fab982f2 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 695c8bb59..c777410e1 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 000000000..428cc3ad4 --- /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]); + } +} -- GitLab