Skip to content

Commit f0cf242

Browse files
gnu-andrewRealCLanger
authored andcommitted
8370615: Improve Kerberos credentialing
Reviewed-by: abakhtin Backport-of: 52af52817f3da0189566ca435d0395be4f16c8a5
1 parent db7c263 commit f0cf242

7 files changed

Lines changed: 135 additions & 67 deletions

File tree

src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/AesDkCrypto.java

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -118,14 +118,7 @@ public byte[] stringToKey(char[] password, String salt, byte[] s2kparams)
118118
private byte[] stringToKey(char[] secret, byte[] salt, byte[] params)
119119
throws GeneralSecurityException {
120120

121-
int iter_count = DEFAULT_ITERATION_COUNT;
122-
if (params != null) {
123-
if (params.length != 4) {
124-
throw new RuntimeException("Invalid parameter to stringToKey");
125-
}
126-
iter_count = readBigEndian(params, 0, 4);
127-
}
128-
121+
int iter_count = DkCrypto.iterationCount(params, DEFAULT_ITERATION_COUNT);
129122
byte[] tmpKey = randomToKey(PBKDF2(secret, salt, iter_count,
130123
getKeySeedLength()));
131124
byte[] result = dk(tmpKey, KERBEROS_CONSTANT);
@@ -485,17 +478,4 @@ private static byte[] PBKDF2(char[] secret, byte[] salt,
485478

486479
return result;
487480
}
488-
489-
public static final int readBigEndian(byte[] data, int pos, int size) {
490-
int retVal = 0;
491-
int shifter = (size-1)*8;
492-
while (size > 0) {
493-
retVal += (data[pos] & 0xff) << shifter;
494-
shifter -= 8;
495-
pos++;
496-
size--;
497-
}
498-
return retVal;
499-
}
500-
501481
}

