提交 2441b8c1 编写于 作者: W weijun

8186831: Kerberos ignores PA-DATA with a non-null s2kparams

Reviewed-by: xuelei
上级 85ccacb3
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2017, 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
...@@ -44,6 +44,7 @@ import sun.security.krb5.internal.crypto.Des3; ...@@ -44,6 +44,7 @@ import sun.security.krb5.internal.crypto.Des3;
import sun.security.krb5.internal.crypto.Aes128; import sun.security.krb5.internal.crypto.Aes128;
import sun.security.krb5.internal.crypto.Aes256; import sun.security.krb5.internal.crypto.Aes256;
import sun.security.krb5.internal.crypto.ArcFourHmac; import sun.security.krb5.internal.crypto.ArcFourHmac;
import sun.security.krb5.internal.crypto.EType;
class CipherHelper { class CipherHelper {
...@@ -77,10 +78,6 @@ class CipherHelper { ...@@ -77,10 +78,6 @@ class CipherHelper {
private int sgnAlg, sealAlg; private int sgnAlg, sealAlg;
private byte[] keybytes; private byte[] keybytes;
// new token format from draft-ietf-krb-wg-gssapi-cfx-07
// proto is used to determine new GSS token format for "newer" etypes
private int proto = 0;
CipherHelper(EncryptionKey key) throws GSSException { CipherHelper(EncryptionKey key) throws GSSException {
etype = key.getEType(); etype = key.getEType();
keybytes = key.getBytes(); keybytes = key.getBytes();
...@@ -106,7 +103,6 @@ class CipherHelper { ...@@ -106,7 +103,6 @@ class CipherHelper {
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96: case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
sgnAlg = -1; sgnAlg = -1;
sealAlg = -1; sealAlg = -1;
proto = 1;
break; break;
default: default:
...@@ -123,8 +119,10 @@ class CipherHelper { ...@@ -123,8 +119,10 @@ class CipherHelper {
return sealAlg; return sealAlg;
} }
// new token format from draft-ietf-krb-wg-gssapi-cfx-07
// proto is used to determine new GSS token format for "newer" etypes
int getProto() { int getProto() {
return proto; return EType.isNewer(etype) ? 1 : 0;
} }
int getEType() { int getEType() {
......
/* /*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 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
...@@ -31,7 +32,7 @@ ...@@ -31,7 +32,7 @@
package sun.security.krb5.internal; package sun.security.krb5.internal;
import sun.security.krb5.KrbException; import sun.security.krb5.internal.crypto.EType;
import sun.security.util.*; import sun.security.util.*;
import sun.security.krb5.Asn1Exception; import sun.security.krb5.Asn1Exception;
import java.io.IOException; import java.io.IOException;
...@@ -207,8 +208,8 @@ public class PAData { ...@@ -207,8 +208,8 @@ public class PAData {
while (d2.data.available() > 0) { while (d2.data.available() > 0) {
DerValue value = d2.data.getDerValue(); DerValue value = d2.data.getDerValue();
ETypeInfo2 tmp = new ETypeInfo2(value); ETypeInfo2 tmp = new ETypeInfo2(value);
if (tmp.getParams() == null) { if (EType.isNewer(tmp.getEType()) || tmp.getParams() == null) {
// we don't support non-null s2kparams // we don't support non-null s2kparams for old etypes
return tmp.getEType(); return tmp.getEType();
} }
} }
...@@ -274,8 +275,9 @@ public class PAData { ...@@ -274,8 +275,9 @@ public class PAData {
while (d2.data.available() > 0) { while (d2.data.available() > 0) {
DerValue value = d2.data.getDerValue(); DerValue value = d2.data.getDerValue();
ETypeInfo2 tmp = new ETypeInfo2(value); ETypeInfo2 tmp = new ETypeInfo2(value);
if (tmp.getParams() == null && tmp.getEType() == eType) { if (tmp.getEType() == eType &&
// we don't support non-null s2kparams (EType.isNewer(eType) || tmp.getParams() == null)) {
// we don't support non-null s2kparams for old etypes
return new SaltAndParams(tmp.getSalt(), tmp.getParams()); return new SaltAndParams(tmp.getSalt(), tmp.getParams());
} }
} }
......
/* /*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2017, 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
...@@ -301,6 +301,26 @@ public abstract class EType { ...@@ -301,6 +301,26 @@ public abstract class EType {
return isSupported(eTypeConst, enabledETypes); return isSupported(eTypeConst, enabledETypes);
} }
/**
* https://tools.ietf.org/html/rfc4120#section-3.1.3:
*
* A "newer" enctype is any enctype first officially
* specified concurrently with or subsequent to the issue of this RFC.
* The enctypes DES, 3DES, or RC4 and any defined in [RFC1510] are not
* "newer" enctypes.
*
* @param eTypeConst the encryption type
* @return true if "newer"
*/
public static boolean isNewer(int eTypeConst) {
return eTypeConst != EncryptedData.ETYPE_DES_CBC_CRC &&
eTypeConst != EncryptedData.ETYPE_DES_CBC_MD4 &&
eTypeConst != EncryptedData.ETYPE_DES_CBC_MD5 &&
eTypeConst != EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD &&
eTypeConst != EncryptedData.ETYPE_ARCFOUR_HMAC &&
eTypeConst != EncryptedData.ETYPE_ARCFOUR_HMAC_EXP;
}
public static String toString(int type) { public static String toString(int type) {
switch (type) { switch (type) {
case 0: case 0:
......
/*
* Copyright (c) 2017, 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 8186831
* @summary Kerberos ignores PA-DATA with a non-null s2kparams
* @compile -XDignore.symbol.file DiffSaltParams.java
* @run main/othervm -Dsun.security.krb5.debug=true -Dsun.net.spi.nameservice.provider.1=ns,mock DiffSaltParams
*/
public class DiffSaltParams {
public static void main(String[] args) throws Exception {
OneKDC kdc = new OneKDC(null).writeJAASConf();
kdc.addPrincipal("user1", "user1pass".toCharArray(),
"hello", new byte[]{0, 0, 1, 0});
kdc.addPrincipal("user2", "user2pass".toCharArray(),
"hello", null);
kdc.addPrincipal("user3", "user3pass".toCharArray(),
null, new byte[]{0, 0, 1, 0});
kdc.addPrincipal("user4", "user4pass".toCharArray());
Context.fromUserPass("user1", "user1pass".toCharArray(), true);
Context.fromUserPass("user2", "user2pass".toCharArray(), true);
Context.fromUserPass("user3", "user3pass".toCharArray(), true);
Context.fromUserPass("user4", "user4pass".toCharArray(), true);
}
}
...@@ -149,6 +149,17 @@ public class KDC { ...@@ -149,6 +149,17 @@ public class KDC {
private TreeMap<String,PrincipalName> alias2Principals = new TreeMap<> private TreeMap<String,PrincipalName> alias2Principals = new TreeMap<>
(String.CASE_INSENSITIVE_ORDER); (String.CASE_INSENSITIVE_ORDER);
// Non default salts. Precisely, there should be different salts for
// different etypes, pretend they are the same at the moment.
private TreeMap<String,String> salts = new TreeMap<>
(String.CASE_INSENSITIVE_ORDER);
// Non default s2kparams for newer etypes. Precisely, there should be
// different s2kparams for different etypes, pretend they are the same
// at the moment.
private TreeMap<String,byte[]> s2kparamses = new TreeMap<>
(String.CASE_INSENSITIVE_ORDER);
// Realm name // Realm name
private String realm; private String realm;
// KDC // KDC
...@@ -370,10 +381,28 @@ public class KDC { ...@@ -370,10 +381,28 @@ public class KDC {
* @param pass the password for the principal * @param pass the password for the principal
*/ */
public void addPrincipal(String user, char[] pass) { public void addPrincipal(String user, char[] pass) {
addPrincipal(user, pass, null, null);
}
/**
* Adds a new principal to this realm with a given password.
* @param user the principal's name. For a service principal, use the
* form of host/f.q.d.n
* @param pass the password for the principal
* @param salt the salt, or null if a default value will be used
* @param s2kparams the s2kparams, or null if a default value will be used
*/
public void addPrincipal(String user, char[] pass, String salt, byte[] s2kparams) {
if (user.indexOf('@') < 0) { if (user.indexOf('@') < 0) {
user = user + "@" + realm; user = user + "@" + realm;
} }
passwords.put(user, pass); passwords.put(user, pass);
if (salt != null) {
salts.put(user, salt);
}
if (s2kparams != null) {
s2kparamses.put(user, s2kparams);
}
} }
/** /**
...@@ -611,6 +640,9 @@ public class KDC { ...@@ -611,6 +640,9 @@ public class KDC {
if (p.getRealmString() == null) { if (p.getRealmString() == null) {
pn = pn + "@" + getRealm(); pn = pn + "@" + getRealm();
} }
if (salts.containsKey(pn)) {
return salts.get(pn);
}
if (passwords.containsKey(pn)) { if (passwords.containsKey(pn)) {
try { try {
// Find the principal name with correct case. // Find the principal name with correct case.
...@@ -627,6 +659,29 @@ public class KDC { ...@@ -627,6 +659,29 @@ public class KDC {
return s; return s;
} }
/**
* Returns the s2kparams for the principal given the etype.
* @param p principal
* @param etype encryption type
* @return the s2kparams, might be null
*/
protected byte[] getParams(PrincipalName p, int etype) {
switch (etype) {
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
String pn = p.toString();
if (p.getRealmString() == null) {
pn = pn + "@" + getRealm();
}
if (s2kparamses.containsKey(pn)) {
return s2kparamses.get(pn);
}
return new byte[] {0, 0, 0x10, 0};
default:
return null;
}
}
/** /**
* Returns the key for a given principal of the given encryption type * Returns the key for a given principal of the given encryption type
* @param p the principal * @param p the principal
...@@ -650,7 +705,7 @@ public class KDC { ...@@ -650,7 +705,7 @@ public class KDC {
} }
} }
return new EncryptionKey(EncryptionKeyDotStringToKey( return new EncryptionKey(EncryptionKeyDotStringToKey(
getPassword(p, server), getSalt(p), null, etype), getPassword(p, server), getSalt(p), getParams(p, etype), etype),
etype, kvno); etype, kvno);
} catch (KrbException ke) { } catch (KrbException ke) {
throw ke; throw ke;
...@@ -1116,7 +1171,7 @@ public class KDC { ...@@ -1116,7 +1171,7 @@ public class KDC {
epas[i], epas[i],
epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC ? epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC ?
null : getSalt(body.cname), null : getSalt(body.cname),
null).asn1Encode()); getParams(body.cname, epas[i])).asn1Encode());
} }
boolean allOld = true; boolean allOld = true;
for (int i: eTypes) { for (int i: eTypes) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册