Skip to content
Permalink
Browse files
8259707: LDAP channel binding does not work with StartTLS extension
Backport-of: 874aef4
  • Loading branch information
Alexey Bakhtin authored and Yuri Nesterenko committed Feb 24, 2021
1 parent 72d9bf5 commit a71cc1db9d8118a7f5614a7879c0028de1e71f47
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2021, 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
@@ -117,7 +117,7 @@
* @author Rosanna Lee
* @author Jagane Sundar
*/
public final class Connection implements Runnable, HandshakeCompletedListener {
public final class Connection implements Runnable {

private static final boolean debug = false;
private static final int dump = 0; // > 0 r, > 1 rw
@@ -357,7 +357,7 @@ private Socket createSocket(String host, int port, String socketFactory,
param.setEndpointIdentificationAlgorithm("LDAPS");
sslSocket.setSSLParameters(param);
}
sslSocket.addHandshakeCompletedListener(this);
setHandshakeCompletedListener(sslSocket);
if (connectTimeout > 0) {
int socketTimeout = sslSocket.getSoTimeout();
sslSocket.setSoTimeout(connectTimeout); // reuse full timeout value
@@ -653,13 +653,13 @@ void cleanup(Control[] reqCtls, boolean notifyParent) {
ldr = ldr.next;
}
}
if (isTlsConnection()) {
if (isTlsConnection() && tlsHandshakeListener != null) {
if (closureReason != null) {
CommunicationException ce = new CommunicationException();
ce.setRootCause(closureReason);
tlsHandshakeCompleted.completeExceptionally(ce);
tlsHandshakeListener.tlsHandshakeCompleted.completeExceptionally(ce);
} else {
tlsHandshakeCompleted.cancel(false);
tlsHandshakeListener.tlsHandshakeCompleted.cancel(false);
}
}
sock = null;
@@ -1027,45 +1027,62 @@ public void run() {
return buf;
}

private final CompletableFuture<X509Certificate> tlsHandshakeCompleted =
new CompletableFuture<>();

@Override
public void handshakeCompleted(HandshakeCompletedEvent event) {
try {
X509Certificate tlsServerCert = null;
Certificate[] certs;
if (event.getSocket().getUseClientMode()) {
certs = event.getPeerCertificates();
} else {
certs = event.getLocalCertificates();
}
if (certs != null && certs.length > 0 &&
certs[0] instanceof X509Certificate) {
tlsServerCert = (X509Certificate) certs[0];
}
tlsHandshakeCompleted.complete(tlsServerCert);
} catch (SSLPeerUnverifiedException ex) {
CommunicationException ce = new CommunicationException();
ce.setRootCause(closureReason);
tlsHandshakeCompleted.completeExceptionally(ex);
}
public boolean isTlsConnection() {
return (sock instanceof SSLSocket) || isUpgradedToStartTls;
}

public boolean isTlsConnection() {
return sock instanceof SSLSocket;
/*
* tlsHandshakeListener can be created for initial secure connection
* and updated by StartTLS extended operation. It is used later by LdapClient
* to create TLS Channel Binding data on the base of TLS server certificate
*/
private volatile HandshakeListener tlsHandshakeListener;

synchronized public void setHandshakeCompletedListener(SSLSocket sslSocket) {
if (tlsHandshakeListener != null)
tlsHandshakeListener.tlsHandshakeCompleted.cancel(false);

tlsHandshakeListener = new HandshakeListener();
sslSocket.addHandshakeCompletedListener(tlsHandshakeListener);
}

public X509Certificate getTlsServerCertificate()
throws SaslException {
throws SaslException {
try {
if (isTlsConnection())
return tlsHandshakeCompleted.get();
if (isTlsConnection() && tlsHandshakeListener != null)
return tlsHandshakeListener.tlsHandshakeCompleted.get();
} catch (InterruptedException iex) {
throw new SaslException("TLS Handshake Exception ", iex);
} catch (ExecutionException eex) {
throw new SaslException("TLS Handshake Exception ", eex.getCause());
}
return null;
}

private class HandshakeListener implements HandshakeCompletedListener {

private final CompletableFuture<X509Certificate> tlsHandshakeCompleted =
new CompletableFuture<>();
@Override
public void handshakeCompleted(HandshakeCompletedEvent event) {
try {
X509Certificate tlsServerCert = null;
Certificate[] certs;
if (event.getSocket().getUseClientMode()) {
certs = event.getPeerCertificates();
} else {
certs = event.getLocalCertificates();
}
if (certs != null && certs.length > 0 &&
certs[0] instanceof X509Certificate) {
tlsServerCert = (X509Certificate) certs[0];
}
tlsHandshakeCompleted.complete(tlsServerCert);
} catch (SSLPeerUnverifiedException ex) {
CommunicationException ce = new CommunicationException();
ce.setRootCause(closureReason);
tlsHandshakeCompleted.completeExceptionally(ex);
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, 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
@@ -351,6 +351,7 @@ private SSLSocket startHandshake(SSLSocketFactory factory)
System.out.println(
"StartTLS: Calling sslSocket.startHandshake");
}
ldapConnection.setHandshakeCompletedListener(sslSocket);
sslSocket.startHandshake();
if (debug) {
System.out.println(

1 comment on commit a71cc1d

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on a71cc1d Feb 24, 2021

Please sign in to comment.