8075301: Tests for sun.security.krb5.principal system property

Reviewed-by: weijun
diff --git a/jdk/test/sun/security/krb5/auto/KDC.java b/jdk/test/sun/security/krb5/auto/KDC.java
index d09d8e1..d4a919f 100644
--- a/jdk/test/sun/security/krb5/auto/KDC.java
+++ b/jdk/test/sun/security/krb5/auto/KDC.java
@@ -30,6 +30,7 @@
 import java.security.SecureRandom;
 import java.util.*;
 import java.util.concurrent.*;
+
 import sun.net.spi.nameservice.NameService;
 import sun.net.spi.nameservice.NameServiceDescriptor;
 import sun.security.krb5.*;
@@ -155,6 +156,8 @@
     DatagramSocket u1 = null;
     ServerSocket t1 = null;
 
+    public static enum KtabMode { APPEND, EXISTING };
+
     /**
      * Option names, to be expanded forever.
      */
@@ -1316,6 +1319,68 @@
             // OK
         }
     }
+
+    public static void startKDC(final String host, final String krbConfFileName,
+            final String realm, final Map<String, String> principals,
+            final String ktab, final KtabMode mode) {
+
+        try {
+            KDC kdc = KDC.create(realm, host, 0, true);
+            kdc.setOption(KDC.Option.PREAUTH_REQUIRED, Boolean.FALSE);
+            KDC.saveConfig(krbConfFileName, kdc);
+
+            // Add principals
+            if (principals != null) {
+                principals.forEach((name, password) -> {
+                    if (password == null || password.isEmpty()) {
+                        System.out.println(String.format(
+                                "KDC:add a principal '%s' with a random " +
+                                        "password", name));
+                        kdc.addPrincipalRandKey(name);
+                    } else {
+                        System.out.println(String.format(
+                                "KDC:add a principal '%s' with '%s' password",
+                                name, password));
+                        kdc.addPrincipal(name, password.toCharArray());
+                    }
+                });
+            }
+
+            // Create or append keys to existing keytab file
+            if (ktab != null) {
+                File ktabFile = new File(ktab);
+                switch(mode) {
+                    case APPEND:
+                        if (ktabFile.exists()) {
+                            System.out.println(String.format(
+                                    "KDC:append keys to an exising keytab "
+                                    + "file %s", ktab));
+                            kdc.appendKtab(ktab);
+                        } else {
+                            System.out.println(String.format(
+                                    "KDC:create a new keytab file %s", ktab));
+                            kdc.writeKtab(ktab);
+                        }
+                        break;
+                    case EXISTING:
+                        System.out.println(String.format(
+                                "KDC:use an existing keytab file %s", ktab));
+                        break;
+                    default:
+                        throw new RuntimeException(String.format(
+                                "KDC:unsupported keytab mode: %s", mode));
+                }
+            }
+
+            System.out.println(String.format(
+                    "KDC: started on %s:%s with '%s' realm",
+                    host, kdc.getPort(), realm));
+        } catch (Exception e) {
+            throw new RuntimeException("KDC: unexpected exception", e);
+        }
+
+    }
+
     /**
      * Helper class to encapsulate a job in a KDC.
      */
diff --git a/jdk/test/sun/security/krb5/auto/UnboundSSL.java b/jdk/test/sun/security/krb5/auto/UnboundSSL.java
index 0862f07..5df24f8 100644
--- a/jdk/test/sun/security/krb5/auto/UnboundSSL.java
+++ b/jdk/test/sun/security/krb5/auto/UnboundSSL.java
@@ -26,6 +26,7 @@
 import java.security.PrivilegedActionException;
 import java.util.HashMap;
 import java.util.Map;
