提交 58f816a4 编写于 作者: W weijun

6849275: enhance krb5 reg tests

Reviewed-by: xuelei
上级 221295e8
/*
* 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 @@ public class CrossRealm implements CallbackHandler {
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 @@ public class CrossRealm implements CallbackHandler {
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" +
......
......@@ -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.IOException;
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.GSSContext;
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 @@ import sun.security.krb5.Config;
* 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 class HttpNegotiateServer implements NameServiceDescriptor {
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 @@ public class HttpNegotiateServer 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
throw new UnknownHostException();
}
};
return ns;
}
@Override
public String getProviderName() {
return "mock";
}
@Override
public String getType() {
return "ns";
}
}
......@@ -30,6 +30,8 @@ import java.lang.reflect.Method;
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 @@ public class KDC {
// 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;
// The request/response job queue
private BlockingQueue<Job> q = new ArrayBlockingQueue<Job>(100);
// KDC
private String kdc;
// Service port number
private int port;
// The request/response job queue
private BlockingQueue<Job> q = new ArrayBlockingQueue<Job>(100);
// Options
private Map<Option,Object> options = new HashMap<Option,Object>();
......@@ -139,33 +143,21 @@ public class KDC {
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 @@ public class KDC {
* @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 @@ public class KDC {
* @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 @@ public class KDC {
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 @@ public class KDC {
* @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 @@ public class KDC {
* form of host/f.q.d.n
*/
public void addPrincipalRandKey(String user) {
passwords.put(user, randomPassword());
addPrincipal(user, randomPassword());
}
/**
......@@ -275,6 +267,14 @@ public class KDC {
return realm;
}
/**
* 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
......@@ -299,7 +299,7 @@ public class KDC {
*
* [realms]
* REALM.NAME = {
* kdc = localhost:port_number
* kdc = host:port_number
* }
* </pre>
*
......@@ -320,10 +320,10 @@ public class KDC {
*
* [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 @@ public class KDC {
* 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 @@ public class KDC {
* 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 @@ public class KDC {
}
/**
* 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 @@ public class KDC {
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 @@ public class KDC {
/**
* 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 class KDC {
}
}
}
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";
}
}
}
/*
* 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 @@ import sun.security.krb5.Config;
*/
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);
......
#
# 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 @@ OS=`uname -s`
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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册