提交 3a370799 编写于 作者: W weijun

8005523: Unbound krb5 for TLS

Reviewed-by: xuelei
上级 f6dea072
...@@ -86,10 +86,10 @@ public class KerberosClientKeyExchange extends HandshakeMessage { ...@@ -86,10 +86,10 @@ public class KerberosClientKeyExchange extends HandshakeMessage {
public KerberosClientKeyExchange(ProtocolVersion protocolVersion, public KerberosClientKeyExchange(ProtocolVersion protocolVersion,
ProtocolVersion clientVersion, SecureRandom rand, ProtocolVersion clientVersion, SecureRandom rand,
HandshakeInStream input, SecretKey[] serverKeys) throws IOException { HandshakeInStream input, AccessControlContext acc, Object serverKeys) throws IOException {
if (impl != null) { if (impl != null) {
init(protocolVersion, clientVersion, rand, input, serverKeys); init(protocolVersion, clientVersion, rand, input, acc, serverKeys);
} else { } else {
throw new IllegalStateException("Kerberos is unavailable"); throw new IllegalStateException("Kerberos is unavailable");
} }
...@@ -126,10 +126,10 @@ public class KerberosClientKeyExchange extends HandshakeMessage { ...@@ -126,10 +126,10 @@ public class KerberosClientKeyExchange extends HandshakeMessage {
public void init(ProtocolVersion protocolVersion, public void init(ProtocolVersion protocolVersion,
ProtocolVersion clientVersion, SecureRandom rand, ProtocolVersion clientVersion, SecureRandom rand,
HandshakeInStream input, SecretKey[] serverKeys) throws IOException { HandshakeInStream input, AccessControlContext acc, Object ServiceCreds) throws IOException {
if (impl != null) { if (impl != null) {
impl.init(protocolVersion, clientVersion, rand, input, serverKeys); impl.init(protocolVersion, clientVersion, rand, input, acc, ServiceCreds);
} }
} }
......
...@@ -94,18 +94,18 @@ public final class Krb5Helper { ...@@ -94,18 +94,18 @@ public final class Krb5Helper {
/** /**
* Returns the KerberosKeys for the default server-side principal. * Returns the KerberosKeys for the default server-side principal.
*/ */
public static SecretKey[] getServerKeys(AccessControlContext acc) public static Object getServiceCreds(AccessControlContext acc)
throws LoginException { throws LoginException {
ensureAvailable(); ensureAvailable();
return proxy.getServerKeys(acc); return proxy.getServiceCreds(acc);
} }
/** /**
* Returns the server-side principal name associated with the KerberosKey. * Returns the server-side principal name associated with the KerberosKey.
*/ */
public static String getServerPrincipalName(SecretKey kerberosKey) { public static String getServerPrincipalName(Object serviceCreds) {
ensureAvailable(); ensureAvailable();
return proxy.getServerPrincipalName(kerberosKey); return proxy.getServerPrincipalName(serviceCreds);
} }
/** /**
...@@ -124,4 +124,12 @@ public final class Krb5Helper { ...@@ -124,4 +124,12 @@ public final class Krb5Helper {
ensureAvailable(); ensureAvailable();
return proxy.getServicePermission(principalName, action); return proxy.getServicePermission(principalName, action);
} }
/**
* Determines if the Subject might contain creds for princ.
*/
public static boolean isRelated(Subject subject, Principal princ) {
ensureAvailable();
return proxy.isRelated(subject, princ);
}
} }
...@@ -50,14 +50,14 @@ public interface Krb5Proxy { ...@@ -50,14 +50,14 @@ public interface Krb5Proxy {
/** /**
* Returns the KerberosKeys for the default server-side principal. * Returns the Kerberos ServiceCreds for the default server-side principal.
*/ */
SecretKey[] getServerKeys(AccessControlContext acc) throws LoginException; Object getServiceCreds(AccessControlContext acc) throws LoginException;
/** /**
* Returns the server-side principal name associated with the KerberosKey. * Returns the server-side principal name associated with the KerberosKey.
*/ */
String getServerPrincipalName(SecretKey kerberosKey); String getServerPrincipalName(Object serviceCreds);
/** /**
* Returns the hostname embedded in the principal name. * Returns the hostname embedded in the principal name.
...@@ -68,4 +68,9 @@ public interface Krb5Proxy { ...@@ -68,4 +68,9 @@ public interface Krb5Proxy {
* Returns a ServicePermission for the principal name and action. * Returns a ServicePermission for the principal name and action.
*/ */
Permission getServicePermission(String principalName, String action); Permission getServicePermission(String principalName, String action);
/**
* Determines if the Subject might contain creds for princ.
*/
boolean isRelated(Subject subject, Principal princ);
} }
...@@ -62,7 +62,7 @@ final class ServerHandshaker extends Handshaker { ...@@ -62,7 +62,7 @@ final class ServerHandshaker extends Handshaker {
private X509Certificate[] certs; private X509Certificate[] certs;
private PrivateKey privateKey; private PrivateKey privateKey;
private SecretKey[] kerberosKeys; private Object serviceCreds;
// flag to check for clientCertificateVerify message // flag to check for clientCertificateVerify message
private boolean needClientVerify = false; private boolean needClientVerify = false;
...@@ -200,7 +200,8 @@ final class ServerHandshaker extends Handshaker { ...@@ -200,7 +200,8 @@ final class ServerHandshaker extends Handshaker {
clientRequestedVersion, clientRequestedVersion,
sslContext.getSecureRandom(), sslContext.getSecureRandom(),
input, input,
kerberosKeys)); this.getAccSE(),
serviceCreds));
break; break;
case K_DHE_RSA: case K_DHE_RSA:
case K_DHE_DSS: case K_DHE_DSS:
...@@ -543,18 +544,15 @@ final class ServerHandshaker extends Handshaker { ...@@ -543,18 +544,15 @@ final class ServerHandshaker extends Handshaker {
if (subject != null) { if (subject != null) {
// Eliminate dependency on KerberosPrincipal // Eliminate dependency on KerberosPrincipal
Set<Principal> principals = if (Krb5Helper.isRelated(subject, localPrincipal)) {
subject.getPrincipals(Principal.class); if (debug != null && Debug.isOn("session"))
if (!principals.contains(localPrincipal)) { System.out.println("Subject can" +
resumingSession = false; " provide creds for princ");
if (debug != null && Debug.isOn("session")) {
System.out.println("Subject identity" +
" is not the same");
}
} else { } else {
resumingSession = false;
if (debug != null && Debug.isOn("session")) if (debug != null && Debug.isOn("session"))
System.out.println("Subject identity" + System.out.println("Subject cannot" +
" is same"); " provide creds for princ");
} }
} else { } else {
resumingSession = false; resumingSession = false;
...@@ -1316,49 +1314,51 @@ final class ServerHandshaker extends Handshaker { ...@@ -1316,49 +1314,51 @@ final class ServerHandshaker extends Handshaker {
* @return true if successful, false if not available or invalid * @return true if successful, false if not available or invalid
*/ */
private boolean setupKerberosKeys() { private boolean setupKerberosKeys() {
if (kerberosKeys != null) { if (serviceCreds != null) {
return true; return true;
} }
try { try {
final AccessControlContext acc = getAccSE(); final AccessControlContext acc = getAccSE();
kerberosKeys = AccessController.doPrivileged( serviceCreds = AccessController.doPrivileged(
// Eliminate dependency on KerberosKey // Eliminate dependency on KerberosKey
new PrivilegedExceptionAction<SecretKey[]>() { new PrivilegedExceptionAction<Object>() {
@Override @Override
public SecretKey[] run() throws Exception { public Object run() throws Exception {
// get kerberos key for the default principal // get kerberos key for the default principal
return Krb5Helper.getServerKeys(acc); return Krb5Helper.getServiceCreds(acc);
}}); }});
// check permission to access and use the secret key of the // check permission to access and use the secret key of the
// Kerberized "host" service // Kerberized "host" service
if (kerberosKeys != null && kerberosKeys.length > 0) { if (serviceCreds != null) {
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
for (SecretKey k: kerberosKeys) { System.out.println("Using Kerberos creds");
System.out.println("Using Kerberos key: " +
k);
}
} }
String serverPrincipal = String serverPrincipal =
Krb5Helper.getServerPrincipalName(kerberosKeys[0]); Krb5Helper.getServerPrincipalName(serviceCreds);
SecurityManager sm = System.getSecurityManager(); if (serverPrincipal != null) {
try { // When service is bound, we check ASAP. Otherwise,
if (sm != null) { // will check after client request is received
// Eliminate dependency on ServicePermission // in in Kerberos ClientKeyExchange
sm.checkPermission(Krb5Helper.getServicePermission( SecurityManager sm = System.getSecurityManager();
serverPrincipal, "accept"), acc); try {
} if (sm != null) {
} catch (SecurityException se) { // Eliminate dependency on ServicePermission
kerberosKeys = null; sm.checkPermission(Krb5Helper.getServicePermission(
// %%% destroy keys? or will that affect Subject? serverPrincipal, "accept"), acc);
if (debug != null && Debug.isOn("handshake")) }
System.out.println("Permission to access Kerberos" } catch (SecurityException se) {
+ " secret key denied"); serviceCreds = null;
return false; // Do not destroy keys. Will affect Subject
if (debug != null && Debug.isOn("handshake")) {
System.out.println("Permission to access Kerberos"
+ " secret key denied");
}
return false;
}
} }
} }
return (kerberosKeys != null && kerberosKeys.length > 0); return serviceCreds != null;
} catch (PrivilegedActionException e) { } catch (PrivilegedActionException e) {
// Likely exception here is LoginExceptin // Likely exception here is LoginExceptin
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
......
...@@ -33,8 +33,8 @@ import java.security.PrivilegedExceptionAction; ...@@ -33,8 +33,8 @@ import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.net.InetAddress; import java.net.InetAddress;
import java.security.PrivilegedAction;
import javax.crypto.SecretKey;
import javax.security.auth.kerberos.KerberosTicket; import javax.security.auth.kerberos.KerberosTicket;
import javax.security.auth.kerberos.KerberosKey; import javax.security.auth.kerberos.KerberosKey;
import javax.security.auth.kerberos.KerberosPrincipal; import javax.security.auth.kerberos.KerberosPrincipal;
...@@ -44,18 +44,19 @@ import sun.security.jgss.GSSCaller; ...@@ -44,18 +44,19 @@ import sun.security.jgss.GSSCaller;
import sun.security.krb5.EncryptionKey; import sun.security.krb5.EncryptionKey;
import sun.security.krb5.EncryptedData; import sun.security.krb5.EncryptedData;
import sun.security.krb5.PrincipalName; import sun.security.krb5.PrincipalName;
import sun.security.krb5.Realm;
import sun.security.krb5.internal.Ticket; import sun.security.krb5.internal.Ticket;
import sun.security.krb5.internal.EncTicketPart; import sun.security.krb5.internal.EncTicketPart;
import sun.security.krb5.internal.crypto.KeyUsage; import sun.security.krb5.internal.crypto.KeyUsage;
import sun.security.jgss.krb5.Krb5Util; import sun.security.jgss.krb5.Krb5Util;
import sun.security.jgss.krb5.ServiceCreds;
import sun.security.krb5.KrbException; import sun.security.krb5.KrbException;
import sun.security.krb5.internal.Krb5; import sun.security.krb5.internal.Krb5;
import sun.security.ssl.Debug; import sun.security.ssl.Debug;
import sun.security.ssl.HandshakeInStream; import sun.security.ssl.HandshakeInStream;
import sun.security.ssl.HandshakeOutStream; import sun.security.ssl.HandshakeOutStream;
import sun.security.ssl.Krb5Helper;
import sun.security.ssl.ProtocolVersion; import sun.security.ssl.ProtocolVersion;
/** /**
...@@ -138,16 +139,15 @@ public final class KerberosClientKeyExchangeImpl ...@@ -138,16 +139,15 @@ public final class KerberosClientKeyExchangeImpl
* @param rand random number generator used for generating random * @param rand random number generator used for generating random
* premaster secret if ticket and/or premaster verification fails * premaster secret if ticket and/or premaster verification fails
* @param input inputstream from which to get ASN.1-encoded KerberosWrapper * @param input inputstream from which to get ASN.1-encoded KerberosWrapper
* @param serverKey server's master secret key * @param acc the AccessControlContext of the handshaker
* @param serviceCreds server's creds
*/ */
@Override @Override
public void init(ProtocolVersion protocolVersion, public void init(ProtocolVersion protocolVersion,
ProtocolVersion clientVersion, ProtocolVersion clientVersion,
SecureRandom rand, HandshakeInStream input, SecretKey[] secretKeys) SecureRandom rand, HandshakeInStream input, AccessControlContext acc, Object serviceCreds)
throws IOException { throws IOException {
KerberosKey[] serverKeys = (KerberosKey[])secretKeys;
// Read ticket // Read ticket
encodedTicket = input.getBytes16(); encodedTicket = input.getBytes16();
...@@ -163,9 +163,42 @@ public final class KerberosClientKeyExchangeImpl ...@@ -163,9 +163,42 @@ public final class KerberosClientKeyExchangeImpl
EncryptedData encPart = t.encPart; EncryptedData encPart = t.encPart;
PrincipalName ticketSname = t.sname; PrincipalName ticketSname = t.sname;
Realm ticketRealm = t.sname.getRealm();
String serverPrincipal = serverKeys[0].getPrincipal().getName(); final ServiceCreds creds = (ServiceCreds)serviceCreds;
final KerberosPrincipal princ =
new KerberosPrincipal(ticketSname.toString());
// For bound service, permission already checked at setup
if (creds.getName() == null) {
SecurityManager sm = System.getSecurityManager();
try {
if (sm != null) {
// Eliminate dependency on ServicePermission
sm.checkPermission(Krb5Helper.getServicePermission(
ticketSname.toString(), "accept"), acc);
}
} catch (SecurityException se) {
serviceCreds = null;
// Do not destroy keys. Will affect Subject
if (debug != null && Debug.isOn("handshake")) {
System.out.println("Permission to access Kerberos"
+ " secret key denied");
}
throw new IOException("Kerberos service not allowedy");
}
}
KerberosKey[] serverKeys = AccessController.doPrivileged(
new PrivilegedAction<KerberosKey[]>() {
@Override
public KerberosKey[] run() {
return creds.getKKeys(princ);
}
});
if (serverKeys.length == 0) {
throw new IOException("Found no key for " + princ +
(creds.getName() == null ? "" :
(", this keytab is for " + creds.getName() + " only")));
}
/* /*
* permission to access and use the secret key of the Kerberized * permission to access and use the secret key of the Kerberized
...@@ -174,17 +207,6 @@ public final class KerberosClientKeyExchangeImpl ...@@ -174,17 +207,6 @@ public final class KerberosClientKeyExchangeImpl
* before promising the client * before promising the client
*/ */
// Check that ticket Sname matches serverPrincipal
String ticketPrinc = ticketSname.toString();
if (!ticketPrinc.equals(serverPrincipal)) {
if (debug != null && Debug.isOn("handshake"))
System.out.println("Service principal in Ticket does not"
+ " match associated principal in KerberosKey");
throw new IOException("Server principal is " +
serverPrincipal + " but ticket is for " +
ticketPrinc);
}
// See if we have the right key to decrypt the ticket to get // See if we have the right key to decrypt the ticket to get
// the session key. // the session key.
int encPartKeyType = encPart.getEType(); int encPartKeyType = encPart.getEType();
...@@ -198,9 +220,8 @@ public final class KerberosClientKeyExchangeImpl ...@@ -198,9 +220,8 @@ public final class KerberosClientKeyExchangeImpl
} }
if (dkey == null) { if (dkey == null) {
// %%% Should print string repr of etype // %%% Should print string repr of etype
throw new IOException( throw new IOException("Cannot find key of appropriate type" +
"Cannot find key of appropriate type to decrypt ticket - need etype " + " to decrypt ticket - need etype " + encPartKeyType);
encPartKeyType);
} }
EncryptionKey secretKey = new EncryptionKey( EncryptionKey secretKey = new EncryptionKey(
...@@ -222,7 +243,7 @@ public final class KerberosClientKeyExchangeImpl ...@@ -222,7 +243,7 @@ public final class KerberosClientKeyExchangeImpl
sessionKey = encTicketPart.key; sessionKey = encTicketPart.key;
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
System.out.println("server principal: " + serverPrincipal); System.out.println("server principal: " + ticketSname);
System.out.println("cname: " + encTicketPart.cname.toString()); System.out.println("cname: " + encTicketPart.cname.toString());
} }
} catch (IOException e) { } catch (IOException e) {
...@@ -382,12 +403,22 @@ public final class KerberosClientKeyExchangeImpl ...@@ -382,12 +403,22 @@ public final class KerberosClientKeyExchangeImpl
KerberosKey[] keys) throws KrbException { KerberosKey[] keys) throws KrbException {
int ktype; int ktype;
boolean etypeFound = false; boolean etypeFound = false;
// When no matched kvno is found, returns tke key of the same
// etype with the highest kvno
int kvno_found = 0;
KerberosKey key_found = null;
for (int i = 0; i < keys.length; i++) { for (int i = 0; i < keys.length; i++) {
ktype = keys[i].getKeyType(); ktype = keys[i].getKeyType();
if (etype == ktype) { if (etype == ktype) {
int kv = keys[i].getVersionNumber();
etypeFound = true; etypeFound = true;
if (versionMatches(version, keys[i].getVersionNumber())) { if (versionMatches(version, kv)) {
return keys[i]; return keys[i];
} else if (kv > kvno_found) {
key_found = keys[i];
kvno_found = kv;
} }
} }
} }
...@@ -399,18 +430,25 @@ public final class KerberosClientKeyExchangeImpl ...@@ -399,18 +430,25 @@ public final class KerberosClientKeyExchangeImpl
ktype = keys[i].getKeyType(); ktype = keys[i].getKeyType();
if (ktype == EncryptedData.ETYPE_DES_CBC_CRC || if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
ktype == EncryptedData.ETYPE_DES_CBC_MD5) { ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
int kv = keys[i].getVersionNumber();
etypeFound = true; etypeFound = true;
if (versionMatches(version, keys[i].getVersionNumber())) { if (versionMatches(version, kv)) {
return new KerberosKey(keys[i].getPrincipal(), return new KerberosKey(keys[i].getPrincipal(),
keys[i].getEncoded(), keys[i].getEncoded(),
etype, etype,
keys[i].getVersionNumber()); kv);
} else if (kv > kvno_found) {
key_found = new KerberosKey(keys[i].getPrincipal(),
keys[i].getEncoded(),
etype,
kv);
kvno_found = kv;
} }
} }
} }
} }
if (etypeFound) { if (etypeFound) {
throw new KrbException(Krb5.KRB_AP_ERR_BADKEYVER); return key_found;
} }
return null; return null;
} }
......
...@@ -28,9 +28,11 @@ package sun.security.ssl.krb5; ...@@ -28,9 +28,11 @@ package sun.security.ssl.krb5;
import java.security.AccessControlContext; import java.security.AccessControlContext;
import java.security.Permission; import java.security.Permission;
import java.security.Principal; import java.security.Principal;
import java.util.Set;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.security.auth.Subject; import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosKey; import javax.security.auth.kerberos.KerberosKey;
import javax.security.auth.kerberos.KeyTab;
import javax.security.auth.kerberos.ServicePermission; import javax.security.auth.kerberos.ServicePermission;
import javax.security.auth.login.LoginException; import javax.security.auth.login.LoginException;
...@@ -61,17 +63,16 @@ public class Krb5ProxyImpl implements Krb5Proxy { ...@@ -61,17 +63,16 @@ public class Krb5ProxyImpl implements Krb5Proxy {
} }
@Override @Override
public SecretKey[] getServerKeys(AccessControlContext acc) public Object getServiceCreds(AccessControlContext acc)
throws LoginException { throws LoginException {
ServiceCreds serviceCreds = ServiceCreds serviceCreds =
Krb5Util.getServiceCreds(GSSCaller.CALLER_SSL_SERVER, null, acc); Krb5Util.getServiceCreds(GSSCaller.CALLER_SSL_SERVER, null, acc);
return serviceCreds != null ? serviceCreds.getKKeys() : return serviceCreds;
new KerberosKey[0];
} }
@Override @Override
public String getServerPrincipalName(SecretKey kerberosKey) { public String getServerPrincipalName(Object serviceCreds) {
return ((KerberosKey)kerberosKey).getPrincipal().getName(); return ((ServiceCreds)serviceCreds).getName();
} }
@Override @Override
...@@ -100,4 +101,21 @@ public class Krb5ProxyImpl implements Krb5Proxy { ...@@ -100,4 +101,21 @@ public class Krb5ProxyImpl implements Krb5Proxy {
String action) { String action) {
return new ServicePermission(principalName, action); return new ServicePermission(principalName, action);
} }
@Override
public boolean isRelated(Subject subject, Principal princ) {
if (princ == null) return false;
Set<Principal> principals =
subject.getPrincipals(Principal.class);
if (principals.contains(princ)) {
// bound to this principal
return true;
}
for (KeyTab pc: subject.getPrivateCredentials(KeyTab.class)) {
if (!pc.isBound()) {
return true;
}
}
return false;
}
} }
...@@ -23,10 +23,11 @@ ...@@ -23,10 +23,11 @@
/* /*
* @test * @test
* @bug 6894643 6913636 * @bug 6894643 6913636 8005523
* @summary Test JSSE Kerberos ciphersuite * @summary Test JSSE Kerberos ciphersuite
* @run main/othervm SSL TLS_KRB5_WITH_RC4_128_SHA * @run main/othervm SSL TLS_KRB5_WITH_RC4_128_SHA
* @run main/othervm SSL TLS_KRB5_WITH_RC4_128_MD5 * @run main/othervm SSL TLS_KRB5_WITH_RC4_128_SHA unbound
* @run main/othervm SSL TLS_KRB5_WITH_3DES_EDE_CBC_SHA * @run main/othervm SSL TLS_KRB5_WITH_3DES_EDE_CBC_SHA
* @run main/othervm SSL TLS_KRB5_WITH_3DES_EDE_CBC_MD5 * @run main/othervm SSL TLS_KRB5_WITH_3DES_EDE_CBC_MD5
* @run main/othervm SSL TLS_KRB5_WITH_DES_CBC_SHA * @run main/othervm SSL TLS_KRB5_WITH_DES_CBC_SHA
...@@ -38,14 +39,17 @@ ...@@ -38,14 +39,17 @@
*/ */
import java.io.*; import java.io.*;
import java.net.InetAddress; import java.net.InetAddress;
import java.security.AccessControlException;
import java.security.Permission;
import javax.net.ssl.*; import javax.net.ssl.*;
import java.security.Principal; import java.security.Principal;
import java.util.Date; import java.util.Date;
import javax.security.auth.kerberos.ServicePermission;
import sun.security.jgss.GSSUtil; import sun.security.jgss.GSSUtil;
import sun.security.krb5.PrincipalName; import sun.security.krb5.PrincipalName;
import sun.security.krb5.internal.ktab.KeyTab; import sun.security.krb5.internal.ktab.KeyTab;
public class SSL { public class SSL extends SecurityManager {
private static String krb5Cipher; private static String krb5Cipher;
private static final int LOOP_LIMIT = 3; private static final int LOOP_LIMIT = 3;
...@@ -53,13 +57,32 @@ public class SSL { ...@@ -53,13 +57,32 @@ public class SSL {
private static volatile String server; private static volatile String server;
private static volatile int port; private static volatile int port;
private static String permChecks = "";
// 0-Not started, 1-Start OK, 2-Failure // 0-Not started, 1-Start OK, 2-Failure
private static volatile int serverState = 0; private static volatile int serverState = 0;
@Override
public void checkPermission(Permission perm, Object context) {
checkPermission(perm);
}
public void checkPermission(Permission perm) {
if (!(perm instanceof ServicePermission)) {
return;
}
ServicePermission p = (ServicePermission)perm;
permChecks = permChecks + p.getActions().toUpperCase().charAt(0);
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
krb5Cipher = args[0]; krb5Cipher = args[0];
boolean unbound = args.length > 1;
System.setSecurityManager(new SSL());
KDC kdc = KDC.create(OneKDC.REALM); KDC kdc = KDC.create(OneKDC.REALM);
// Run this after KDC, so our own DNS service can be started // Run this after KDC, so our own DNS service can be started
try { try {
...@@ -85,6 +108,7 @@ public class SSL { ...@@ -85,6 +108,7 @@ public class SSL {
// and use the middle one as the real key // and use the middle one as the real key
kdc.addPrincipal("host/" + server, "pass2".toCharArray()); kdc.addPrincipal("host/" + server, "pass2".toCharArray());
// JAAS config entry name ssl // JAAS config entry name ssl
System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF); System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF);
File f = new File(OneKDC.JAAS_CONF); File f = new File(OneKDC.JAAS_CONF);
...@@ -92,7 +116,9 @@ public class SSL { ...@@ -92,7 +116,9 @@ public class SSL {
fos.write(( fos.write((
"ssl {\n" + "ssl {\n" +
" com.sun.security.auth.module.Krb5LoginModule required\n" + " com.sun.security.auth.module.Krb5LoginModule required\n" +
" principal=\"host/" + server + "\"\n" + (unbound ?
" principal=*\n" :
" principal=\"host/" + server + "\"\n") +
" useKeyTab=true\n" + " useKeyTab=true\n" +
" keyTab=" + OneKDC.KTAB + "\n" + " keyTab=" + OneKDC.KTAB + "\n" +
" isInitiator=false\n" + " isInitiator=false\n" +
...@@ -103,7 +129,6 @@ public class SSL { ...@@ -103,7 +129,6 @@ public class SSL {
Context c; Context c;
final Context s = Context.fromJAAS("ssl"); final Context s = Context.fromJAAS("ssl");
// There's no keytab file when server starts.
s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
Thread server = new Thread(new Runnable() { Thread server = new Thread(new Runnable() {
...@@ -127,21 +152,6 @@ public class SSL { ...@@ -127,21 +152,6 @@ public class SSL {
throw new Exception("Server already failed"); throw new Exception("Server already failed");
} }
// Now create the keytab
/*
// Add 3 versions of keys into keytab
KeyTab ktab = KeyTab.create(OneKDC.KTAB);
PrincipalName service = new PrincipalName(
"host/" + server, PrincipalName.KRB_NT_SRV_HST);
ktab.addEntry(service, "pass1".toCharArray(), 1);
ktab.addEntry(service, "pass2".toCharArray(), 2);
ktab.addEntry(service, "pass3".toCharArray(), 3);
ktab.save();
// and use the middle one as the real key
kdc.addPrincipal("host/" + server, "pass2".toCharArray());
*/
c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID); c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID);
c.doAs(new JsseClientAction(), null); c.doAs(new JsseClientAction(), null);
...@@ -157,20 +167,22 @@ public class SSL { ...@@ -157,20 +167,22 @@ public class SSL {
c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID); c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID);
c.doAs(new JsseClientAction(), null); c.doAs(new JsseClientAction(), null);
// Revoke the old key // Permission checking check. Please note this is highly
/*Thread.sleep(2000); // implementation related.
ktab = KeyTab.create(OneKDC.KTAB); if (unbound) {
ktab.addEntry(service, "pass5".toCharArray(), 5, false); // For unbound, server does not know what name to check.
ktab.save(); // Client checks "initiate", then server gets the name
// and checks "accept". Second connection resume.
c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); if (!permChecks.equals("IA")) {
c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID); throw new Exception();
try { }
c.doAs(new JsseClientAction(), null); } else {
throw new Exception("Should fail this time."); // For bound, JAAS checks "accept" once. Server checks again,
} catch (SSLException e) { // client then checks "initiate". Second connection resume.
// Correct behavior. if (!permChecks.equals("AAI")) {
}*/ throw new Exception();
}
}
} }
// Following codes copied from // Following codes copied from
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册