8130648: JCK test api/java_security/AuthProvider/ProviderTests_login starts failing after JDK-7191662
Summary: Make uninitialized SunPKCS11 provider throw IllegalStateException for AuthProvider calls.
Reviewed-by: mullan
--- a/jdk/src/java.base/share/classes/java/security/AuthProvider.java Thu Oct 08 17:03:07 2015 +0530
+++ b/jdk/src/java.base/share/classes/java/security/AuthProvider.java Thu Oct 08 20:51:08 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, 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
@@ -79,8 +79,10 @@
* this provider to obtain authentication information
* from the caller, which may be {@code null}
*
- * @exception LoginException if the login operation fails
- * @exception SecurityException if the caller does not pass a
+ * @throws IllegalStateException if the provider requires configuration
+ * and {@link configure} has not been called
+ * @throws LoginException if the login operation fails
+ * @throws SecurityException if the caller does not pass a
* security check for
* {@code SecurityPermission("authProvider.name")},
* where {@code name} is the value returned by
@@ -92,8 +94,10 @@
/**
* Log out from this provider.
*
- * @exception LoginException if the logout operation fails
- * @exception SecurityException if the caller does not pass a
+ * @throws IllegalStateException if the provider requires configuration
+ * and {@link configure} has not been called
+ * @throws LoginException if the logout operation fails
+ * @throws SecurityException if the caller does not pass a
* security check for
* {@code SecurityPermission("authProvider.name")},
* where {@code name} is the value returned by
@@ -118,7 +122,9 @@
* @param handler a {@code CallbackHandler} for obtaining
* authentication information, which may be {@code null}
*
- * @exception SecurityException if the caller does not pass a
+ * @throws IllegalStateException if the provider requires configuration
+ * and {@link configure} has not been called
+ * @throws SecurityException if the caller does not pass a
* security check for
* {@code SecurityPermission("authProvider.name")},
* where {@code name} is the value returned by
--- a/jdk/src/java.base/share/classes/java/security/Provider.java Thu Oct 08 17:03:07 2015 +0530
+++ b/jdk/src/java.base/share/classes/java/security/Provider.java Thu Oct 08 20:51:08 2015 +0000
@@ -187,13 +187,30 @@
* is invalid.
* @return a provider configured with the supplied configuration argument.
*
- * @since 1.9
+ * @since 9
*/
public Provider configure(String configArg) {
throw new UnsupportedOperationException("configure is not supported");
}
/**
+ * Check if this provider instance has been configured.
+ *
+ * @implSpec
+ * The default implementation returns true.
+ * Subclasses should override this method if the provider instance requires
+ * an explicit {@code configure} call after being constructed.
+ *
+ * @return true if no further configuration is needed, false otherwise.
+ *
+ * @since 9
+ */
+ public boolean isConfigured() {
+ return true;
+ }
+
+
+ /**
* Returns the name of this provider.
*
* @return the name of this provider.
--- a/jdk/src/java.base/share/classes/java/security/SecurityPermission.java Thu Oct 08 17:03:07 2015 +0530
+++ b/jdk/src/java.base/share/classes/java/security/SecurityPermission.java Thu Oct 08 20:51:08 2015 +0000
@@ -53,6 +53,17 @@
* </tr>
*
* <tr>
+ * <td>authProvider.{provider name}</td>
+ * <td>Allow the named provider to be an AuthProvider for login and
+ * logout operations. </td>
+ * <td>This allows the named provider to perform login and logout
+ * operations. The named provider must extend {@code AuthProvider}
+ * and care must be taken to grant to a trusted provider since
+ * login operations involve sensitive authentication information
+ * such as PINs and passwords. </td>
+ * </tr>
+ *
+ * <tr>
* <td>createAccessControlContext</td>
* <td>Creation of an AccessControlContext</td>
* <td>This allows someone to instantiate an AccessControlContext
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java Thu Oct 08 17:03:07 2015 +0530
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java Thu Oct 08 20:51:08 2015 +0000
@@ -106,9 +106,9 @@
public Provider configure(String configArg) throws InvalidParameterException {
final String newConfigName = checkNull(configArg);
try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction<Provider>() {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<>() {
@Override
- public Provider run() throws Exception {
+ public SunPKCS11 run() throws Exception {
return new SunPKCS11(new Config(newConfigName));
}
});
@@ -119,6 +119,11 @@
}
}
+ @Override
+ public boolean isConfigured() {
+ return (config != null);
+ }
+
private static <T> T checkNull(T obj) {
if (obj == null) {
throw new NullPointerException();
@@ -1142,8 +1147,10 @@
* @param handler the <code>CallbackHandler</code> used by
* this provider to communicate with the caller
*
- * @exception LoginException if the login operation fails
- * @exception SecurityException if the does not pass a security check for
+ * @throws IllegalStateException if the provider requires configuration
+ * and Provider.configure has not been called
+ * @throws LoginException if the login operation fails
+ * @throws SecurityException if the does not pass a security check for
* <code>SecurityPermission("authProvider.<i>name</i>")</code>,
* where <i>name</i> is the value returned by
* this provider's <code>getName</code> method
@@ -1151,8 +1158,11 @@
public void login(Subject subject, CallbackHandler handler)
throws LoginException {
+ if (!isConfigured()) {
+ throw new IllegalStateException("Configuration is required");
+ }
+
// security check
-
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
if (debug != null) {
@@ -1271,16 +1281,21 @@
/**
* Log out from this provider
*
- * @exception LoginException if the logout operation fails
- * @exception SecurityException if the does not pass a security check for
+ * @throws IllegalStateException if the provider requires configuration
+ * and Provider.configure has not been called
+ * @throws LoginException if the logout operation fails
+ * @throws SecurityException if the does not pass a security check for
* <code>SecurityPermission("authProvider.<i>name</i>")</code>,
* where <i>name</i> is the value returned by
* this provider's <code>getName</code> method
*/
public void logout() throws LoginException {
+ if (!isConfigured()) {
+ throw new IllegalStateException("Configuration is required");
+ }
+
// security check
-
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission
@@ -1353,7 +1368,9 @@
* @param handler a <code>CallbackHandler</code> for obtaining
* authentication information, which may be <code>null</code>
*
- * @exception SecurityException if the caller does not pass a
+ * @throws IllegalStateException if the provider requires configuration
+ * and Provider.configure has not been called
+ * @throws SecurityException if the caller does not pass a
* security check for
* <code>SecurityPermission("authProvider.<i>name</i>")</code>,
* where <i>name</i> is the value returned by
@@ -1361,8 +1378,11 @@
*/
public void setCallbackHandler(CallbackHandler handler) {
+ if (!isConfigured()) {
+ throw new IllegalStateException("Configuration is required");
+ }
+
// security check
-
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs11/Provider/LoginISE.java Thu Oct 08 20:51:08 2015 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+import java.io.*;
+import java.util.*;
+import java.security.*;
+import javax.security.auth.callback.*;
+
+/**
+ * @test
+ * @bug 8130648
+ * @summary make sure IllegalStateException is thrown for uninitialized
+ * SunPKCS11 provider instance
+ */
+public class LoginISE {
+
+ public static void main(String[] args) throws Exception {
+
+ Provider p = Security.getProvider("SunPKCS11");
+ if (p == null) {
+ System.out.println("No un-initialized PKCS11 provider available; skip");
+ return;
+ }
+ if (!(p instanceof AuthProvider)) {
+ throw new RuntimeException("Error: expect AuthProvider!");
+ }
+ AuthProvider ap = (AuthProvider) p;
+ if (ap.isConfigured()) {
+ throw new RuntimeException("Fail: isConfigured() should return false");
+ }
+ try {
+ ap.login(null, null);
+ throw new RuntimeException("Fail: expected ISE not thrown!");
+ } catch (IllegalStateException ise) {
+ System.out.println("Expected ISE thrown for login call");
+ }
+ try {
+ ap.logout();
+ throw new RuntimeException("Fail: expected ISE not thrown!");
+ } catch (IllegalStateException ise) {
+ System.out.println("Expected ISE thrown for logout call");
+ }
+ try {
+ ap.setCallbackHandler(new PasswordCallbackHandler());
+ throw new RuntimeException("Fail: expected ISE not thrown!");
+ } catch (IllegalStateException ise) {
+ System.out.println("Expected ISE thrown for logout call");
+ }
+
+ System.out.println("Test Passed");
+ }
+
+ public static class PasswordCallbackHandler implements CallbackHandler {
+ public void handle(Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException {
+ }
+ }
+}