+
 import javax.security.auth.login.LoginException;
 
 /*
@@ -74,8 +75,9 @@
                UnboundSSLUtils.KRB5_CONF_FILENAME);
 
         // start a local KDC instance
-        UnboundSSLUtils.startKDC(UnboundSSLUtils.REALM, principals,
-                UnboundSSLUtils.KTAB_FILENAME, UnboundSSLUtils.KtabMode.APPEND);
+        KDC.startKDC(UnboundSSLUtils.HOST, UnboundSSLUtils.KRB5_CONF_FILENAME,
+                UnboundSSLUtils.REALM, principals,
+                UnboundSSLUtils.KTAB_FILENAME, KDC.KtabMode.APPEND);
 
         System.setProperty("java.security.auth.login.config",
                 UnboundSSLUtils.TEST_SRC + UnboundSSLUtils.FS + jaacConfigFile);
diff --git a/jdk/test/sun/security/krb5/auto/UnboundSSLMultipleKeys.java b/jdk/test/sun/security/krb5/auto/UnboundSSLMultipleKeys.java
index 255a40c..aa1ea2b3 100644
--- a/jdk/test/sun/security/krb5/auto/UnboundSSLMultipleKeys.java
+++ b/jdk/test/sun/security/krb5/auto/UnboundSSLMultipleKeys.java
@@ -26,6 +26,7 @@
 import java.security.PrivilegedActionException;
 import java.util.HashMap;
 import java.util.Map;
+
 import javax.security.auth.login.LoginException;
 
 /*
@@ -81,8 +82,9 @@
          * principal, but password for only one key is the same with the record
          * for service1 principal in KDC.
          */
-        UnboundSSLUtils.startKDC(UnboundSSLUtils.REALM, principals,
-                UnboundSSLUtils.KTAB_FILENAME, UnboundSSLUtils.KtabMode.APPEND);
+        KDC.startKDC(UnboundSSLUtils.HOST, UnboundSSLUtils.KRB5_CONF_FILENAME,
+                UnboundSSLUtils.REALM, principals,
+                UnboundSSLUtils.KTAB_FILENAME, KDC.KtabMode.APPEND);
 
         System.setProperty("java.security.auth.login.config",
                 UnboundSSLUtils.TEST_SRC + UnboundSSLUtils.FS + jaacConfigFile);
diff --git a/jdk/test/sun/security/krb5/auto/UnboundSSLPrincipalProperty.java b/jdk/test/sun/security/krb5/auto/UnboundSSLPrincipalProperty.java
index 3ccb4bf..ab8549e 100644
--- a/jdk/test/sun/security/krb5/auto/UnboundSSLPrincipalProperty.java
+++ b/jdk/test/sun/security/krb5/auto/UnboundSSLPrincipalProperty.java
@@ -70,8 +70,9 @@
                 UnboundSSLUtils.KRB5_CONF_FILENAME);
 
         // start a local KDC instance
-        UnboundSSLUtils.startKDC(UnboundSSLUtils.REALM, principals,
-                UnboundSSLUtils.KTAB_FILENAME, UnboundSSLUtils.KtabMode.APPEND);
+        KDC.startKDC(UnboundSSLUtils.HOST, UnboundSSLUtils.KRB5_CONF_FILENAME,
+                UnboundSSLUtils.REALM, principals,
+                UnboundSSLUtils.KTAB_FILENAME, KDC.KtabMode.APPEND);
 
         System.setProperty("java.security.auth.login.config",
                 UnboundSSLUtils.TEST_SRC + UnboundSSLUtils.FS + jaacConfigFile);
diff --git a/jdk/test/sun/security/krb5/auto/UnboundSSLUtils.java b/jdk/test/sun/security/krb5/auto/UnboundSSLUtils.java
index ab55e1f..1aefac2 100644
--- a/jdk/test/sun/security/krb5/auto/UnboundSSLUtils.java
+++ b/jdk/test/sun/security/krb5/auto/UnboundSSLUtils.java
@@ -50,8 +50,6 @@
  */
 class UnboundSSLUtils {
 
-    static enum KtabMode { APPEND, EXISTING };
-
     static final String KTAB_FILENAME = "krb5.keytab.data";
     static final String HOST = "localhost";
     static final String REALM = "TEST.REALM";
@@ -87,65 +85,6 @@
         });
     }
 
