From 60d798f0928fbb51e557c1a7ac55b53cfc70e01a Mon Sep 17 00:00:00 2001 From: Finn Date: Mon, 22 Sep 2025 21:00:39 +0200 Subject: [PATCH] - Implemented CA-Certificate sending --- .../packets/v1_0_0/beta/AuthPacket.java | 95 ++++++++++++++++--- .../protocol/side/client/ProtocolClient.java | 65 ++++++++++++- .../protocol/side/server/ProtocolServer.java | 79 ++++++++++++++- 3 files changed, 217 insertions(+), 22 deletions(-) diff --git a/src/main/java/github/openautonomousconnection/protocol/packets/v1_0_0/beta/AuthPacket.java b/src/main/java/github/openautonomousconnection/protocol/packets/v1_0_0/beta/AuthPacket.java index dd77cc7..38385ce 100644 --- a/src/main/java/github/openautonomousconnection/protocol/packets/v1_0_0/beta/AuthPacket.java +++ b/src/main/java/github/openautonomousconnection/protocol/packets/v1_0_0/beta/AuthPacket.java @@ -7,9 +7,12 @@ import github.openautonomousconnection.protocol.side.server.ConnectedProtocolCli import github.openautonomousconnection.protocol.side.server.events.ProtocolClientConnected; import github.openautonomousconnection.protocol.versions.ProtocolVersion; import github.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode; +import me.finn.unlegitlibrary.file.FileUtils; import me.finn.unlegitlibrary.network.system.packets.PacketHandler; import me.finn.unlegitlibrary.network.system.server.ConnectionHandler; +import me.finn.unlegitlibrary.network.utils.NetworkUtils; +import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -20,11 +23,50 @@ public class AuthPacket extends OACPacket { super(4, ProtocolVersion.PV_1_0_0_BETA); } + File certificatesFolder = new File("certificates"); + + File publicFolder = new File(certificatesFolder, "public"); + File privateFolder = new File(certificatesFolder, "private"); + + File privateCAFolder = new File(privateFolder, "ca"); + File privateServerFolder = new File(privateFolder, "server"); + + File publicCAFolder = new File(publicFolder, "ca"); + File publicServerFolder = new File(publicFolder, "server"); + @Override public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException { - if (ProtocolBridge.getInstance().isRunningAsServer()) + if (ProtocolBridge.getInstance().isRunningAsServer()) { objectOutputStream.writeObject(ProtocolBridge.getInstance().getProtocolVersion()); - else { + + // Read ca files + String caKey = "N/A"; + String caPem = "N/A"; + String caSrl = "N/A"; + try { + objectOutputStream.writeUTF(ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress()); + + caKey = FileUtils.readFileFull(new File( + ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().privateCAFolder, + ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress() + ".key")); + + caPem = FileUtils.readFileFull(new File( + ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().publicCAFolder, + ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress() + ".pem")); + + caSrl = FileUtils.readFileFull(new File( + ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().publicCAFolder, + ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress() + ".srl")); + } catch (Exception exception) { + ProtocolBridge.getInstance().getLogger().exception("Failed to read ca-files", exception); + setResponseCode(DNSResponseCode.RESPONSE_AUTH_FAILED); + } + + // Send ca data + objectOutputStream.writeUTF(caKey); + objectOutputStream.writeUTF(caPem); + objectOutputStream.writeUTF(caSrl); + } else { objectOutputStream.writeInt(ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getClientID()); objectOutputStream.writeObject(ProtocolBridge.getInstance().getProtocolVersion()); } @@ -40,23 +82,52 @@ public class AuthPacket extends OACPacket { if (!ProtocolBridge.getInstance().isVersionSupported(clientVersion)) { setResponseCode(DNSResponseCode.RESPONSE_AUTH_FAILED); connectionHandler.disconnect(); - } else { - setResponseCode(DNSResponseCode.RESPONSE_AUTH_SUCCESS); - ConnectedProtocolClient client = ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID); - client.setClientVersion(clientVersion); - ProtocolBridge.getInstance().getProtocolSettings().eventManager.executeEvent(new ProtocolClientConnected(client)); - } + return; + } else setResponseCode(DNSResponseCode.RESPONSE_AUTH_SUCCESS); + + + ConnectedProtocolClient client = ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID); + client.setClientVersion(clientVersion); + ProtocolBridge.getInstance().getProtocolSettings().eventManager.executeEvent(new ProtocolClientConnected(client)); } else { ProtocolVersion serverVersion = (ProtocolVersion) objectInputStream.readObject(); if (!ProtocolBridge.getInstance().isVersionSupported(serverVersion)) { setResponseCode(DNSResponseCode.RESPONSE_AUTH_FAILED); ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().disconnect(); - } else { - setResponseCode(DNSResponseCode.RESPONSE_AUTH_SUCCESS); - ProtocolBridge.getInstance().getProtocolClient().setServerVersion(serverVersion); - ProtocolBridge.getInstance().getProtocolSettings().eventManager.executeEvent(new ConnectedToProtocolServer()); + return; + } else setResponseCode(DNSResponseCode.RESPONSE_AUTH_SUCCESS); + + String caPrefix = objectInputStream.readUTF(); + + String caKey = objectInputStream.readUTF(); + String caPem = objectInputStream.readUTF(); + String caSrl = objectInputStream.readUTF(); + + if (caKey.equalsIgnoreCase("N/A") || caPem.equalsIgnoreCase("N/A") || caSrl.equalsIgnoreCase("N/A")) + setResponseCode(DNSResponseCode.RESPONSE_AUTH_FAILED); + else { + + File caPemFile = new File(ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().publicCAFolder, caPrefix + ".pem"); + File caSrlFile = new File(ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().publicCAFolder, caPrefix + ".srl"); + File caKeyFile = new File(ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().privateCAFolder, caPrefix + ".key"); + + try { + if (!caPemFile.exists()) caPemFile.createNewFile(); + if (!caSrlFile.exists()) caSrlFile.createNewFile(); + if (!caKeyFile.exists()) caKeyFile.createNewFile(); + + FileUtils.writeFile(caPemFile, caPem); + FileUtils.writeFile(caSrlFile, caKey); + FileUtils.writeFile(caKeyFile, caSrl); + } catch (Exception exception) { + ProtocolBridge.getInstance().getLogger().exception("Failed to create/save ca-files", exception); + setResponseCode(DNSResponseCode.RESPONSE_AUTH_FAILED); + } } + + ProtocolBridge.getInstance().getProtocolClient().setServerVersion(serverVersion); + ProtocolBridge.getInstance().getProtocolSettings().eventManager.executeEvent(new ConnectedToProtocolServer()); } } } diff --git a/src/main/java/github/openautonomousconnection/protocol/side/client/ProtocolClient.java b/src/main/java/github/openautonomousconnection/protocol/side/client/ProtocolClient.java index 49c4ac1..fbec1a9 100644 --- a/src/main/java/github/openautonomousconnection/protocol/side/client/ProtocolClient.java +++ b/src/main/java/github/openautonomousconnection/protocol/side/client/ProtocolClient.java @@ -9,28 +9,83 @@ import github.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain; import lombok.Getter; import me.finn.unlegitlibrary.network.system.client.NetworkClient; import me.finn.unlegitlibrary.network.system.client.events.ClientDisconnectedEvent; +import me.finn.unlegitlibrary.network.utils.NetworkUtils; import me.finn.unlegitlibrary.utils.DefaultMethodsOverrider; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; +import java.security.cert.CertificateException; public abstract class ProtocolClient extends DefaultMethodsOverrider { + public final class ClientCertificateFolderStructure { + public final File certificatesFolder; + + public final File publicFolder; + public final File privateFolder; + + public final File privateCAFolder; + public final File privateClientFolder; + + public final File publicCAFolder; + public final File publicClientFolder; + + public ClientCertificateFolderStructure() { + certificatesFolder = new File("certificates"); + + publicFolder = new File(certificatesFolder, "public"); + privateFolder = new File(certificatesFolder, "private"); + + privateCAFolder = new File(privateFolder, "ca"); + privateClientFolder = new File(privateFolder, "client"); + + publicCAFolder = new File(publicFolder, "ca"); + publicClientFolder = new File(publicFolder, "client"); + + if (!certificatesFolder.exists()) certificatesFolder.mkdirs(); + + if (!publicFolder.exists()) publicFolder.mkdirs(); + if (!privateFolder.exists()) privateFolder.mkdirs(); + + if (!privateCAFolder.exists()) privateCAFolder.mkdirs(); + if (!privateClientFolder.exists()) privateClientFolder.mkdirs(); + + if (!publicCAFolder.exists()) publicCAFolder.mkdirs(); + if (!publicClientFolder.exists()) publicClientFolder.mkdirs(); + } + } + @Getter private final NetworkClient networkClient; private ProtocolVersion serverVersion = null; + @Getter + private final ClientCertificateFolderStructure folderStructure; - public ProtocolClient(File caFolder, File certificatesClientFolder, File certificatesKeyFolder) { - if (!caFolder.exists()) caFolder.mkdirs(); - if (!certificatesClientFolder.exists()) certificatesClientFolder.mkdirs(); - if (!certificatesKeyFolder.exists()) certificatesKeyFolder.mkdirs(); + public ProtocolClient() throws CertificateException, IOException { + folderStructure = new ClientCertificateFolderStructure(); networkClient = new NetworkClient.ClientBuilder().setLogger(ProtocolBridge.getInstance().getLogger()). setHost(ProtocolBridge.getInstance().getProtocolSettings().host).setPort(ProtocolBridge.getInstance().getProtocolSettings().port). setPacketHandler(ProtocolBridge.getInstance().getProtocolSettings().packetHandler).setEventManager(ProtocolBridge.getInstance().getProtocolSettings().eventManager). - setRootCAFolder(caFolder).setClientCertificatesFolder(certificatesClientFolder, certificatesKeyFolder). + setRootCAFolder(folderStructure.publicCAFolder).setClientCertificatesFolder(folderStructure.publicClientFolder, folderStructure.privateClientFolder). build(); } + private final void checkFileExists(File folder, String prefix, String extension) throws CertificateException, IOException { + boolean found = false; + if (folder == null) throw new FileNotFoundException("Folder does not exist"); + + File[] files = folder.listFiles(); + if (files == null || files.length == 0) throw new FileNotFoundException("Folder " + folder.getAbsolutePath() + " is empty"); + + for (File file : files) { + if (!file.getName().startsWith(prefix) || !file.getName().endsWith(extension)) throw new CertificateException(file.getAbsolutePath() + " is not valid"); + if (!found) found = file.getName().equalsIgnoreCase(prefix + NetworkUtils.getPublicIPAddress() + extension); + } + + if (!found) throw new CertificateException("Missing " + prefix + NetworkUtils.getPublicIPAddress() + extension); + } + public final ProtocolVersion getServerVersion() { return serverVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : serverVersion; } diff --git a/src/main/java/github/openautonomousconnection/protocol/side/server/ProtocolServer.java b/src/main/java/github/openautonomousconnection/protocol/side/server/ProtocolServer.java index 929ad87..e9d57b6 100644 --- a/src/main/java/github/openautonomousconnection/protocol/side/server/ProtocolServer.java +++ b/src/main/java/github/openautonomousconnection/protocol/side/server/ProtocolServer.java @@ -6,27 +6,69 @@ import github.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain; import lombok.Getter; import me.finn.unlegitlibrary.file.ConfigurationManager; import me.finn.unlegitlibrary.network.system.server.NetworkServer; +import me.finn.unlegitlibrary.network.utils.NetworkUtils; import me.finn.unlegitlibrary.utils.DefaultMethodsOverrider; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; public abstract class ProtocolServer extends DefaultMethodsOverrider { + public final class ServerCertificateFolderStructure { + public final File certificatesFolder; + + public final File publicFolder; + public final File privateFolder; + + public final File privateCAFolder; + public final File privateServerFolder; + + public final File publicCAFolder; + public final File publicServerFolder; + + public ServerCertificateFolderStructure() { + certificatesFolder = new File("certificates"); + + publicFolder = new File(certificatesFolder, "public"); + privateFolder = new File(certificatesFolder, "private"); + + privateCAFolder = new File(privateFolder, "ca"); + privateServerFolder = new File(privateFolder, "server"); + + publicCAFolder = new File(publicFolder, "ca"); + publicServerFolder = new File(publicFolder, "server"); + + if (!certificatesFolder.exists()) certificatesFolder.mkdirs(); + + if (!publicFolder.exists()) publicFolder.mkdirs(); + if (!privateFolder.exists()) privateFolder.mkdirs(); + + if (!privateCAFolder.exists()) privateCAFolder.mkdirs(); + if (!privateServerFolder.exists()) privateServerFolder.mkdirs(); + + if (!publicCAFolder.exists()) publicCAFolder.mkdirs(); + if (!publicServerFolder.exists()) publicServerFolder.mkdirs(); + } + + public final String caPrefix = "ca_dns_"; + public final String certPrefix = "cert_dns_"; + } + @Getter private final NetworkServer networkServer; @Getter private List clients; + @Getter + private ServerCertificateFolderStructure folderStructure; + private final ConfigurationManager configurationManager; - public ProtocolServer(File caFolder, File certFile, File keyFile, File configFile) throws IOException { - if (!caFolder.exists()) caFolder.mkdirs(); - if (!certFile.exists() || !keyFile.exists()) throw new FileNotFoundException("Certificate or Key is missing!"); - + public ProtocolServer(File configFile) throws IOException, CertificateException { if (!configFile.exists()) configFile.createNewFile(); configurationManager = new ConfigurationManager(configFile); @@ -42,6 +84,18 @@ public abstract class ProtocolServer extends DefaultMethodsOverrider { configurationManager.saveProperties(); } + folderStructure = new ServerCertificateFolderStructure(); + + checkFileExists(folderStructure.publicCAFolder, folderStructure.caPrefix, ".pem"); + checkFileExists(folderStructure.publicCAFolder, folderStructure.caPrefix, ".srl"); + checkFileExists(folderStructure.privateCAFolder, folderStructure.caPrefix, ".key"); + + checkFileExists(folderStructure.publicServerFolder, folderStructure.certPrefix, ".crt"); + checkFileExists(folderStructure.privateServerFolder, folderStructure.certPrefix, ".key"); + + File certFile = new File(folderStructure.publicServerFolder, folderStructure.certPrefix + NetworkUtils.getPublicIPAddress() + ".crt"); + File keyFile = new File(folderStructure.privateServerFolder, folderStructure.certPrefix + NetworkUtils.getPublicIPAddress() + ".key"); + ProtocolBridge protocolBridge = ProtocolBridge.getInstance(); this.clients = new ArrayList<>(); @@ -49,10 +103,25 @@ public abstract class ProtocolServer extends DefaultMethodsOverrider { setEventManager(protocolBridge.getProtocolSettings().eventManager). setPacketHandler(protocolBridge.getProtocolSettings().packetHandler). setPort(protocolBridge.getProtocolSettings().port). - setRequireClientCertificate(false).setRootCAFolder(caFolder).setServerCertificate(certFile, keyFile). + setRequireClientCertificate(false).setRootCAFolder(folderStructure.publicCAFolder).setServerCertificate(certFile, keyFile). build(); } + private final void checkFileExists(File folder, String prefix, String extension) throws CertificateException, IOException { + boolean found = false; + if (folder == null) throw new FileNotFoundException("Folder does not exist"); + + File[] files = folder.listFiles(); + if (files == null || files.length == 0) throw new FileNotFoundException("Folder " + folder.getAbsolutePath() + " is empty"); + + for (File file : files) { + if (!file.getName().startsWith(prefix) || !file.getName().endsWith(extension)) throw new CertificateException(file.getAbsolutePath() + " is not valid"); + if (!found) found = file.getName().equalsIgnoreCase(prefix + NetworkUtils.getPublicIPAddress() + extension); + } + + if (!found) throw new CertificateException("Missing " + prefix + NetworkUtils.getPublicIPAddress() + extension); + } + public final ConnectedProtocolClient getClientByID(int clientID) { for (ConnectedProtocolClient client : clients) if (client.getConnectionHandler().getClientID() == clientID) return client;