6849275: enhance krb5 reg tests
authorweijun
Wed, 17 Jun 2009 15:26:58 +0800
changeset 3046 dd50d75d88e6
parent 3045 cdfc2f549bbc
child 3047 30e88a671e72
child 3458 bc0aa59e8e40
6849275: enhance krb5 reg tests Reviewed-by: xuelei
jdk/test/sun/security/krb5/auto/CrossRealm.java
jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java
jdk/test/sun/security/krb5/auto/KDC.java
jdk/test/sun/security/krb5/auto/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
jdk/test/sun/security/krb5/auto/OneKDC.java
jdk/test/sun/security/krb5/auto/basic.sh
--- a/jdk/test/sun/security/krb5/auto/CrossRealm.java	Tue Jun 16 20:46:25 2009 +0800
+++ b/jdk/test/sun/security/krb5/auto/CrossRealm.java	Wed Jun 17 15:26:58 2009 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2008-2009 Sun Microsystems, Inc.  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,6 +26,7 @@
  * @bug 6706974
  * @summary Add krb5 test infrastructure
  */
+import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.security.Security;
@@ -50,17 +51,20 @@
         KDC kdc1 = KDC.create("RABBIT.HOLE");
         kdc1.addPrincipal("dummy", "bogus".toCharArray());
         kdc1.addPrincipalRandKey("krbtgt/RABBIT.HOLE");
-        kdc1.addPrincipal("krbtgt/SNAKE.HOLE", "sharedsec".toCharArray());
+        kdc1.addPrincipal("krbtgt/SNAKE.HOLE@RABBIT.HOLE",
+                "rabbit->snake".toCharArray());
 
         KDC kdc2 = KDC.create("SNAKE.HOLE");
         kdc2.addPrincipalRandKey("krbtgt/SNAKE.HOLE");
-        kdc2.addPrincipal("krbtgt/RABBIT.HOLE", "sharedsec".toCharArray());
+        kdc2.addPrincipal("krbtgt/SNAKE.HOLE@RABBIT.HOLE",
+                "rabbit->snake".toCharArray());
         kdc2.addPrincipalRandKey("host/www.snake.hole");
 
         KDC.saveConfig("krb5-localkdc.conf", kdc1, kdc2,
                 "forwardable=true",
                 "[domain_realm]",
                 ".snake.hole=SNAKE.HOLE");
+        new File("krb5-localkdc.conf").deleteOnExit();
         System.setProperty("java.security.krb5.conf", "krb5-localkdc.conf");
     }
 
@@ -68,6 +72,7 @@
         Security.setProperty("auth.login.defaultCallbackHandler", "CrossRealm");
         System.setProperty("java.security.auth.login.config", "jaas-localkdc.conf");
         System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
