--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/LoginContext/CustomLoginModule.java Thu Apr 23 18:01:01 2015 +0800
@@ -0,0 +1,275 @@
+/*
+ * 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.IOException;
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Map;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.ChoiceCallback;
+import javax.security.auth.callback.ConfirmationCallback;
+import javax.security.auth.callback.LanguageCallback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
+import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+public class CustomLoginModule implements LoginModule {
+
+ static final String HELLO = "Hello";
+
+ private Subject subject;
+ private CallbackHandler callbackHandler;
+ private boolean loginSucceeded = false;
+ private String username;
+ private char[] password;
+
+ /*
+ * Initialize this LoginModule.
+ */
+ @Override
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map<String, ?> sharedState, Map<String, ?> options) {
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+
+ // check if custom parameter is passed from comfiguration
+ if (options == null) {
+ throw new RuntimeException("options is null");
+ }
+
+ // read username/password from configuration
+ Object o = options.get("username");
+ if (o == null) {
+ throw new RuntimeException("Custom parameter not passed");
+ }
+ if (!(o instanceof String)) {
+ throw new RuntimeException("Password is not a string");
+ }
+ username = (String) o;
+
+ o = options.get("password");
+ if (o == null) {
+ throw new RuntimeException("Custom parameter not passed");
+ }
+ if (!(o instanceof String)) {
+ throw new RuntimeException("Password is not a string");
+ }
+ password = ((String) o).toCharArray();
+ }
+
+ /*
+ * Authenticate the user.
+ */
+ @Override
+ public boolean login() throws LoginException {
+ // prompt for a user name and password
+ if (callbackHandler == null) {
+ throw new LoginException("No CallbackHandler available");
+ }
+
+ // standard callbacks
+ NameCallback name = new NameCallback("username: ", "default");
+ PasswordCallback passwd = new PasswordCallback("password: ", false);
+
+ LanguageCallback language = new LanguageCallback();
+
+ TextOutputCallback error = new TextOutputCallback(
+ TextOutputCallback.ERROR, "This is an error");
+ TextOutputCallback warning = new TextOutputCallback(
+ TextOutputCallback.WARNING, "This is a warning");
+ TextOutputCallback info = new TextOutputCallback(
+ TextOutputCallback.INFORMATION, "This is a FYI");
+
+ TextInputCallback text = new TextInputCallback("Please type " + HELLO,
+ "Bye");
+
+ ChoiceCallback choice = new ChoiceCallback("Choice: ",
+ new String[] { "pass", "fail" }, 1, true);
+
+ ConfirmationCallback confirmation = new ConfirmationCallback(
+ "confirmation: ", ConfirmationCallback.INFORMATION,
+ ConfirmationCallback.YES_NO_OPTION, ConfirmationCallback.NO);
+
+ CustomCallback custom = new CustomCallback();
+
+ Callback[] callbacks = new Callback[] {
+ choice, info, warning, error, name, passwd, text, language,
+ confirmation, custom
+ };
+
+ boolean uce = false;
+ try {
+ callbackHandler.handle(callbacks);
+ } catch (UnsupportedCallbackException e) {
+ Callback callback = e.getCallback();
+ if (custom.equals(callback)) {
+ uce = true;
+ System.out.println("CustomLoginModule: "
+ + "custom callback not supported as expected");
+ } else {
+ throw new LoginException("Unsupported callback: " + callback);
+ }
+ } catch (IOException ioe) {
+ throw new LoginException(ioe.toString());
+ }
+
+ if (!uce) {
+ throw new RuntimeException("UnsupportedCallbackException "
+ + "not thrown");
+ }
+
+ if (!HELLO.equals(text.getText())) {
+ System.out.println("Text: " + text.getText());
+ throw new FailedLoginException("No hello");
+ }
+
+ if (!Locale.GERMANY.equals(language.getLocale())) {
+ System.out.println("Selected locale: " + language.getLocale());
+ throw new FailedLoginException("Achtung bitte");
+ }
+
+ String readUsername = name.getName();
+ char[] readPassword = passwd.getPassword();
+ if (readPassword == null) {
+ // treat a NULL password as an empty password
+ readPassword = new char[0];
+ }
+ passwd.clearPassword();
+
+ // verify the username/password
+ if (!username.equals(readUsername)
+ || !Arrays.equals(password, readPassword)) {
+ loginSucceeded = false;
+ throw new FailedLoginException("Username/password is not correct");
+ }
+
+ // check chosen option
+ int[] selected = choice.getSelectedIndexes();
+ if (selected == null || selected.length == 0) {
+ throw new FailedLoginException("Nothing selected");
+ }
+
+ if (selected[0] != 0) {
+ throw new FailedLoginException("Wrong choice: " + selected[0]);
+ }
+
+ // check confirmation
+ if (confirmation.getSelectedIndex() != ConfirmationCallback.YES) {
+ throw new FailedLoginException("Not confirmed: "
+ + confirmation.getSelectedIndex());
+ }
+
+ loginSucceeded = true;
+ System.out.println("CustomLoginModule: authentication succeeded");
+ return true;
+ }
+
+ /*
+ * This method is called if the LoginContext's overall authentication
+ * succeeded.
+ */
+ @Override
+ public boolean commit() throws LoginException {
+ if (loginSucceeded) {
+ // add a Principal to the Subject
+ Principal principal = new TestPrincipal(username);
+ if (!subject.getPrincipals().contains(principal)) {
+ subject.getPrincipals().add(principal);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ /*
+ * This method is called if the LoginContext's overall authentication
+ * failed.
+ */
+ @Override
+ public boolean abort() throws LoginException {
+ loginSucceeded = false;
+ return true;
+ }
+
+ /*
+ * Logout the user.
+ */
+ @Override
+ public boolean logout() throws LoginException {
+ loginSucceeded = false;
+ boolean removed = subject.getPrincipals().remove(
+ new TestPrincipal(username));
+ if (!removed) {
+ throw new LoginException("Coundn't remove a principal: "
+ + username);
+ }
+ return true;
+ }
+
+ static class TestPrincipal implements Principal {
+
+ private final String name;
+
+ public TestPrincipal(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return("TestPrincipal [name =" + name + "]");
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null) {
+ return false;
+ }
+ if (!(o instanceof TestPrincipal)) {
+ return false;
+ }
+ TestPrincipal other = (TestPrincipal) o;
+ return name != null ? name.equals(other.name) : other.name == null;
+ }
+ }
+
+ static class CustomCallback implements Callback {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/LoginContext/SharedState.java Thu Apr 23 18:01:01 2015 +0800
@@ -0,0 +1,98 @@
+/*
+ * 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.util.Map;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+/**
+ * @test
+ * @bug 8048138
+ * @summary Check if shared state is passed to login module
+ * @run main/othervm SharedState
+ */
+public class SharedState {
+
+ static final String NAME = "name";
+ static final String VALUE = "shared";
+
+ public static void main(String[] args) throws LoginException {
+ System.setProperty("java.security.auth.login.config",
+ System.getProperty("test.src")
+ + System.getProperty("file.separator")
+ + "shared.config");
+
+ new LoginContext("SharedState").login();
+ }
+
+ public static abstract class Module implements LoginModule {
+
+ @Override
+ public boolean login() throws LoginException {
+ return true;
+ }
+
+ @Override
+ public boolean commit() throws LoginException {
+ return true;
+ }
+
+ @Override
+ public boolean abort() throws LoginException {
+ return true;
+ }
+
+ @Override
+ public boolean logout() throws LoginException {
+ return true;
+ }
+ }
+
+ public static class FirstModule extends Module {
+
+ @Override
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map<String,?> sharedState, Map<String,?> options) {
+ ((Map)sharedState).put(NAME, VALUE);
+ }
+
+ }
+
+ public static class SecondModule extends Module {
+
+ @Override
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map<String,?> sharedState, Map<String,?> options) {
+ // check shared object
+ Object shared = sharedState.get(NAME);
+ if (!VALUE.equals(shared)) {
+ throw new RuntimeException("Unexpected shared object: "
+ + shared);
+ }
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/LoginContext/StandardCallbacks.java Thu Apr 23 18:01:01 2015 +0800
@@ -0,0 +1,189 @@
+/*
+ * 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.security.Principal;
+import java.util.Arrays;
+import java.util.Locale;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.ChoiceCallback;
+import javax.security.auth.callback.ConfirmationCallback;
+import javax.security.auth.callback.LanguageCallback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
+import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+/*
+ * @test
+ * @bug 8048138
+ * @summary Checks if JAAS login works fine with standard callbacks
+ * @compile DefaultHandlerModule.java
+ * @run main/othervm StandardCallbacks
+ */
+public class StandardCallbacks {
+
+ private static final String USERNAME = "username";
+ private static final char[] PASSWORD = "password".toCharArray();
+
+ public static void main(String[] args) throws LoginException {
+ System.setProperty("java.security.auth.login.config",
+ System.getProperty("test.src")
+ + System.getProperty("file.separator")
+ + "custom.config");
+
+ CustomCallbackHandler handler = new CustomCallbackHandler(USERNAME);
+ LoginContext context = new LoginContext("StandardCallbacks", handler);
+
+ handler.setPassword(PASSWORD);
+ System.out.println("Try to login with correct password, "
+ + "successful authentication is expected");
+ context.login();
+ System.out.println("Authentication succeeded!");
+
+ Subject subject = context.getSubject();
+ System.out.println("Authenticated user has the following principals ["
+ + subject.getPrincipals().size() + " ]:");
+ boolean found = true;
+ for (Principal principal : subject.getPrincipals()) {
+ System.out.println("principal: " + principal);
+ if (principal instanceof CustomLoginModule.TestPrincipal) {
+ CustomLoginModule.TestPrincipal testPrincipal =
+ (CustomLoginModule.TestPrincipal) principal;
+ if (USERNAME.equals(testPrincipal.getName())) {
+ System.out.println("Found test principal: "
+ + testPrincipal);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ throw new RuntimeException("TestPrincipal not found");
+ }
+
+ // check if all expected text output callbacks have been called
+ if (!handler.info) {
+ throw new RuntimeException("TextOutputCallback.INFO not called");
+ }
+
+ if (!handler.warning) {
+ throw new RuntimeException("TextOutputCallback.WARNING not called");
+ }
+
+ if (!handler.error) {
+ throw new RuntimeException("TextOutputCallback.ERROR not called");
+ }
+
+ System.out.println("Authenticated user has the following public "
+ + "credentials [" + subject.getPublicCredentials().size()
+ + "]:");
+ subject.getPublicCredentials().stream().
+ forEach((o) -> {
+ System.out.println("public credential: " + o);
+ });
+
+ context.logout();
+
+ System.out.println("Test passed");
+ }
+
+ private static class CustomCallbackHandler implements CallbackHandler {
+
+ private final String username;
+ private char[] password;
+ private boolean info = false;
+ private boolean warning = false;
+ private boolean error = false;
+
+ CustomCallbackHandler(String username) {
+ this.username = username;
+ }
+
+ void setPassword(char[] password) {
+ this.password = password;
+ }
+
+ @Override
+ public void handle(Callback[] callbacks)
+ throws UnsupportedCallbackException {
+ for (Callback callback : callbacks) {
+ if (callback instanceof TextOutputCallback) {
+ TextOutputCallback toc = (TextOutputCallback) callback;
+ switch (toc.getMessageType()) {
+ case TextOutputCallback.INFORMATION:
+ System.out.println("INFO: " + toc.getMessage());
+ info = true;
+ break;
+ case TextOutputCallback.ERROR:
+ System.out.println("ERROR: " + toc.getMessage());
+ error = true;
+ break;
+ case TextOutputCallback.WARNING:
+ System.out.println("WARNING: " + toc.getMessage());
+ warning = true;
+ break;
+ default:
+ throw new UnsupportedCallbackException(toc,
+ "Unsupported message type: "
+ + toc.getMessageType());
+ }
+ } else if (callback instanceof TextInputCallback) {
+ TextInputCallback tic = (TextInputCallback) callback;
+ System.out.println(tic.getPrompt());
+ tic.setText(CustomLoginModule.HELLO);
+ } else if (callback instanceof LanguageCallback) {
+ LanguageCallback lc = (LanguageCallback) callback;
+ lc.setLocale(Locale.GERMANY);
+ } else if (callback instanceof ConfirmationCallback) {
+ ConfirmationCallback cc = (ConfirmationCallback) callback;
+ System.out.println(cc.getPrompt());
+ cc.setSelectedIndex(ConfirmationCallback.YES);
+ } else if (callback instanceof ChoiceCallback) {
+ ChoiceCallback cc = (ChoiceCallback) callback;
+ System.out.println(cc.getPrompt()
+ + Arrays.toString(cc.getChoices()));
+ cc.setSelectedIndex(0);
+ } else if (callback instanceof NameCallback) {
+ NameCallback nc = (NameCallback) callback;
+ System.out.println(nc.getPrompt());
+ nc.setName(username);
+ } else if (callback instanceof PasswordCallback) {
+ PasswordCallback pc = (PasswordCallback) callback;
+ System.out.println(pc.getPrompt());
+ pc.setPassword(password);
+ } else {
+ throw new UnsupportedCallbackException(callback,
+ "Unknown callback");
+ }
+ }
+ }
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/LoginContext/custom.config Thu Apr 23 18:01:01 2015 +0800
@@ -0,0 +1,4 @@
+StandardCallbacks {
+ DefaultHandlerModule required;
+ CustomLoginModule required username="username" password="password";
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/LoginContext/shared.config Thu Apr 23 18:01:01 2015 +0800
@@ -0,0 +1,4 @@
+SharedState {
+ SharedState$FirstModule required;
+ SharedState$SecondModule required;
+};
\ No newline at end of file