8187218: GSSCredential.getRemainingLifetime() returns negative value for TTL > 24 days
Co-authored-by: Weijun Wang <weijun.wang@oracle.com> Reviewed-by: mullan
This commit is contained in:
parent
22c9d34be1
commit
b3e5409c1d
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -234,14 +234,12 @@ public class Krb5InitCredential
|
|||||||
* @exception GSSException may be thrown
|
* @exception GSSException may be thrown
|
||||||
*/
|
*/
|
||||||
public int getInitLifetime() throws GSSException {
|
public int getInitLifetime() throws GSSException {
|
||||||
int retVal = 0;
|
|
||||||
Date d = getEndTime();
|
Date d = getEndTime();
|
||||||
if (d == null) {
|
if (d == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
retVal = (int)(d.getTime() - (new Date().getTime()));
|
long retVal = d.getTime() - System.currentTimeMillis();
|
||||||
|
return (int)(retVal/1000);
|
||||||
return retVal/1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -713,10 +713,10 @@ public class KDC {
|
|||||||
/**
|
/**
|
||||||
* Returns a KerberosTime.
|
* Returns a KerberosTime.
|
||||||
*
|
*
|
||||||
* @param offset offset from NOW in milliseconds
|
* @param offset offset from NOW in seconds
|
||||||
*/
|
*/
|
||||||
private static KerberosTime timeFor(long offset) {
|
private static KerberosTime timeAfter(int offset) {
|
||||||
return new KerberosTime(new Date().getTime() + offset);
|
return new KerberosTime(new Date().getTime() + offset * 1000L);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -832,12 +832,12 @@ public class KDC {
|
|||||||
KerberosTime from = body.from;
|
KerberosTime from = body.from;
|
||||||
KerberosTime till = body.till;
|
KerberosTime till = body.till;
|
||||||
if (from == null || from.isZero()) {
|
if (from == null || from.isZero()) {
|
||||||
from = timeFor(0);
|
from = timeAfter(0);
|
||||||
}
|
}
|
||||||
if (till == null) {
|
if (till == null) {
|
||||||
throw new KrbException(Krb5.KDC_ERR_NEVER_VALID); // TODO
|
throw new KrbException(Krb5.KDC_ERR_NEVER_VALID); // TODO
|
||||||
} else if (till.isZero()) {
|
} else if (till.isZero()) {
|
||||||
till = timeFor(1000 * DEFAULT_LIFETIME);
|
till = timeAfter(DEFAULT_LIFETIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
|
boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
|
||||||
@ -863,7 +863,7 @@ public class KDC {
|
|||||||
}
|
}
|
||||||
if (body.kdcOptions.get(KDCOptions.RENEWABLE)) {
|
if (body.kdcOptions.get(KDCOptions.RENEWABLE)) {
|
||||||
bFlags[Krb5.TKT_OPTS_RENEWABLE] = true;
|
bFlags[Krb5.TKT_OPTS_RENEWABLE] = true;
|
||||||
//renew = timeFor(1000 * 3600 * 24 * 7);
|
//renew = timeAfter(3600 * 24 * 7);
|
||||||
}
|
}
|
||||||
if (body.kdcOptions.get(KDCOptions.PROXIABLE)) {
|
if (body.kdcOptions.get(KDCOptions.PROXIABLE)) {
|
||||||
bFlags[Krb5.TKT_OPTS_PROXIABLE] = true;
|
bFlags[Krb5.TKT_OPTS_PROXIABLE] = true;
|
||||||
@ -933,7 +933,7 @@ public class KDC {
|
|||||||
key,
|
key,
|
||||||
cname,
|
cname,
|
||||||
new TransitedEncoding(1, new byte[0]), // TODO
|
new TransitedEncoding(1, new byte[0]), // TODO
|
||||||
timeFor(0),
|
timeAfter(0),
|
||||||
from,
|
from,
|
||||||
till, renewTill,
|
till, renewTill,
|
||||||
body.addresses != null ? body.addresses
|
body.addresses != null ? body.addresses
|
||||||
@ -952,13 +952,13 @@ public class KDC {
|
|||||||
EncTGSRepPart enc_part = new EncTGSRepPart(
|
EncTGSRepPart enc_part = new EncTGSRepPart(
|
||||||
key,
|
key,
|
||||||
new LastReq(new LastReqEntry[] {
|
new LastReq(new LastReqEntry[] {
|
||||||
new LastReqEntry(0, timeFor(-10000))
|
new LastReqEntry(0, timeAfter(-10))
|
||||||
}),
|
}),
|
||||||
body.getNonce(), // TODO: detect replay
|
body.getNonce(), // TODO: detect replay
|
||||||
timeFor(1000 * 3600 * 24),
|
timeAfter(3600 * 24),
|
||||||
// Next 5 and last MUST be same with ticket
|
// Next 5 and last MUST be same with ticket
|
||||||
tFlags,
|
tFlags,
|
||||||
timeFor(0),
|
timeAfter(0),
|
||||||
from,
|
from,
|
||||||
till, renewTill,
|
till, renewTill,
|
||||||
service,
|
service,
|
||||||
@ -986,7 +986,7 @@ public class KDC {
|
|||||||
+ " " +ke.returnCodeMessage());
|
+ " " +ke.returnCodeMessage());
|
||||||
if (kerr == null) {
|
if (kerr == null) {
|
||||||
kerr = new KRBError(null, null, null,
|
kerr = new KRBError(null, null, null,
|
||||||
timeFor(0),
|
timeAfter(0),
|
||||||
0,
|
0,
|
||||||
ke.returnCode(),
|
ke.returnCode(),
|
||||||
body.cname,
|
body.cname,
|
||||||
@ -1059,20 +1059,21 @@ public class KDC {
|
|||||||
KerberosTime till = body.till;
|
KerberosTime till = body.till;
|
||||||
KerberosTime rtime = body.rtime;
|
KerberosTime rtime = body.rtime;
|
||||||
if (from == null || from.isZero()) {
|
if (from == null || from.isZero()) {
|
||||||
from = timeFor(0);
|
from = timeAfter(0);
|
||||||
}
|
}
|
||||||
if (till == null) {
|
if (till == null) {
|
||||||
throw new KrbException(Krb5.KDC_ERR_NEVER_VALID); // TODO
|
throw new KrbException(Krb5.KDC_ERR_NEVER_VALID); // TODO
|
||||||
} else if (till.isZero()) {
|
} else if (till.isZero()) {
|
||||||
till = timeFor(1000 * DEFAULT_LIFETIME);
|
till = timeAfter(DEFAULT_LIFETIME);
|
||||||
} else if (till.greaterThan(timeFor(24 * 3600 * 1000))) {
|
} else if (till.greaterThan(timeAfter(24 * 3600))
|
||||||
|
&& System.getProperty("test.kdc.force.till") == null) {
|
||||||
// If till is more than 1 day later, make it renewable
|
// If till is more than 1 day later, make it renewable
|
||||||
till = timeFor(1000 * DEFAULT_LIFETIME);
|
till = timeAfter(DEFAULT_LIFETIME);
|
||||||
body.kdcOptions.set(KDCOptions.RENEWABLE, true);
|
body.kdcOptions.set(KDCOptions.RENEWABLE, true);
|
||||||
if (rtime == null) rtime = till;
|
if (rtime == null) rtime = till;
|
||||||
}
|
}
|
||||||
if (rtime == null && body.kdcOptions.get(KDCOptions.RENEWABLE)) {
|
if (rtime == null && body.kdcOptions.get(KDCOptions.RENEWABLE)) {
|
||||||
rtime = timeFor(1000 * DEFAULT_RENEWTIME);
|
rtime = timeAfter(DEFAULT_RENEWTIME);
|
||||||
}
|
}
|
||||||
//body.from
|
//body.from
|
||||||
boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
|
boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
|
||||||
@ -1088,7 +1089,7 @@ public class KDC {
|
|||||||
}
|
}
|
||||||
if (body.kdcOptions.get(KDCOptions.RENEWABLE)) {
|
if (body.kdcOptions.get(KDCOptions.RENEWABLE)) {
|
||||||
bFlags[Krb5.TKT_OPTS_RENEWABLE] = true;
|
bFlags[Krb5.TKT_OPTS_RENEWABLE] = true;
|
||||||
//renew = timeFor(1000 * 3600 * 24 * 7);
|
//renew = timeAfter(3600 * 24 * 7);
|
||||||
}
|
}
|
||||||
if (body.kdcOptions.get(KDCOptions.PROXIABLE)) {
|
if (body.kdcOptions.get(KDCOptions.PROXIABLE)) {
|
||||||
bFlags[Krb5.TKT_OPTS_PROXIABLE] = true;
|
bFlags[Krb5.TKT_OPTS_PROXIABLE] = true;
|
||||||
@ -1234,7 +1235,7 @@ public class KDC {
|
|||||||
key,
|
key,
|
||||||
body.cname,
|
body.cname,
|
||||||
new TransitedEncoding(1, new byte[0]),
|
new TransitedEncoding(1, new byte[0]),
|
||||||
timeFor(0),
|
timeAfter(0),
|
||||||
from,
|
from,
|
||||||
till, rtime,
|
till, rtime,
|
||||||
body.addresses,
|
body.addresses,
|
||||||
@ -1246,13 +1247,13 @@ public class KDC {
|
|||||||
EncASRepPart enc_part = new EncASRepPart(
|
EncASRepPart enc_part = new EncASRepPart(
|
||||||
key,
|
key,
|
||||||
new LastReq(new LastReqEntry[]{
|
new LastReq(new LastReqEntry[]{
|
||||||
new LastReqEntry(0, timeFor(-10000))
|
new LastReqEntry(0, timeAfter(-10))
|
||||||
}),
|
}),
|
||||||
body.getNonce(), // TODO: detect replay?
|
body.getNonce(), // TODO: detect replay?
|
||||||
timeFor(1000 * 3600 * 24),
|
timeAfter(3600 * 24),
|
||||||
// Next 5 and last MUST be same with ticket
|
// Next 5 and last MUST be same with ticket
|
||||||
tFlags,
|
tFlags,
|
||||||
timeFor(0),
|
timeAfter(0),
|
||||||
from,
|
from,
|
||||||
till, rtime,
|
till, rtime,
|
||||||
service,
|
service,
|
||||||
@ -1314,7 +1315,7 @@ public class KDC {
|
|||||||
eData = temp.toByteArray();
|
eData = temp.toByteArray();
|
||||||
}
|
}
|
||||||
kerr = new KRBError(null, null, null,
|
kerr = new KRBError(null, null, null,
|
||||||
timeFor(0),
|
timeAfter(0),
|
||||||
0,
|
0,
|
||||||
ke.returnCode(),
|
ke.returnCode(),
|
||||||
body.cname,
|
body.cname,
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8131051 8194486
|
* @bug 8131051 8194486 8187218
|
||||||
* @summary KDC might issue a renewable ticket even if not requested
|
* @summary KDC might issue a renewable ticket even if not requested
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @compile -XDignore.symbol.file LongLife.java
|
* @compile -XDignore.symbol.file LongLife.java
|
||||||
@ -31,7 +31,12 @@
|
|||||||
* @run main/othervm -Djdk.net.hosts.file=TestHosts LongLife
|
* @run main/othervm -Djdk.net.hosts.file=TestHosts LongLife
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.ietf.jgss.GSSCredential;
|
||||||
|
import org.ietf.jgss.GSSManager;
|
||||||
import sun.security.krb5.Config;
|
import sun.security.krb5.Config;
|
||||||
|
import javax.security.auth.Subject;
|
||||||
|
import javax.security.auth.kerberos.KerberosTicket;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
|
||||||
public class LongLife {
|
public class LongLife {
|
||||||
|
|
||||||
@ -39,11 +44,53 @@ public class LongLife {
|
|||||||
|
|
||||||
OneKDC kdc = new OneKDC(null).writeJAASConf();
|
OneKDC kdc = new OneKDC(null).writeJAASConf();
|
||||||
|
|
||||||
// A lifetime 2d will make it renewable
|
test(kdc, "10h", false, 36000, false);
|
||||||
|
test(kdc, "2d", false, KDC.DEFAULT_LIFETIME, true);
|
||||||
|
test(kdc, "2d", true, 2 * 24 * 3600, false);
|
||||||
|
|
||||||
|
// 8187218: getRemainingLifetime() is negative if lifetime
|
||||||
|
// is longer than 30 days.
|
||||||
|
test(kdc, "30d", true, 30 * 24 * 3600, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test(
|
||||||
|
KDC kdc,
|
||||||
|
String ticketLifetime,
|
||||||
|
boolean forceTill, // if true, KDC will not try RENEWABLE
|
||||||
|
int expectedLifeTime,
|
||||||
|
boolean expectedRenewable) throws Exception {
|
||||||
|
|
||||||
KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
|
KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
|
||||||
"ticket_lifetime = 2d");
|
"ticket_lifetime = " + ticketLifetime);
|
||||||
Config.refresh();
|
Config.refresh();
|
||||||
|
|
||||||
Context.fromJAAS("client");
|
if (forceTill) {
|
||||||
|
System.setProperty("test.kdc.force.till", "");
|
||||||
|
} else {
|
||||||
|
System.clearProperty("test.kdc.force.till");
|
||||||
|
}
|
||||||
|
|
||||||
|
Context c = Context.fromJAAS("client");
|
||||||
|
|
||||||
|
GSSCredential cred = Subject.doAs(c.s(),
|
||||||
|
(PrivilegedExceptionAction<GSSCredential>)
|
||||||
|
()-> {
|
||||||
|
GSSManager m = GSSManager.getInstance();
|
||||||
|
return m.createCredential(GSSCredential.INITIATE_ONLY);
|
||||||
|
});
|
||||||
|
|
||||||
|
KerberosTicket tgt = c.s().getPrivateCredentials(KerberosTicket.class)
|
||||||
|
.iterator().next();
|
||||||
|
System.out.println(tgt);
|
||||||
|
|
||||||
|
int actualLifeTime = cred.getRemainingLifetime();
|
||||||
|
if (actualLifeTime < expectedLifeTime - 60
|
||||||
|
|| actualLifeTime > expectedLifeTime + 60) {
|
||||||
|
throw new Exception("actualLifeTime is " + actualLifeTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tgt.isRenewable() != expectedRenewable) {
|
||||||
|
throw new Exception("TGT's RENEWABLE flag is " + tgt.isRenewable());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user