diff --git a/core/pva/src/main/java/org/epics/pva/client/ChannelSearch.java b/core/pva/src/main/java/org/epics/pva/client/ChannelSearch.java index d9b6cf58ad..c75ce090e7 100644 --- a/core/pva/src/main/java/org/epics/pva/client/ChannelSearch.java +++ b/core/pva/src/main/java/org/epics/pva/client/ChannelSearch.java @@ -403,13 +403,15 @@ else if (count == 0) /** Issue a PVA server list request */ public void list() { + final boolean tls = !PVASettings.EPICS_PVA_TLS_KEYCHAIN.isBlank(); + // Search is invoked for new SearchedChannel(channel, now) // as well as by regular, timed search. // Lock the send buffer to avoid concurrent use. synchronized (send_buffer) { logger.log(Level.FINE, "List Request"); - sendSearch(0, null); + sendSearch(0, null, tls); } } @@ -418,13 +420,14 @@ public void list() */ private void search(final Collection channels) { + // TODO How to decide if TCP search (EPICS_PVA_NAME_SERVERS) should use TLS? + // Configure via flags in EPICS_PVA_NAME_SERVERS? + // For now setting EPICS_PVA_TLS_KEYCHAIN enables TLS for all searches, UDP and TCP + final boolean tls = !PVASettings.EPICS_PVA_TLS_KEYCHAIN.isBlank(); + // Search via TCP for (AddressInfo name_server : name_server_addresses) { - // TODO How to decide if TCP search should use TLS? - // Configure via EPICS_PVA_NAME_SERVERS? - // For now configuring EPICS_PVA_TLS_KEYCHAIN enables TLS for all name server lookups - final boolean tls = !PVASettings.EPICS_PVA_TLS_KEYCHAIN.isBlank(); final ClientTCPHandler tcp = tcp_provider.apply(name_server.getAddress(), tls); // In case of connection errors (TCP connection blocked by firewall), @@ -443,7 +446,7 @@ private void search(final Collection channels) // Use 'any' reply address since reply will be via this TCP socket final InetSocketAddress response_address = new InetSocketAddress(0); - SearchRequest.encode(true, seq, channels, response_address , buffer); + SearchRequest.encode(true, seq, channels, response_address, tls , buffer); }; tcp.submit(search_request); } @@ -462,19 +465,23 @@ private void search(final Collection channels) // match up duplicate packets and allows debugging bucket usage final int seq = current_search_bucket.get(); logger.log(Level.FINE, () -> "UDP Search Request #" + seq + " for " + channels); - sendSearch(seq, channels); + sendSearch(seq, channels, tls); } } - /** Send a 'list' or channel search out via UDP */ - private void sendSearch(final int seq, final Collection channels) + /** Send a 'list' or channel search out via UDP + * @param seq Search sequence number + * @param channels Channels to search, null for listing channels + * @param tls Use TLS? + */ + private void sendSearch(final int seq, final Collection channels, final boolean tls) { // Buffer starts out with UNICAST bit set in the search message for (AddressInfo addr : unicast_search_addresses) { send_buffer.clear(); final InetSocketAddress response = udp.getResponseAddress(addr); - SearchRequest.encode(true, seq, channels, response, send_buffer); + SearchRequest.encode(true, seq, channels, response, tls, send_buffer); send_buffer.flip(); try { @@ -492,7 +499,7 @@ private void sendSearch(final int seq, final Collection c { send_buffer.clear(); final InetSocketAddress response = udp.getResponseAddress(addr); - SearchRequest.encode(false, seq, channels, response, send_buffer); + SearchRequest.encode(false, seq, channels, response, tls, send_buffer); send_buffer.flip(); try { diff --git a/core/pva/src/main/java/org/epics/pva/client/ClientUDPHandler.java b/core/pva/src/main/java/org/epics/pva/client/ClientUDPHandler.java index 65782214eb..5c7a5feb31 100644 --- a/core/pva/src/main/java/org/epics/pva/client/ClientUDPHandler.java +++ b/core/pva/src/main/java/org/epics/pva/client/ClientUDPHandler.java @@ -284,7 +284,7 @@ private boolean handleSearchRequest(final InetSocketAddress from, final byte ver if (search.reply_required) { forward_buffer.clear(); - SearchRequest.encode(false, 0, null, search.client, forward_buffer); + SearchRequest.encode(false, 0, null, search.client, search.tls, forward_buffer); forward_buffer.flip(); logger.log(Level.FINER, () -> "Forward search to list servers to " + local_multicast + "\n" + Hexdump.toHexdump(forward_buffer)); send(forward_buffer, local_multicast); @@ -293,7 +293,7 @@ private boolean handleSearchRequest(final InetSocketAddress from, final byte ver else { forward_buffer.clear(); - SearchRequest.encode(false, search.seq, search.channels, search.client, forward_buffer); + SearchRequest.encode(false, search.seq, search.channels, search.client, search.tls, forward_buffer); forward_buffer.flip(); logger.log(Level.FINER, () -> "Forward search to " + local_multicast + "\n" + Hexdump.toHexdump(forward_buffer)); send(forward_buffer, local_multicast); diff --git a/core/pva/src/main/java/org/epics/pva/common/SearchRequest.java b/core/pva/src/main/java/org/epics/pva/common/SearchRequest.java index 6f45a85453..f95019b54b 100644 --- a/core/pva/src/main/java/org/epics/pva/common/SearchRequest.java +++ b/core/pva/src/main/java/org/epics/pva/common/SearchRequest.java @@ -17,7 +17,6 @@ import java.util.List; import java.util.logging.Level; -import org.epics.pva.PVASettings; import org.epics.pva.data.PVAAddress; import org.epics.pva.data.PVAString; @@ -183,9 +182,10 @@ else if ("tcp".equals(protocol)) * @param seq Sequence number * @param channels Channels to search, null for 'list' * @param address client's address + * @param tls Use TLS? * @param buffer Buffer into which to encode */ - public static void encode(final boolean unicast, final int seq, final Collection channels, final InetSocketAddress address, final ByteBuffer buffer) + public static void encode(final boolean unicast, final int seq, final Collection channels, final InetSocketAddress address, final boolean tls, final ByteBuffer buffer) { // Create with zero payload size, to be patched later PVAHeader.encodeMessageHeader(buffer, PVAHeader.FLAG_NONE, PVAHeader.CMD_SEARCH, 0); @@ -225,15 +225,14 @@ public static void encode(final boolean unicast, final int seq, final Collection } else { - // Only support tcp, or both tls and tcp? - // TODO pass 'use_tls' in because encode might also be called by ServerUDPHandler.forwardSearchRequest - if (PVASettings.EPICS_PVA_TLS_KEYCHAIN.isBlank()) - buffer.put((byte)1); - else + // Support both tls and tcp, or only tcp? + if (tls) { buffer.put((byte)2); PVAString.encodeString("tls", buffer); } + else + buffer.put((byte)1); PVAString.encodeString("tcp", buffer); buffer.putShort((short)channels.size()); diff --git a/core/pva/src/main/java/org/epics/pva/server/ServerUDPHandler.java b/core/pva/src/main/java/org/epics/pva/server/ServerUDPHandler.java index 9f2724eeca..98650500d2 100644 --- a/core/pva/src/main/java/org/epics/pva/server/ServerUDPHandler.java +++ b/core/pva/src/main/java/org/epics/pva/server/ServerUDPHandler.java @@ -185,7 +185,7 @@ private boolean handleSearch(final InetSocketAddress from, final byte version, { // pvlist request final boolean handled = server.handleSearchRequest(0, -1, null, search.client, search.tls, null); if (! handled && search.unicast) - PVAServer.POOL.submit(() -> forwardSearchRequest(0, null, search.client)); + PVAServer.POOL.submit(() -> forwardSearchRequest(0, null, search.client, search.tls)); } } else @@ -205,7 +205,7 @@ private boolean handleSearch(final InetSocketAddress from, final byte version, if (forward != null) { final List to_forward = forward; - PVAServer.POOL.submit(() -> forwardSearchRequest(search.seq, to_forward, search.client)); + PVAServer.POOL.submit(() -> forwardSearchRequest(search.seq, to_forward, search.client, search.tls)); } } @@ -223,8 +223,9 @@ private boolean handleSearch(final InetSocketAddress from, final byte version, * @param seq Search sequence or 0 * @param channels Channel CIDs and names or null for 'list' * @param address Client's address and port + * @param tls Use TLS or plain TCP? */ - private void forwardSearchRequest(final int seq, final Collection channels, final InetSocketAddress address) + private void forwardSearchRequest(final int seq, final Collection channels, final InetSocketAddress address, final boolean tls) { // TODO Remove the local IPv4 multicast re-send from the protocol, just use multicast from the start as with IPv6 if (local_multicast == null) @@ -232,7 +233,7 @@ private void forwardSearchRequest(final int seq, final Collection "Forward search to " + local_multicast + "\n" + Hexdump.toHexdump(send_buffer)); try