提交 a508d7f8 编写于 作者: P pkoppula

8187218: GSSCredential.getRemainingLifetime() returns negative value for TTL > 24 days.

8131051: KDC might issue a renewable ticket even if not requested
Reviewed-by: weijun
上级 ca251265
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -234,14 +234,13 @@ public class Krb5InitCredential
* @exception GSSException may be thrown
*/
public int getInitLifetime() throws GSSException {
int retVal = 0;
Date d = getEndTime();
if (d == null) {
return 0;
}
retVal = (int)(d.getTime() - (new Date().getTime()));
return retVal/1000;
long retVal = d.getTime() - System.currentTimeMillis();
return (int)(retVal/1000);
}
/**
......
......@@ -75,10 +75,11 @@ abstract class KrbKdcRep {
}
}
// XXX Can renew a ticket but not ask for a renewable renewed ticket
// See impl of Credentials.renew().
if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE) !=
rep.encKDCRepPart.flags.get(KDCOptions.RENEWABLE)) {
// Reply to a renewable request should be renewable, but if request does
// not contain renewable, KDC is free to issue a renewable ticket (for
// example, if ticket_lifetime is too big).
if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE) &&
!rep.encKDCRepPart.flags.get(KDCOptions.RENEWABLE)) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
if ((req.reqBody.from == null) || req.reqBody.from.isZero())
......
/*
* Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2018, 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
......@@ -28,6 +28,10 @@ import java.net.*;
import java.io.*;
import java.lang.reflect.Method;
import java.security.SecureRandom;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAmount;
import java.time.temporal.TemporalUnit;
import java.util.*;
import java.util.concurrent.*;
......@@ -41,6 +45,8 @@ import sun.security.krb5.internal.ktab.KeyTab;
import sun.security.util.DerInputStream;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A KDC server.
......@@ -123,6 +129,9 @@ public class KDC {
// Under the hood.
public static final int DEFAULT_LIFETIME = 39600;
public static final int DEFAULT_RENEWTIME = 86400;
// The random generator to generate random keys (including session keys)
private static SecureRandom secureRandom = new SecureRandom();
......@@ -619,6 +628,15 @@ public class KDC {
}
}
/**
* Returns a KerberosTime.
*
* @param offset offset from NOW in seconds
*/
private static KerberosTime timeAfter(int offset) {
return new KerberosTime(new Date().getTime() + offset * 1000L);
}
/**
* Processes an incoming request and generates a response.
* @param in the request
......@@ -919,11 +937,27 @@ public class KDC {
EncryptionKey key = generateRandomKey(eType);
// Check time, TODO
KerberosTime till = body.till;
KerberosTime rtime = body.rtime;
if (till == null) {
throw new KrbException(Krb5.KDC_ERR_NEVER_VALID); // TODO
} else if (till.isZero()) {
till = new KerberosTime(new Date().getTime() + 1000 * 3600 * 11);
String ttlsVal = System.getProperty("test.kdc.ttl.value");
if (ttlsVal != null){
till = timeAfter(duration(ttlsVal));
if (till.greaterThan(timeAfter(24 * 3600)) &&
(System.getProperty("test.kdc.force.till") == null)) {
till = timeAfter(DEFAULT_LIFETIME);
body.kdcOptions.set(KDCOptions.RENEWABLE, true);
}
} else {
till = timeAfter(DEFAULT_LIFETIME);
}
}
if (rtime == null && body.kdcOptions.get(KDCOptions.RENEWABLE)) {
rtime = timeAfter(DEFAULT_RENEWTIME);
}
//body.from
boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
if (body.kdcOptions.get(KDCOptions.FORWARDABLE)) {
......@@ -1079,7 +1113,7 @@ public class KDC {
new TransitedEncoding(1, new byte[0]),
new KerberosTime(new Date()),
body.from,
till, body.rtime,
till, rtime,
body.addresses,
null);
Ticket t = new Ticket(
......@@ -1097,7 +1131,7 @@ public class KDC {
tFlags,
new KerberosTime(new Date()),
body.from,
till, body.rtime,
till, rtime,
service,
body.addresses
);
......@@ -1168,6 +1202,72 @@ public class KDC {
}
}
/**
* Translates a duration value into seconds.
*
* The format can be one of "h:m[:s]", "NdNhNmNs", and "N". See
* http://web.mit.edu/kerberos/krb5-devel/doc/basic/date_format.html#duration
* for definitions.
*
* @param s the string duration
* @return time in seconds
* @throw KrbException if format is illegal
*/
public static int duration(String s) throws KrbException {
if (s.isEmpty()) {
throw new KrbException("Duration cannot be empty");
}
// N
if (s.matches("\\d+")) {
return Integer.parseInt(s);
}
// h:m[:s]
Matcher m = Pattern.compile("(\\d+):(\\d+)(:(\\d+))?").matcher(s);
if (m.matches()) {
int hr = Integer.parseInt(m.group(1));
int min = Integer.parseInt(m.group(2));
if (min >= 60) {
throw new KrbException("Illegal duration format " + s);
}
int result = hr * 3600 + min * 60;
if (m.group(4) != null) {
int sec = Integer.parseInt(m.group(4));
if (sec >= 60) {
throw new KrbException("Illegal duration format " + s);
}
result += sec;
}
return result;
}
// NdNhNmNs
// 120m allowed. Maybe 1h120m is not good, but still allowed
m = Pattern.compile(
"((\\d+)d)?\\s*((\\d+)h)?\\s*((\\d+)m)?\\s*((\\d+)s)?",
Pattern.CASE_INSENSITIVE).matcher(s);
if (m.matches()) {
int result = 0;
if (m.group(2) != null) {
result += 86400 * Integer.parseInt(m.group(2));
}
if (m.group(4) != null) {
result += 3600 * Integer.parseInt(m.group(4));
}
if (m.group(6) != null) {
result += 60 * Integer.parseInt(m.group(6));
}
if (m.group(8) != null) {
result += Integer.parseInt(m.group(8));
}
return result;
}
throw new KrbException("Illegal duration format " + s);
}
/**
* Generates a line for a KDC to put inside [realms] of krb5.conf
* @return REALM.NAME = { kdc = host:port etc }
......
/*
* Copyright (c) 2018, 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 8131051 8187218
* @summary KDC might issue a renewable ticket even if not requested
* @compile -XDignore.symbol.file LongLife.java
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock LongLife
*/
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSManager;
import sun.security.krb5.Config;
import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosTicket;
import java.security.PrivilegedExceptionAction;
public class LongLife {
public static void main(String[] args) throws Exception {
OneKDC kdc = new OneKDC(null).writeJAASConf();
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);
Config.refresh();
System.setProperty("test.kdc.ttl.value", ticketLifetime);
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 +
" ExpectedLifeTime is " + expectedLifeTime);
}
if (tgt.isRenewable() != expectedRenewable) {
throw new Exception("TGT's RENEWABLE flag is " + tgt.isRenewable());
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册