src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/AesSha2DkCrypto.java

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -122,14 +122,7 @@ public byte[] stringToKey(char[] password, String salt, byte[] s2kparams)
122122
private byte[] stringToKey(char[] secret, byte[] salt, byte[] params)
123123
throws GeneralSecurityException {
124124

125-
int iter_count = DEFAULT_ITERATION_COUNT;
126-
if (params != null) {
127-
if (params.length != 4) {
128-
throw new RuntimeException("Invalid parameter to stringToKey");
129-
}
130-
iter_count = readBigEndian(params, 0, 4);
131-
}
132-
125+
int iter_count = DkCrypto.iterationCount(params, DEFAULT_ITERATION_COUNT);
133126
byte[] saltp = new byte[26 + 1 + salt.length];
134127
if (keyLength == 128) {
135128
System.arraycopy(ETYPE_NAME_128, 0, saltp, 0, 26);
@@ -525,17 +518,4 @@ private static byte[] PBKDF2(char[] secret, byte[] salt,
525518

526519
return result;
527520
}
528-
529-
public static final int readBigEndian(byte[] data, int pos, int size) {
530-
int retVal = 0;
531-
int shifter = (size-1)*8;
532-
while (size > 0) {
533-
retVal += (data[pos] & 0xff) << shifter;
534-
shifter -= 8;
535-
pos++;
536-
size--;
537-
}
538-
return retVal;
539-
}
540-
541521
}

src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/DkCrypto.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
33
*/
44

55
/*
@@ -31,8 +31,8 @@
3131
package sun.security.krb5.internal.crypto.dk;
3232

3333
import javax.crypto.Cipher;
34-
import javax.crypto.Mac;
3534
import java.security.GeneralSecurityException;
35+
import java.security.InvalidAlgorithmParameterException;
3636
import java.util.Arrays;
3737
import java.io.ByteArrayInputStream;
3838
import java.io.ByteArrayOutputStream;
@@ -692,4 +692,41 @@ static byte[] charToUtf16(char[] chars) {
692692
bb.get(answer, 0, len);
693693
return answer;
694694
}
695+
696+
static int iterationCount(byte[] params, int defaultValue)
697+
throws InvalidAlgorithmParameterException {
698+
if (params == null) {
699+
return defaultValue;
700+
}
701+
if (params.length != 4) {
702+
throw new InvalidAlgorithmParameterException("Invalid params");
703+
}
704+
if (params[0] != 0 || ((params[1] & 0xff) >= 80)) {
705+
// IC should be less than 80 * 2^16. This is roughly
706+
// the same as PKCS12KeyStore's 5_000_000 limit.
707+
throw new InvalidAlgorithmParameterException(
708+
"Incoming iteration count is too big");
709+
}
710+
int iter_count = readBigEndian(params, 0, 4);
711+
if (!ALLOW_WEAK_PBKDF2_ITERATION_COUNT && iter_count < defaultValue) {
712+
throw new InvalidAlgorithmParameterException(
713+
"Incoming iteration count is too small");
714+
}
715+
return iter_count;
716+
}
717+
718+
public static final int readBigEndian(byte[] data, int pos, int size) {
719+
int retVal = 0;
720+
int shifter = (size-1)*8;
721+
while (size > 0) {
722+
retVal += (data[pos] & 0xff) << shifter;
723+
shifter -= 8;
724+
pos++;
725+
size--;
726+
}
727+
return retVal;
728+
}
729+
730+
// Only used by test
731+
public static boolean ALLOW_WEAK_PBKDF2_ITERATION_COUNT = false;
695732
}

test/jdk/sun/security/krb5/RFC396xTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -52,6 +52,7 @@ public class RFC396xTest {
5252
public static void main(String[] args) throws Exception {
5353
System.setProperty("sun.security.krb5.msinterop.des.s2kcharset",
5454
"utf-8");
55+
DkCrypto.ALLOW_WEAK_PBKDF2_ITERATION_COUNT = true;
5556
test();
5657
}
5758

test/jdk/sun/security/krb5/auto/DiffSaltParams.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -38,11 +38,11 @@ public static void main(String[] args) throws Exception {
3838

3939
OneKDC kdc = new OneKDC(null).writeJAASConf();
4040
kdc.addPrincipal("user1", "user1pass".toCharArray(),
41-
"hello", new byte[]{0, 0, 1, 0});
41+
"hello", new byte[]{0, 1, 0, 0});
4242
kdc.addPrincipal("user2", "user2pass".toCharArray(),
4343
"hello", null);
4444
kdc.addPrincipal("user3", "user3pass".toCharArray(),
45-
null, new byte[]{0, 0, 1, 0});
45+
null, new byte[]{0, 1, 0, 0});
4646
kdc.addPrincipal("user4", "user4pass".toCharArray());
4747

4848
Context.fromUserPass("user1", "user1pass".toCharArray(), true);

test/jdk/sun/security/krb5/auto/KDC.java

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -362,11 +362,12 @@ public void writeKtab(String tab, boolean append, String... names)
362362
name.indexOf('/') < 0 ?
363363
PrincipalName.KRB_NT_UNKNOWN :
364364
PrincipalName.KRB_NT_SRV_HST);
365-
ktab.addEntry(pn,
366-
getSalt(pn),
367-
pass,
368-
kvno,
369-
true);
365+
int[] etypes = EType.getDefaults("default_tkt_enctypes");
366+
EncryptionKey[] keys = new EncryptionKey[etypes.length];
367+
for (int i = 0; i < etypes.length; i++) {
368+
keys[i] = keyForUser(pn, etypes[i], false);
369+
}
370+
ktab.addEntry(pn, keys, kvno, true);
370371
} else {
371372
nativeKdc.ktadd(name, tab);
372373
}
@@ -667,10 +668,7 @@ private static EncryptionKey generateRandomKey(int eType)
667668
*/
668669
private char[] getPassword(PrincipalName p, boolean server)
669670
throws KrbException {
670-
String pn = p.toString();
671-
if (p.getRealmString() == null) {
672-
pn = pn + "@" + getRealm();
673-
}
671+
String pn = nameOf(p);
674672
char[] pass = passwords.get(pn);
675673
if (pass == null) {
676674
throw new KrbException(server?
@@ -686,10 +684,7 @@ private char[] getPassword(PrincipalName p, boolean server)
686684
* @return the salt
687685
*/
688686
protected String getSalt(PrincipalName p) {
689-
String pn = p.toString();
690-
if (p.getRealmString() == null) {
691-
pn = pn + "@" + getRealm();
692-
}
687+
String pn = nameOf(p);
693688
if (salts.containsKey(pn)) {
694689
return salts.get(pn);
695690
}
@@ -721,10 +716,7 @@ protected byte[] getParams(PrincipalName p, int etype) {
721716
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
722717
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
723718
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
724-
String pn = p.toString();
725-
if (p.getRealmString() == null) {
726-
pn = pn + "@" + getRealm();
727-
}
719+
String pn = nameOf(p);
728720
if (s2kparamses.containsKey(pn)) {
729721
return s2kparamses.get(pn);
730722
}
@@ -738,6 +730,23 @@ protected byte[] getParams(PrincipalName p, int etype) {
738730
}
739731
}
740732

733+
/**
734+
* Returns the name of a PrincipalName inside KDC dbs.
735+
* @param p the principal name
736+
* @return the name
737+
*/
738+
private String nameOf(PrincipalName p) {
739+
String pn = p.toString();
740+
if (p.getRealmString() == null) {
741+
pn = pn + "@" + getRealm();
742+
}
743+
if (pn.startsWith("krbtgt/")) {
744+
// We always register krbtgt using REALM
745+
pn = "krbtgt/" + pn.substring(7).toUpperCase(Locale.ROOT);
746+
}
747+
return pn;
748+
}
749+
741750
/**
742751
* Returns the key for a given principal of the given encryption type
743752
* @param p the principal
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8370615
27+
* @summary Improve Kerberos credentialing
28+
* @library /test/lib
29+
* @compile -XDignore.symbol.file UserIterCount.java
30+
* @run main jdk.test.lib.FileInstaller TestHosts TestHosts
31+
* @run main/othervm -Djdk.net.hosts.file=TestHosts UserIterCount
32+
*/
33+
import sun.security.krb5.PrincipalName;
34+
35+
public class UserIterCount {
36+
37+
static class MyKDC extends OneKDC {
38+
public MyKDC() throws Exception {
39+
super(null);
40+
}
41+
42+
@Override
43+
protected byte[] getParams(PrincipalName p, int etype) {
44+
if (etype == 18) {
45+
if (p.toString().startsWith(OneKDC.USER)) {
46+
return new byte[]{0, 0, 16, 01};
47+
} else {
48+
return new byte[]{0, 79, (byte)255, (byte)255};
49+
}
50+
} else {
51+
return super.getParams(p, etype);
52+
}
53+
}
54+
}
55+
56+
public static void main(String[] args) throws Exception {
57+
new MyKDC().writeJAASConf();
58+
Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
59+
Context.fromUserPass(OneKDC.USER2, OneKDC.PASS2, false);
60+
}
61+
}

0 commit comments

Comments
 (0)