-    /*
-     * Start a KDC server:
-     *   - create a KDC instance
-     *   - create Kerberos principals
-     *   - save Kerberos configuration
-     *   - save keys to keytab file
-     *   - no pre-auth required
-     */
-    static void startKDC(String realm, Map<String, String> principals,
-            String ktab, KtabMode mode) {
-        try {
-            KDC kdc = KDC.create(realm, HOST, 0, true);
-            kdc.setOption(KDC.Option.PREAUTH_REQUIRED, Boolean.FALSE);
-            if (principals != null) {
-                for (Map.Entry<String, String> entry : principals.entrySet()) {
-                    String name = entry.getKey();
-                    String password = entry.getValue();
-                    if (password == null || password.isEmpty()) {
-                        System.out.println("KDC: add a principal '" + name +
-                                "' with a random password");
-                        kdc.addPrincipalRandKey(name);
-                    } else {
-                        System.out.println("KDC: add a principal '" + name +
-                                "' with '" + password + "' password");
-                        kdc.addPrincipal(name, password.toCharArray());
-                    }
-                }
-            }
-
-            KDC.saveConfig(KRB5_CONF_FILENAME, kdc);
-
-            if (ktab != null) {
-                File ktabFile = new File(ktab);
-                if (mode == KtabMode.APPEND) {
-                    if (ktabFile.exists()) {
-                        System.out.println("KDC: append keys to an exising " +
-                                "keytab file " + ktab);
-                        kdc.appendKtab(ktab);
-                    } else {
-                        System.out.println("KDC: create a new keytab file " +
-                                ktab);
-                        kdc.writeKtab(ktab);
-                    }
-                } else if (mode == KtabMode.EXISTING) {
-                    System.out.println("KDC: use an existing keytab file "
-                            + ktab);
-                } else {
-                    throw new RuntimeException("KDC: unsupported keytab mode: "
-                            + mode);
-                }
-            }
-
-            System.out.println("KDC: started on " + HOST + ":" + kdc.getPort()
-                    + " with '" + realm + "' realm");
-        } catch (Exception e) {
-            throw new RuntimeException("KDC: unexpected exception", e);
-        }
-    }
-
 }
 
 class SSLClient {
diff --git a/jdk/test/sun/security/krb5/auto/principalProperty/PrincipalSystemPropTest.java b/jdk/test/sun/security/krb5/auto/principalProperty/PrincipalSystemPropTest.java
new file mode 100644
index 0000000..262e1da
--- /dev/null
+++ b/jdk/test/sun/security/krb5/auto/principalProperty/PrincipalSystemPropTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8075301
+ * @library /sun/security/krb5/auto
+ * @summary New test for sun.security.krb5.principal system property.
+ * The principal can set using the system property sun.security.krb5.principal.
+ * This property is checked during login. If this property is not set,
+ * then the principal name from the configuration is used.
+ * @run main/othervm/java.security.policy=principalSystemPropTest.policy
+ * PrincipalSystemPropTest
+ */
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.login.LoginContext;
+import com.sun.security.auth.callback.TextCallbackHandler;
+
+public class PrincipalSystemPropTest {
+
+    private static final boolean PASS = Boolean.TRUE;
+    private static final boolean FAIL = Boolean.FALSE;
+    private static final String VALID_PRINCIPAL_JAAS_ENTRY =
+            "ValidPrincipalSystemPropTest";
+    private static final String INVALID_PRINCIPAL_JAAS_ENTRY =
+            "InvalidPrincipalSystemPropTest";
+    private static final String NO_PRINCIPAL_JAAS_ENTRY =
+            "NoPrincipalSystemPropTest";
+    private static final String SAME_PRINCIPAL_JAAS_ENTRY =
+            "SelfPrincipalSystemPropTest";
+    private static final String HOST = "localhost";
+    private static final String KTAB_FILENAME = "krb5.keytab.data";
+    private static final String REALM = "TEST.REALM";
+    private static final String TEST_SRC = System.getProperty("test.src", ".");
+    private static final String USER = "USER";
+    private static final String AVAILABLE_USER = "AVAILABLE";
+    private static final String USER_PASSWORD = "password";
+    private static final String FS = System.getProperty("file.separator");
+    private static final String KRB5_CONF_FILENAME = "krb5.conf";
+    private static final String JAAS_CONF_FILENAME = "jaas.conf";
+    private static final String KRBTGT_PRINCIPAL = "krbtgt/" + REALM;
+    private static final String USER_PRINCIPAL = USER + "@" + REALM;
+    private static final String AVAILABLE_USER_PRINCIPAL =
+            AVAILABLE_USER + "@" + REALM;
+
+    public static void main(String[] args) throws Exception {
+
+        setupTest();
+
+        // Expected result, Jaas Config Entry, Login Principal Expected,
+        // Principal passed through System property
+        runTest(PASS, VALID_PRINCIPAL_JAAS_ENTRY,
+                USER_PRINCIPAL, "USER@TEST.REALM");
+        runTest(PASS, VALID_PRINCIPAL_JAAS_ENTRY,
+                AVAILABLE_USER_PRINCIPAL,  null);
+        runTest(PASS, INVALID_PRINCIPAL_JAAS_ENTRY,
+                USER_PRINCIPAL, "USER@TEST.REALM");
+        runTest(FAIL, INVALID_PRINCIPAL_JAAS_ENTRY, null,  null);
+        runTest(PASS, NO_PRINCIPAL_JAAS_ENTRY,
+                USER_PRINCIPAL, "USER@TEST.REALM");
+        runTest(FAIL, NO_PRINCIPAL_JAAS_ENTRY, null, null);
+        runTest(PASS, SAME_PRINCIPAL_JAAS_ENTRY,
+                USER_PRINCIPAL, "USER@TEST.REALM");
+
+    }
+
+    private static void setupTest() {
+
+        System.setProperty("java.security.krb5.conf", KRB5_CONF_FILENAME);
+        System.setProperty("java.security.auth.login.config",
+                TEST_SRC + FS + JAAS_CONF_FILENAME);
+
+        Map<String, String> principals = new HashMap<>();
+        principals.put(USER_PRINCIPAL, USER_PASSWORD);
+        principals.put(AVAILABLE_USER_PRINCIPAL, USER_PASSWORD);
+        principals.put(KRBTGT_PRINCIPAL, null);
+        KDC.startKDC(HOST, KRB5_CONF_FILENAME, REALM, principals,
+                KTAB_FILENAME, KDC.KtabMode.APPEND);
+
+    }
+
+    private static void runTest(boolean expected, String jaasConfigEntry,
+            String expectedLoginUser, String loginUserBySysProp) {
+
+        if(loginUserBySysProp != null) {
+            System.setProperty("sun.security.krb5.principal",
+                    loginUserBySysProp);
+        } else {
+            System.clearProperty("sun.security.krb5.principal");
+        }
+
+        try {
+            LoginContext lc = new LoginContext(jaasConfigEntry,
+                    new TextCallbackHandler());
+            lc.login();
+            System.out.println(String.format(
+                    "Authentication completed with Subject '%s' ",
+                    lc.getSubject()));
+
+            if (!expected) {
+                throw new RuntimeException(
+                        "TEST FAILED - JAAS login success isn't expected");
+            }
+            if(expectedLoginUser != null && !lc.getSubject().getPrincipals()
+                    .stream().map(p -> p.getName()).filter(
+                            expectedLoginUser :: equals).findFirst()
+                            .isPresent()) {
+                throw new RuntimeException(String.format(
+                        "TEST FAILED - Login principal is not matched "
+                        + "to expected principal '%s'.", expectedLoginUser));
+            }
+            System.out.println(
+                    "TEST PASSED - JAAS login success is expected.");
+        } catch (LoginException ie) {
+            System.out.println(String.format(
+                    "Authentication failed with exception: %s",
+                    ie.getMessage()));
+            if (expected) {
+                System.out.println(
+                        "TEST FAILED - JAAS login failure isn't expected");
+                throw new RuntimeException(ie);
+            }
+            System.out.println(
+                    "TEST PASSED - JAAS login failure is expected.");
+        }
+
+    }
+
+}
diff --git a/jdk/test/sun/security/krb5/auto/principalProperty/jaas.conf b/jdk/test/sun/security/krb5/auto/principalProperty/jaas.conf
new file mode 100644
index 0000000..0a5b794
--- /dev/null
+++ b/jdk/test/sun/security/krb5/auto/principalProperty/jaas.conf
@@ -0,0 +1,34 @@
+NoPrincipalSystemPropTest {
+	com.sun.security.auth.module.Krb5LoginModule required 
+	useKeyTab = true
+  	keyTab = krb5.keytab.data
+  	doNotPrompt =true
+  	debug=true;
+};
+
+InvalidPrincipalSystemPropTest {
+  	com.sun.security.auth.module.Krb5LoginModule required 
+  	principal="UNAVAILABLE@TEST.REALM"
+  	useKeyTab = true
+  	keyTab = krb5.keytab.data
+  	doNotPrompt =true
+  	debug=true;
+};
+
+ValidPrincipalSystemPropTest {
+  	com.sun.security.auth.module.Krb5LoginModule required 
+  	principal="AVAILABLE@TEST.REALM"
+  	useKeyTab = true
+  	keyTab = krb5.keytab.data
+  	doNotPrompt =true
+  	debug=true;
+};
+
+SelfPrincipalSystemPropTest {
+  	com.sun.security.auth.module.Krb5LoginModule required 
+  	principal="USER@TEST.REALM"
+  	useKeyTab = true
+  	keyTab = krb5.keytab.data
+  	doNotPrompt =true
+  	debug=true;
+};
diff --git a/jdk/test/sun/security/krb5/auto/principalProperty/principalSystemPropTest.policy b/jdk/test/sun/security/krb5/auto/principalProperty/principalSystemPropTest.policy
new file mode 100644
index 0000000..ac9ef48
--- /dev/null
+++ b/jdk/test/sun/security/krb5/auto/principalProperty/principalSystemPropTest.policy
@@ -0,0 +1,21 @@
+grant {

+  	permission javax.security.auth.AuthPermission

+    	"createLoginContext.ValidPrincipalSystemPropTest";

+    	permission javax.security.auth.AuthPermission

+    	"createLoginContext.InvalidPrincipalSystemPropTest";

+    	permission javax.security.auth.AuthPermission

+    	"createLoginContext.NoPrincipalSystemPropTest";

+    	permission javax.security.auth.AuthPermission

+    	"createLoginContext.SelfPrincipalSystemPropTest";

+  	permission javax.security.auth.AuthPermission "doAs";

+  	permission javax.security.auth.AuthPermission "modifyPrincipals";

+  	permission javax.security.auth.AuthPermission "getSubject";

+  	permission java.util.PropertyPermission "*", "read,write";

+  	permission java.io.FilePermission "*", "read,write,delete";

+  	permission java.lang.RuntimePermission "accessDeclaredMembers";

+  	permission java.lang.reflect.ReflectPermission "suppressAccessChecks";

+  	permission java.lang.RuntimePermission "accessClassInPackage.*";

+  	permission java.net.SocketPermission "*:*", 

+  		"listen,resolve,accept,connect";

+}; 

+