Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/security/krb5/auto/LoginModuleOptions.java
38853 views
/*1* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 676549126* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock LoginModuleOptions27* @summary Krb5LoginModule a little too restrictive, and the doc is not clear.28*/29import com.sun.security.auth.module.Krb5LoginModule;30import java.util.HashMap;31import java.util.Map;32import javax.security.auth.Subject;33import javax.security.auth.callback.Callback;34import javax.security.auth.callback.CallbackHandler;35import javax.security.auth.callback.NameCallback;36import javax.security.auth.callback.PasswordCallback;3738public class LoginModuleOptions {3940private static final String NAME = "javax.security.auth.login.name";41private static final String PWD = "javax.security.auth.login.password";4243public static void main(String[] args) throws Exception {44OneKDC kdc = new OneKDC(null);45kdc.addPrincipal("foo", "bar".toCharArray());46kdc.writeKtab(OneKDC.KTAB); // rewrite to add foo4748// All 4 works: keytab, shared state, callback, cache49login(null, "useKeyTab", "true", "principal", "dummy");50login(null, "tryFirstPass", "true", NAME, OneKDC.USER,51PWD, OneKDC.PASS);52System.setProperty("test.kdc.save.ccache", "krbcc");53login(new MyCallback(OneKDC.USER, OneKDC.PASS)); // save the cache54System.clearProperty("test.kdc.save.ccache");55login(null, "useTicketCache", "true", "ticketCache", "krbcc");5657// Fallbacks58// 1. ccache -> keytab59login(null, "useTicketCache", "true", "ticketCache", "krbcc_non_exists",60"useKeyTab", "true", "principal", "dummy");6162// 2. keytab -> shared63login(null, "useKeyTab", "true", "principal", "dummy",64"keyTab", "ktab_non_exist",65"tryFirstPass", "true", NAME, OneKDC.USER, PWD, OneKDC.PASS);6667// 3. shared -> callback68// 3.1. useFirstPass, no callback69boolean failed = false;70try {71login(new MyCallback(OneKDC.USER, OneKDC.PASS),72"useFirstPass", "true",73NAME, OneKDC.USER, PWD, "haha".toCharArray());74} catch (Exception e) {75failed = true;76}77if (!failed) {78throw new Exception("useFirstPass should not fallback to callback");79}80// 3.2. tryFirstPass, has callback81login(new MyCallback(OneKDC.USER, OneKDC.PASS),82"tryFirstPass", "true",83NAME, OneKDC.USER, PWD, "haha".toCharArray());8485// Preferences of type86// 1. ccache preferred to keytab87login(new MyCallback("foo", null),88"useTicketCache", "true", "ticketCache", "krbcc",89"useKeyTab", "true");90// 2. keytab preferred to shared. This test case is not exactly correct,91// because principal=dummy would shadow the PWD setting in the shared92// state. So by only looking at the final authentication user name93// (which is how this program does), there's no way to tell if keyTab94// is picked first, or shared is tried first but fallback to keytab.95login(null, "useKeyTab", "true", "principal", "dummy",96"tryFirstPass", "true", NAME, "foo", PWD, "bar".toCharArray());97// 3. shared preferred to callback98login(new MyCallback("foo", "bar".toCharArray()),99"tryFirstPass", "true", NAME, OneKDC.USER, PWD, OneKDC.PASS);100101// Preferences of username102// 1. principal preferred to NAME (NAME can be wrong or missing)103login(null, "principal", OneKDC.USER,104"tryFirstPass", "true", NAME, "someone_else", PWD, OneKDC.PASS);105login(null, "principal", OneKDC.USER,106"tryFirstPass", "true", PWD, OneKDC.PASS);107// 2. NAME preferred to callback108login(new MyCallback("someone_else", OneKDC.PASS),109"principal", OneKDC.USER);110// 3. With tryFirstPass, NAME preferred to callback111login(new MyCallback("someone_else", null),112"tryFirstPass", "true", NAME, OneKDC.USER, PWD, OneKDC.PASS);113// 3.1. you must provide a NAME (when there's no principal)114failed = false;115try {116login(new MyCallback(OneKDC.USER, null),117"tryFirstPass", "true", PWD, OneKDC.PASS);118} catch (Exception e) {119failed = true;120}121if (!failed) {122throw new Exception("useFirstPass must provide a NAME");123}124// 3.2 Hybrid, you can use NAME as "", and provide it using callback.125// I don't think this is designed.126login(new MyCallback(OneKDC.USER, null),127"tryFirstPass", "true", NAME, "", PWD, OneKDC.PASS);128129// Test for the bug fix: doNotPrompt can be true if tryFirstPass=true130login(null, "doNotPrompt", "true", "storeKey", "true",131"tryFirstPass", "true", NAME, OneKDC.USER, PWD, OneKDC.PASS);132}133134static void login(CallbackHandler callback, Object... options)135throws Exception {136Krb5LoginModule krb5 = new Krb5LoginModule();137Subject subject = new Subject();138Map<String, String> map = new HashMap<>();139Map<String, Object> shared = new HashMap<>();140141int count = options.length / 2;142for (int i = 0; i < count; i++) {143String key = (String) options[2 * i];144Object value = options[2 * i + 1];145if (key.startsWith("javax")) {146shared.put(key, value);147} else {148map.put(key, (String) value);149}150}151krb5.initialize(subject, callback, shared, map);152krb5.login();153krb5.commit();154if (!subject.getPrincipals().iterator().next()155.getName().startsWith(OneKDC.USER)) {156throw new Exception("The authenticated is not " + OneKDC.USER);157}158}159160static class MyCallback implements CallbackHandler {161162private String name;163private char[] password;164165public MyCallback(String name, char[] password) {166this.name = name;167this.password = password;168}169170public void handle(Callback[] callbacks) {171for (Callback callback : callbacks) {172System.err.println(callback);173if (callback instanceof NameCallback) {174System.err.println("name is " + name);175((NameCallback) callback).setName(name);176}177if (callback instanceof PasswordCallback) {178System.err.println("pass is " + new String(password));179((PasswordCallback) callback).setPassword(password);180}181}182}183}184}185186187