8245527: LDAP Channel Binding support for Java GSS/Kerberos

Reviewed-by: dfuchs, aefimov, mullan
This commit is contained in:
Alexey Bakhtin 2020-09-25 07:26:54 +00:00
parent 37b70282b5
commit cfa3f74931
10 changed files with 542 additions and 11 deletions

View file

@ -41,6 +41,8 @@ module java.security.jgss {
jdk.security.jgss;
exports sun.security.jgss.krb5 to
jdk.security.auth;
exports sun.security.jgss.krb5.internal to
jdk.security.jgss;
exports sun.security.krb5 to
jdk.security.auth;
exports sun.security.krb5.internal to

View file

@ -36,6 +36,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import sun.security.krb5.*;
import sun.security.krb5.internal.Krb5;
import sun.security.jgss.krb5.internal.TlsChannelBindingImpl;
abstract class InitialToken extends Krb5Token {
@ -57,6 +58,7 @@ abstract class InitialToken extends Krb5Token {
private final byte[] CHECKSUM_FIRST_BYTES =
{(byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00};
private static final int CHANNEL_BINDING_AF_UNSPEC = 0;
private static final int CHANNEL_BINDING_AF_INET = 2;
private static final int CHANNEL_BINDING_AF_INET6 = 24;
private static final int CHANNEL_BINDING_AF_NULL_ADDR = 255;
@ -333,8 +335,8 @@ abstract class InitialToken extends Krb5Token {
}
}
private int getAddrType(InetAddress addr) {
int addressType = CHANNEL_BINDING_AF_NULL_ADDR;
private int getAddrType(InetAddress addr, int defValue) {
int addressType = defValue;
if (addr instanceof Inet4Address)
addressType = CHANNEL_BINDING_AF_INET;
@ -344,7 +346,7 @@ abstract class InitialToken extends Krb5Token {
}
private byte[] getAddrBytes(InetAddress addr) throws GSSException {
int addressType = getAddrType(addr);
int addressType = getAddrType(addr, CHANNEL_BINDING_AF_NULL_ADDR);
byte[] addressBytes = addr.getAddress();
if (addressBytes != null) {
switch (addressType) {
@ -375,8 +377,16 @@ abstract class InitialToken extends Krb5Token {
InetAddress acceptorAddress = channelBinding.getAcceptorAddress();
int size = 5*4;
int initiatorAddressType = getAddrType(initiatorAddress);
int acceptorAddressType = getAddrType(acceptorAddress);
// LDAP TLS Channel Binding requires CHANNEL_BINDING_AF_UNSPEC address type
// for unspecified initiator and acceptor addresses.
// CHANNEL_BINDING_AF_NULL_ADDR value should be used for unspecified address
// in all other cases.
int initiatorAddressType = getAddrType(initiatorAddress,
(channelBinding instanceof TlsChannelBindingImpl) ?
CHANNEL_BINDING_AF_UNSPEC : CHANNEL_BINDING_AF_NULL_ADDR);
int acceptorAddressType = getAddrType(acceptorAddress,
(channelBinding instanceof TlsChannelBindingImpl) ?
CHANNEL_BINDING_AF_UNSPEC : CHANNEL_BINDING_AF_NULL_ADDR);
byte[] initiatorAddressBytes = null;
if (initiatorAddress != null) {

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2020, Azul Systems, Inc. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.jgss.krb5.internal;
import org.ietf.jgss.ChannelBinding;
/**
* TLS Channel Binding wrapper class to determine internal
* tls channel binding implementation.
*/
public class TlsChannelBindingImpl extends ChannelBinding {
public TlsChannelBindingImpl(byte[] appData) {
super(appData);
}
}

View file

@ -34,6 +34,8 @@ const int TYPE_CRED_NAME = 10;
const int TYPE_CRED_TIME = 11;
const int TYPE_CRED_USAGE = 12;
static jclass tlsCBCl = NULL;
/*
* Class: sun_security_jgss_wrapper_GSSLibStub
* Method: init
@ -69,6 +71,17 @@ Java_sun_security_jgss_wrapper_GSSLibStub_init(JNIEnv *env,
failed = loadNative(libName);
(*env)->ReleaseStringUTFChars(env, jlibName, libName);
if (tlsCBCl == NULL) {
/* initialize TLS Channel Binding class wrapper */
jclass cl = (*env)->FindClass(env,
"sun/security/jgss/krb5/internal/TlsChannelBindingImpl");
if (cl == NULL) { /* exception thrown */
return JNI_FALSE;
}
tlsCBCl = (*env)->NewGlobalRef(env, cl);
}
if (!failed) {
return JNI_TRUE;
} else {
@ -154,11 +167,13 @@ void deleteGSSCB(gss_channel_bindings_t cb) {
if (cb == GSS_C_NO_CHANNEL_BINDINGS) return;
/* release initiator address */
if (cb->initiator_addrtype != GSS_C_AF_NULLADDR) {
if (cb->initiator_addrtype != GSS_C_AF_NULLADDR &&
cb->initiator_addrtype != GSS_C_AF_UNSPEC) {
resetGSSBuffer(&(cb->initiator_address));
}
/* release acceptor address */
if (cb->acceptor_addrtype != GSS_C_AF_NULLADDR) {
if (cb->acceptor_addrtype != GSS_C_AF_NULLADDR &&
cb->acceptor_addrtype != GSS_C_AF_UNSPEC) {
resetGSSBuffer(&(cb->acceptor_address));
}
/* release application data */
@ -189,9 +204,19 @@ gss_channel_bindings_t newGSSCB(JNIEnv *env, jobject jcb) {
}
// initialize addrtype in CB first
cb->initiator_addrtype = GSS_C_AF_NULLADDR;
cb->acceptor_addrtype = GSS_C_AF_NULLADDR;
// LDAP TLS Channel Binding requires GSS_C_AF_UNSPEC address type
// for unspecified initiator and acceptor addresses.
// GSS_C_AF_NULLADDR value should be used for unspecified address
// in all other cases.
if ((*env)->IsInstanceOf(env, jcb, tlsCBCl)) {
// TLS Channel Binding requires unspecified addrtype=0
cb->initiator_addrtype = GSS_C_AF_UNSPEC;
cb->acceptor_addrtype = GSS_C_AF_UNSPEC;
} else {
cb->initiator_addrtype = GSS_C_AF_NULLADDR;
cb->acceptor_addrtype = GSS_C_AF_NULLADDR;
}
// addresses needs to be initialized to empty
memset(&cb->initiator_address, 0, sizeof(cb->initiator_address));
memset(&cb->acceptor_address, 0, sizeof(cb->acceptor_address));