+        new File("jaas-localkdc.conf").deleteOnExit();
         FileOutputStream fos = new FileOutputStream("jaas-localkdc.conf");
         fos.write(("com.sun.security.jgss.krb5.initiate {\n" +
                 "    com.sun.security.auth.module.Krb5LoginModule\n" +
--- a/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java	Tue Jun 16 20:46:25 2009 +0800
+++ b/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java	Wed Jun 17 15:26:58 2009 +0800
@@ -25,7 +25,6 @@
  * @test
  * @bug 6578647
  * @summary Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock HttpNegotiateServer
  */
 
 import com.sun.net.httpserver.Headers;
@@ -40,12 +39,10 @@
 import java.io.InputStreamReader;
 import java.net.HttpURLConnection;
 import java.net.InetSocketAddress;
-import java.net.InetAddress;
 import java.net.PasswordAuthentication;
 import java.net.Proxy;
 import java.net.URL;
 import java.security.PrivilegedExceptionAction;
-import java.net.UnknownHostException;
 import java.util.HashMap;
 import java.util.Map;
 import javax.security.auth.Subject;
@@ -53,8 +50,6 @@
 import org.ietf.jgss.GSSCredential;
 import org.ietf.jgss.GSSManager;
 import sun.security.jgss.GSSUtil;
-import sun.net.spi.nameservice.NameService;
-import sun.net.spi.nameservice.NameServiceDescriptor;
 import sun.security.krb5.Config;
 
 /**
@@ -62,7 +57,7 @@
  * party uses JAAS login to get subjects and executes JGSS calls using
  * Subject.doAs.
  */
-public class HttpNegotiateServer implements NameServiceDescriptor {
+public class HttpNegotiateServer {
 
     // Two realm, web server in one, proxy server in another
     final static String REALM_WEB = "WEB.DOMAIN";
@@ -142,12 +137,12 @@
     public static void main(String[] args)
             throws Exception {
 
-        KDC kdcw = new KDC(REALM_WEB, 0, true);
+        KDC kdcw = KDC.create(REALM_WEB);
         kdcw.addPrincipal(WEB_USER, WEB_PASS);
         kdcw.addPrincipalRandKey("krbtgt/" + REALM_WEB);
         kdcw.addPrincipalRandKey("HTTP/" + WEB_HOST);
 
-        KDC kdcp = new KDC(REALM_PROXY, 0, true);
+        KDC kdcp = KDC.create(REALM_PROXY);
         kdcp.addPrincipal(PROXY_USER, PROXY_PASS);
         kdcp.addPrincipalRandKey("krbtgt/" + REALM_PROXY);
         kdcp.addPrincipalRandKey("HTTP/" + PROXY_HOST);
@@ -306,36 +301,5 @@
             }
         }
     }
-
-    @Override
-    public NameService createNameService() throws Exception {
-        NameService ns = new NameService() {
-            @Override
-            public InetAddress[] lookupAllHostAddr(String host)
-                    throws UnknownHostException {
-                // Everything is localhost
-                return new InetAddress[]{
-                    InetAddress.getByAddress(host, new byte[]{127,0,0,1})
-                };
-            }
-            @Override
-            public String getHostByAddr(byte[] addr)
-                    throws UnknownHostException {
-                // No reverse lookup
-                throw new UnknownHostException();
-            }
-        };
-        return ns;
-    }
-
-    @Override
-    public String getProviderName() {
-        return "mock";
-    }
-
-    @Override
-    public String getType() {
-        return "ns";
-    }
 }
 
--- a/jdk/test/sun/security/krb5/auto/KDC.java	Tue Jun 16 20:46:25 2009 +0800
+++ b/jdk/test/sun/security/krb5/auto/KDC.java	Wed Jun 17 15:26:58 2009 +0800
@@ -30,6 +30,8 @@
 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.*;
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.ccache.CredentialsCache;
@@ -118,14 +120,16 @@
 
     // The random generator to generate random keys (including session keys)
     private static SecureRandom secureRandom = new SecureRandom();
-    // Principal db
+    // Principal db. principal -> pass
     private Map<String,char[]> passwords = new HashMap<String,char[]>();
     // Realm name
     private String realm;
+    // KDC
+    private String kdc;
+    // Service port number
+    private int port;
     // The request/response job queue
     private BlockingQueue<Job> q = new ArrayBlockingQueue<Job>(100);
-    // Service port number
-    private int port;
     // Options
     private Map<Option,Object> options = new HashMap<Option,Object>();
 
@@ -139,33 +143,21 @@
         PREAUTH_REQUIRED,
     };
 
+    static {
+        System.setProperty("sun.net.spi.nameservice.provider.1", "ns,mock");
+    }
+
     /**
      * A standalone KDC server.
-     * @param args
-     * @throws java.lang.Exception
      */
     public static void main(String[] args) throws Exception {
-        if (args.length > 0) {
-            if (args[0].equals("-help") || args[0].equals("--help")) {
-                System.out.println("Usage:");
-                System.out.println("   java " + KDC.class + "       " +
-                        "Start KDC on port 8888");
-                return;
-            }
-        }
-        String localhost = "localhost";
-        try {
-            localhost = InetAddress.getByName(localhost)
-                    .getCanonicalHostName();
-        } catch (UnknownHostException uhe) {
-            ;   // Ignore, localhost is still "localhost"
-        }
-        KDC kdc = create("RABBIT.HOLE", 8888, false);
+        KDC kdc = create("RABBIT.HOLE", "kdc.rabbit,hole", 0, false);
         kdc.addPrincipal("dummy", "bogus".toCharArray());
         kdc.addPrincipal("foo", "bar".toCharArray());
-        kdc.addPrincipalRandKey("krbtgt/" + kdc.realm);
-        kdc.addPrincipalRandKey("server/" + localhost);
-        kdc.addPrincipalRandKey("backend/" + localhost);
+        kdc.addPrincipalRandKey("krbtgt/RABBIT.HOLE");
+        kdc.addPrincipalRandKey("server/host.rabbit.hole");
+        kdc.addPrincipalRandKey("backend/host.rabbit.hole");
+        KDC.saveConfig("krb5.conf", kdc, "forwardable = true");
     }
 
     /**
@@ -175,7 +167,7 @@
      * @throws java.io.IOException for any socket creation error
      */
     public static KDC create(String realm) throws IOException {
-        return create(realm, 0, true);
+        return create(realm, "kdc." + realm.toLowerCase(), 0, true);
     }
 
     /**
@@ -187,8 +179,8 @@
      * @return the running KDC instance
      * @throws java.io.IOException for any socket creation error
      */
