Skip to content

Commit

Permalink
Server: Offer x509 auth (but don't fully handle, yet)
Browse files Browse the repository at this point in the history
  • Loading branch information
kasemir committed Aug 10, 2023
1 parent 7abb8d8 commit b4553a6
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 Oak Ridge National Laboratory.
* Copyright (c) 2019-2023 Oak Ridge National Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand All @@ -14,6 +14,7 @@
import java.util.List;

import org.epics.pva.common.CommandHandler;
import org.epics.pva.common.PVAAuth;
import org.epics.pva.common.PVAHeader;
import org.epics.pva.data.PVASize;
import org.epics.pva.data.PVAString;
Expand Down Expand Up @@ -50,10 +51,11 @@ public void handleCommand(final ClientTCPHandler tcp, final ByteBuffer buffer) t

// Support "ca" authorization, fall back to anonymouse
final ClientAuthentication authentication;
if (auth.contains("ca"))
if (auth.contains(PVAAuth.CA))
authentication = ClientAuthentication.CA;
else
authentication = ClientAuthentication.Anonymous;
// TODO PVAAuth.X509
tcp.handleValidationRequest(server_receive_buffer_size,
server_introspection_registry_max_size,
authentication);
Expand Down
5 changes: 4 additions & 1 deletion core/pva/src/main/java/org/epics/pva/common/PVAAuth.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 Oak Ridge National Laboratory.
* Copyright (c) 2019-2023 Oak Ridge National Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand All @@ -18,4 +18,7 @@ public class PVAAuth

/** CA authentication based on user name and host */
public static String CA = "ca";

/**Authentication based on 'Common Name' in certificate */
public static String X509 = "x509";
}
67 changes: 50 additions & 17 deletions core/pva/src/main/java/org/epics/pva/server/ServerAuth.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,28 @@ abstract class ServerAuth
public static ServerAuth decode(final ServerTCPHandler tcp, final ByteBuffer buffer) throws Exception
{
final String auth = PVAString.decodeString(buffer);

if (buffer.remaining() < 1)
throw new Exception("Missing authentication detail for '" + auth + "'");

final PVATypeRegistry types = tcp.getClientTypes();
final PVAData type = types.decodeType("", buffer);
PVAStructure info = null;
if (type instanceof PVAStructure)
{
info = (PVAStructure) type;
info.decode(types, buffer);
}

if (PVAAuth.CA.equals(auth))
return new CAServerAuth(tcp, buffer);
return new CAServerAuth(info);

if (info != null)
throw new Exception("Expected no authentication detail for '" + auth + "' but got " + info);

if (PVAAuth.X509.equals(auth))
return new X509ServerAuth();

return Anonymous;
}

Expand All @@ -63,20 +83,8 @@ private static class CAServerAuth extends ServerAuth
{
private String user, host;

public CAServerAuth(final ServerTCPHandler tcp, final ByteBuffer buffer) throws Exception
public CAServerAuth(final PVAStructure info) throws Exception
{
final PVATypeRegistry types = tcp.getClientTypes();

if (buffer.remaining() < 1)
throw new Exception("Missing 'ca' authentication info");

final PVAData data = types.decodeType("", buffer);
if (! (data instanceof PVAStructure))
throw new Exception("Expected structure for 'ca' authentication info, got " + data);

final PVAStructure info = (PVAStructure) data;
info.decode(types, buffer);

PVAString element = info.get("user");
if (element == null)
throw new Exception("Missing 'ca' authentication 'user', got " + info);
Expand All @@ -91,9 +99,7 @@ public CAServerAuth(final ServerTCPHandler tcp, final ByteBuffer buffer) throws
@Override
public boolean hasWriteAccess(final String channel)
{
// TODO Implement access security based on `acf` type config file
// if (! channel.contains("demo"))
// return false;
// TODO Implement access security based on `acf` type config file, checking channel for user and host
return true;
}

Expand All @@ -103,4 +109,31 @@ public String toString()
return "ca(" + user + "@" + host + ")";
}
}


private static class X509ServerAuth extends ServerAuth
{
private String user, host;

public X509ServerAuth() throws Exception
{
// TODO Get user from certificate, host from TCP??
user = "TODO";
host = "TODO";
}

@Override
public boolean hasWriteAccess(final String channel)
{
// TODO Implement access security based on `acf` type config file, checking channel for user and host
return true;
}

@Override
public String toString()
{
return "x509(" + user + "@" + host + ")";
}
}

}
26 changes: 17 additions & 9 deletions core/pva/src/main/java/org/epics/pva/server/ServerTCPHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
import java.nio.ByteBuffer;
import java.util.logging.Level;

import javax.net.ssl.SSLSocket;

import org.epics.pva.common.CommandHandlers;
import org.epics.pva.common.PVAAuth;
import org.epics.pva.common.PVAHeader;
import org.epics.pva.common.RequestEncoder;
import org.epics.pva.common.SearchResponse;
Expand Down Expand Up @@ -78,23 +81,28 @@ public ServerTCPHandler(final PVAServer server, final Socket client) throws Exce
submit((version, buffer) ->
{
logger.log(Level.FINE, () -> "Sending Validation Request");
PVAHeader.encodeMessageHeader(buffer,
PVAHeader.FLAG_SERVER,
PVAHeader.CMD_CONNECTION_VALIDATION, 4+2+1+PVAString.getEncodedSize("anonymous") + PVAString.getEncodedSize("ca"));

final int size_offset = buffer.position() + PVAHeader.HEADER_OFFSET_PAYLOAD_SIZE;
PVAHeader.encodeMessageHeader(buffer, PVAHeader.FLAG_SERVER, PVAHeader.CMD_CONNECTION_VALIDATION, 4+2+1);
final int payload_start = buffer.position();

// int serverReceiveBufferSize;
buffer.putInt(receive_buffer.capacity());

// short serverIntrospectionRegistryMaxSize;
buffer.putShort(Short.MAX_VALUE);

// string[] authNZ;
PVASize.encodeSize(1, buffer);
// On secure connection server supports "x509"
boolean support_x509 = (client instanceof SSLSocket);

// string[] authNZ; listing most secure at end
PVASize.encodeSize(support_x509 ? 3 : 2, buffer);
PVAString.encodeString(PVAAuth.ANONYMOUS, buffer);
PVAString.encodeString(PVAAuth.CA, buffer);
if (support_x509)
PVAString.encodeString(PVAAuth.X509, buffer);

// TODO ServerAuthentication
PVAString.encodeString("ca", buffer);
PVAString.encodeString("anonymous", buffer);
// TODO "x509"
buffer.putInt(size_offset, buffer.position() - payload_start);
});
}

Expand Down

0 comments on commit b4553a6

Please sign in to comment.