-    public static KDC create(String realm, int port, boolean asDaemon) throws IOException {
-        return new KDC(realm, port, asDaemon);
+    public static KDC create(String realm, String kdc, int port, boolean asDaemon) throws IOException {
+        return new KDC(realm, kdc, port, asDaemon);
     }
 
     /**
@@ -228,10 +220,7 @@
         KeyTab ktab = KeyTab.create(tab);
         for (KDC kdc: kdcs) {
             for (String name : kdc.passwords.keySet()) {
-                if (name.equals("krbtgt/" + kdc.realm)) {
-                    continue;
-                }
-                ktab.addEntry(new PrincipalName(name + "@" + kdc.realm,
+                ktab.addEntry(new PrincipalName(name,
                         name.indexOf('/') < 0 ?
                             PrincipalName.KRB_NT_UNKNOWN :
                             PrincipalName.KRB_NT_SRV_HST),
@@ -255,6 +244,9 @@
      * @param pass the password for the principal
      */
     public void addPrincipal(String user, char[] pass) {
+        if (user.indexOf('@') < 0) {
+            user = user + "@" + realm;
+        }
         passwords.put(user, pass);
     }
 
@@ -264,7 +256,7 @@
      *        form of host/f.q.d.n
      */
     public void addPrincipalRandKey(String user) {
-        passwords.put(user, randomPassword());
+        addPrincipal(user, randomPassword());
     }
 
     /**
@@ -276,6 +268,14 @@
     }
 
     /**
+     * Returns the name of kdc
+     * @return the name of kdc
+     */
+    public String getKDC() {
+        return kdc;
+    }
+
+    /**
      * Writes a krb5.conf for one or more KDC that includes KDC locations for
      * each realm and the default realm name. You can also add extra strings
      * into the file. The method should be called like:
@@ -299,7 +299,7 @@
      *
      * [realms]
      *   REALM.NAME = {
-     *     kdc = localhost:port_number
+     *     kdc = host:port_number
      *   }
      * </pre>
      *
@@ -320,10 +320,10 @@
      *
      * [realms]
      *   KDC1.NAME = {
-     *     kdc = localhost:port1
+     *     kdc = host:port1
      *   }
      *   KDC2.NAME = {
-     *     kdc = localhost:port2
+     *     kdc = host:port2
      *   }
      * </pre>
      * @param file the name of the file to write into
@@ -372,16 +372,17 @@
      * Private constructor, cannot be called outside.
      * @param realm
      */
-    private KDC(String realm) {
+    private KDC(String realm, String kdc) {
         this.realm = realm;
+        this.kdc = kdc;
     }
 
     /**
      * A constructor that starts the KDC service also.
      */
-    protected KDC(String realm, int port, boolean asDaemon)
+    protected KDC(String realm, String kdc, int port, boolean asDaemon)
             throws IOException {
-        this(realm);
+        this(realm, kdc);
         startServer(port, asDaemon);
     }
     /**
@@ -426,7 +427,11 @@
      *         the database.
      */
     private char[] getPassword(PrincipalName p) throws KrbException {
-        char[] pass = passwords.get(p.getNameString());
+        String pn = p.toString();
+        if (p.getRealmString() == null) {
+            pn = pn + "@" + getRealm();
+        }
+        char[] pass = passwords.get(pn);
         if (pass == null) {
             throw new KrbException(Krb5.KDC_ERR_C_PRINCIPAL_UNKNOWN);
         }
@@ -434,29 +439,18 @@
     }
 
     /**
-     * Returns the salt string for the principal. For normal users, the
-     * concatenation for the realm name and the sections of the principal;
-     * for krgtgt/A@B and krbtgt/B@A, always return AB (so that inter-realm
-     * principals have the same key).
+     * Returns the salt string for the principal.
      * @param p principal
      * @return the salt
      */
     private String getSalt(PrincipalName p) {
         String[] ns = p.getNameStrings();
-        if (ns[0].equals("krbtgt") && ns.length > 1) {
-            // Shared cross-realm keys must be the same
-            if (ns[1].compareTo(realm) < 0) {
-                return ns[1] + realm;
-            } else {
-                return realm + ns[1];
-            }
-        } else {
-            String s = getRealm();
-            for (String n: p.getNameStrings()) {
-                s += n;
-            }
-            return s;
+        String s = p.getRealmString();
+        if (s == null) s = getRealm();
+        for (String n: p.getNameStrings()) {
+            s += n;
         }
+        return s;
     }
 
     /**
@@ -525,14 +519,8 @@
                         EncryptedData ed = apReq.authenticator;
                         tkt = apReq.ticket;
                         etype = tkt.encPart.getEType();
-                        EncryptionKey kkey = null;
-                        if (!tkt.realm.toString().equals(realm)) {
-                            if (tkt.sname.getNameString().equals("krbtgt/" + realm)) {
-                                kkey = keyForUser(new PrincipalName("krbtgt/" + tkt.realm.toString(), realm), etype);
-                            }
-                        } else {
-                            kkey = keyForUser(tkt.sname, etype);
-                        }
+                        tkt.sname.setRealm(tkt.realm);
+                        EncryptionKey kkey = keyForUser(tkt.sname, etype);
                         byte[] bb = tkt.encPart.decrypt(kkey, KeyUsage.KU_TICKET);
                         DerInputStream derIn = new DerInputStream(bb);
                         DerValue der = derIn.getDerValue();
@@ -857,10 +845,13 @@
     /**
      * Generates a line for a KDC to put inside [realms] of krb5.conf
      * @param kdc the KDC
-     * @return REALM.NAME = { kdc = localhost:port }
+     * @return REALM.NAME = { kdc = host:port }
      */
     private static String realmLineForKDC(KDC kdc) {
-        return String.format("  %s = {\n    kdc = localhost:%d\n  }\n", kdc.realm, kdc.port);
+        return String.format("  %s = {\n    kdc = %s:%d\n  }\n",
+                kdc.realm,
+                kdc.kdc,
+                kdc.port);
     }
 
     /**
@@ -1000,4 +991,37 @@
             }
         }
     }
+
+    public static class KDCNameService implements NameServiceDescriptor {
+        @Override
+        public NameService createNameService() throws Exception {
+            NameService ns = new NameService() {
+                @Override
+                public InetAddress[] lookupAllHostAddr(String host)
+                        throws UnknownHostException {
+                    // Everything is localhost
+                    return new InetAddress[]{
+                        InetAddress.getByAddress(host, new byte[]{127,0,0,1})
+                    };
+                }
+                @Override
+                public String getHostByAddr(byte[] addr)
+                        throws UnknownHostException {
+                    // No reverse lookup, PrincipalName use original string
+                    throw new UnknownHostException();
+                }
+            };
+            return ns;
+        }
+
+        @Override
+        public String getProviderName() {
+            return "mock";
+        }
+
+        @Override
+        public String getType() {
+            return "ns";
+        }
+    }
 }
--- a/jdk/test/sun/security/krb5/auto/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor	Tue Jun 16 20:46:25 2009 +0800
+++ b/jdk/test/sun/security/krb5/auto/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor	Wed Jun 17 15:26:58 2009 +0800
@@ -1,1 +1,1 @@
-HttpNegotiateServer
+KDC$KDCNameService
--- a/jdk/test/sun/security/krb5/auto/OneKDC.java	Tue Jun 16 20:46:25 2009 +0800
+++ b/jdk/test/sun/security/krb5/auto/OneKDC.java	Wed Jun 17 15:26:58 2009 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2008-2009 Sun Microsystems, Inc.  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
@@ -46,35 +46,22 @@
  */
 public class OneKDC extends KDC {
 
-    // The krb5 codes would try to canonicalize hostnames before creating
-    // a service principal name, so let's find out the canonicalized form
-    // of localhost first. The following codes mimic the process inside
-    // PrincipalName.java.
-    static String localhost = "localhost";
-    static {
-        try {
-            localhost = InetAddress.getByName(localhost)
-                    .getCanonicalHostName();
-        } catch (UnknownHostException uhe) {
-            ;   // Ignore, localhost is still "localhost"
-        }
-    }
     public static final String USER = "dummy";
     public static final char[] PASS = "bogus".toCharArray();
-    public static String SERVER = "server/" + localhost;
-    public static String BACKEND = "backend/" + localhost;
     public static final String KRB5_CONF = "localkdc-krb5.conf";
     public static final String KTAB = "localkdc.ktab";
     public static final String JAAS_CONF = "localkdc-jaas.conf";
     public static final String REALM = "RABBIT.HOLE";
-
+    public static String SERVER = "server/host." + REALM.toLowerCase();
+    public static String BACKEND = "backend/host." + REALM.toLowerCase();
+    public static String KDCHOST = "kdc." + REALM.toLowerCase();
     /**
      * Creates the KDC and starts it.
      * @param etype Encryption type, null if not specified
      * @throws java.lang.Exception if there's anything wrong
      */
     public OneKDC(String etype) throws Exception {
-        super(REALM, 0, true);
+        super(REALM, KDCHOST, 0, true);
         addPrincipal(USER, PASS);
         addPrincipalRandKey("krbtgt/" + REALM);
         addPrincipalRandKey(SERVER);
--- a/jdk/test/sun/security/krb5/auto/basic.sh	Tue Jun 16 20:46:25 2009 +0800
+++ b/jdk/test/sun/security/krb5/auto/basic.sh	Wed Jun 17 15:26:58 2009 +0800
@@ -1,5 +1,5 @@
 #
-# Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2008-2009 Sun Microsystems, Inc.  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
@@ -41,25 +41,31 @@
 case "$OS" in
   Windows_* )
     FS="\\"
+    SEP=";"
     ;;
   * )
     FS="/"
+    SEP=":"
     ;;
 esac
 
-${TESTJAVA}${FS}bin${FS}javac -d . \
+${TESTJAVA}${FS}bin${FS}javac -XDignore.symbol.file -d . \
     ${TESTSRC}${FS}BasicKrb5Test.java \
     ${TESTSRC}${FS}KDC.java \
     ${TESTSRC}${FS}OneKDC.java \
     ${TESTSRC}${FS}Action.java \
     ${TESTSRC}${FS}Context.java \
     || exit 10
-${TESTJAVA}${FS}bin${FS}java -Dtest.src=$TESTSRC BasicKrb5Test || exit 100
-${TESTJAVA}${FS}bin${FS}java -Dtest.src=$TESTSRC BasicKrb5Test des-cbc-crc || exit 1
-${TESTJAVA}${FS}bin${FS}java -Dtest.src=$TESTSRC BasicKrb5Test des-cbc-md5 || exit 3
-${TESTJAVA}${FS}bin${FS}java -Dtest.src=$TESTSRC BasicKrb5Test des3-cbc-sha1 || exit 16
-${TESTJAVA}${FS}bin${FS}java -Dtest.src=$TESTSRC BasicKrb5Test aes128-cts || exit 17
-${TESTJAVA}${FS}bin${FS}java -Dtest.src=$TESTSRC BasicKrb5Test aes256-cts || exit 18
-${TESTJAVA}${FS}bin${FS}java -Dtest.src=$TESTSRC BasicKrb5Test rc4-hmac || exit 23
+
+# Add $TESTSRC to classpath so that customized nameservice can be used
+J="${TESTJAVA}${FS}bin${FS}java -cp $TESTSRC${SEP}. BasicKrb5Test"
+
+$J || exit 100
+$J des-cbc-crc || exit 1
+$J des-cbc-md5 || exit 3
+$J des3-cbc-sha1 || exit 16
+$J aes128-cts || exit 17
+$J aes256-cts || exit 18
+$J rc4-hmac || exit 23
 
 exit 0