Security fix
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>org.openautonomousconnection</groupId>
|
<groupId>org.openautonomousconnection</groupId>
|
||||||
<artifactId>Protocol</artifactId>
|
<artifactId>Protocol</artifactId>
|
||||||
<version>1.0.0-BETA.7.2</version>
|
<version>1.0.0-BETA.7.3</version>
|
||||||
<organization>
|
<organization>
|
||||||
<name>Open Autonomous Connection</name>
|
<name>Open Autonomous Connection</name>
|
||||||
<url>https://open-autonomous-connection.org/</url>
|
<url>https://open-autonomous-connection.org/</url>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.openautonomousconnection.protocol.side.server.CustomConnectedClient;
|
|||||||
import org.openautonomousconnection.protocol.side.server.events.S_CustomClientConnectedEvent;
|
import org.openautonomousconnection.protocol.side.server.events.S_CustomClientConnectedEvent;
|
||||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
|
||||||
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.TOFUFeedback;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -59,9 +60,7 @@ public final class AuthPacket extends OACPacket {
|
|||||||
if (protocolBridge.isRunningAsINSServer()) {
|
if (protocolBridge.isRunningAsINSServer()) {
|
||||||
objectOutputStream.writeUTF(protocolBridge.getProtocolVersion().name());
|
objectOutputStream.writeUTF(protocolBridge.getProtocolVersion().name());
|
||||||
|
|
||||||
String caKey = "N/A";
|
|
||||||
String caPem = "N/A";
|
String caPem = "N/A";
|
||||||
String caSrl = "N/A";
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String caPrefix = protocolBridge.getProtocolServer().getFolderStructure().getCaPrefix()
|
String caPrefix = protocolBridge.getProtocolServer().getFolderStructure().getCaPrefix()
|
||||||
@@ -69,32 +68,19 @@ public final class AuthPacket extends OACPacket {
|
|||||||
|
|
||||||
objectOutputStream.writeUTF(caPrefix);
|
objectOutputStream.writeUTF(caPrefix);
|
||||||
|
|
||||||
caKey = FileUtils.readFileFull(new File(
|
|
||||||
protocolBridge.getProtocolServer().getFolderStructure().privateCAFolder,
|
|
||||||
caPrefix + ".key"));
|
|
||||||
|
|
||||||
caPem = FileUtils.readFileFull(new File(
|
caPem = FileUtils.readFileFull(new File(
|
||||||
protocolBridge.getProtocolServer().getFolderStructure().publicCAFolder,
|
protocolBridge.getProtocolServer().getFolderStructure().publicCAFolder,
|
||||||
caPrefix + ".pem"));
|
caPrefix + ".pem"));
|
||||||
|
|
||||||
caSrl = FileUtils.readFileFull(new File(
|
|
||||||
protocolBridge.getProtocolServer().getFolderStructure().publicCAFolder,
|
|
||||||
caPrefix + ".srl"));
|
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
protocolBridge.getLogger().exception("Failed to read ca-files", exception);
|
protocolBridge.getLogger().exception("Failed to read ca-files", exception);
|
||||||
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
objectOutputStream.writeUTF(caKey);
|
|
||||||
objectOutputStream.writeUTF(caPem);
|
objectOutputStream.writeUTF(caPem);
|
||||||
objectOutputStream.writeUTF(caSrl);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protocolBridge.isRunningAsClient()) {
|
if (protocolBridge.isRunningAsClient()) {
|
||||||
// FIX: Send the connection id of the connection this auth is meant for.
|
|
||||||
// If we are connecting/authing against INS, use INS connectionId.
|
|
||||||
// Otherwise use Server connectionId.
|
|
||||||
UUID clientConnectionId = null;
|
UUID clientConnectionId = null;
|
||||||
|
|
||||||
if (protocolBridge.getProtocolClient() != null) {
|
if (protocolBridge.getProtocolClient() != null) {
|
||||||
@@ -161,27 +147,58 @@ public final class AuthPacket extends OACPacket {
|
|||||||
setResponseCode(INSResponseStatus.RESPONSE_AUTH_SUCCESS);
|
setResponseCode(INSResponseStatus.RESPONSE_AUTH_SUCCESS);
|
||||||
|
|
||||||
String caPrefix = objectInputStream.readUTF();
|
String caPrefix = objectInputStream.readUTF();
|
||||||
|
|
||||||
String caKey = objectInputStream.readUTF();
|
|
||||||
String caPem = objectInputStream.readUTF();
|
String caPem = objectInputStream.readUTF();
|
||||||
String caSrl = objectInputStream.readUTF();
|
|
||||||
|
|
||||||
if (caKey.equalsIgnoreCase("N/A") || caPem.equalsIgnoreCase("N/A") || caSrl.equalsIgnoreCase("N/A")) {
|
if (!caPrefix.matches("^[a-zA-Z0-9_-]+$")) {
|
||||||
|
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caPem.equalsIgnoreCase("N/A")) {
|
||||||
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
byte[] caBytes = caPem.getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
||||||
|
java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");
|
||||||
|
String fp = java.util.HexFormat.of().formatHex(md.digest(caBytes));
|
||||||
|
|
||||||
|
|
||||||
File caPemFile = new File(protocolBridge.getProtocolClient().getFolderStructure().publicCAFolder, caPrefix + ".pem");
|
File caPemFile = new File(protocolBridge.getProtocolClient().getFolderStructure().publicCAFolder, caPrefix + ".pem");
|
||||||
File caSrlFile = new File(protocolBridge.getProtocolClient().getFolderStructure().publicCAFolder, caPrefix + ".srl");
|
|
||||||
File caKeyFile = new File(protocolBridge.getProtocolClient().getFolderStructure().privateCAFolder, caPrefix + ".key");
|
File fpFile = new File(
|
||||||
|
protocolBridge.getProtocolClient().getFolderStructure().publicCAFolder,
|
||||||
|
caPrefix + ".fp");
|
||||||
|
|
||||||
|
boolean allowWritePem = false;
|
||||||
|
|
||||||
|
if (fpFile.exists()) {
|
||||||
|
String existing = FileUtils.readFileFull(fpFile).trim();
|
||||||
|
TOFUFeedback feedback = protocolBridge.getProtocolClient().insFingerprintChanged(existing, fp);
|
||||||
|
if (feedback == TOFUFeedback.DISCONNECT) {
|
||||||
|
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||||
|
protocolBridge.getProtocolClient().getClientINSConnection().disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (feedback == TOFUFeedback.TRUST) { FileUtils.writeFile(fpFile, fp + System.lineSeparator()); allowWritePem = true; }
|
||||||
|
} else {
|
||||||
|
TOFUFeedback feedback = protocolBridge.getProtocolClient().trustINS(fp);
|
||||||
|
if (feedback == TOFUFeedback.DISCONNECT) {
|
||||||
|
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||||
|
protocolBridge.getProtocolClient().getClientINSConnection().disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (feedback == TOFUFeedback.TRUST) { FileUtils.writeFile(fpFile, fp + System.lineSeparator()); allowWritePem = true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allowWritePem) {
|
||||||
|
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!caPemFile.exists()) caPemFile.createNewFile();
|
if (!caPemFile.exists()) caPemFile.createNewFile();
|
||||||
if (!caSrlFile.exists()) caSrlFile.createNewFile();
|
|
||||||
if (!caKeyFile.exists()) caKeyFile.createNewFile();
|
|
||||||
|
|
||||||
// FIX: Correct file assignments.
|
// FIX: Correct file assignments.
|
||||||
FileUtils.writeFile(caPemFile, caPem);
|
FileUtils.writeFile(caPemFile, caPem);
|
||||||
FileUtils.writeFile(caSrlFile, caSrl);
|
|
||||||
FileUtils.writeFile(caKeyFile, caKey);
|
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
protocolBridge.getLogger().exception("Failed to create/save ca-files", exception);
|
protocolBridge.getLogger().exception("Failed to create/save ca-files", exception);
|
||||||
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||||
|
|||||||
@@ -18,11 +18,8 @@ import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
|||||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord;
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecordType;
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecordType;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
|
||||||
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.TOFUFeedback;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -320,7 +317,7 @@ public abstract class ProtocolClient extends EventListener {
|
|||||||
onQuerySent(tln, name, sub, type);
|
onQuerySent(tln, name, sub, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void disconnectFromServer() {
|
private final void disconnectFromServer() {
|
||||||
if (clientToServer != null) {
|
if (clientToServer != null) {
|
||||||
protocolBridge.getProtocolValues().eventManager.unregisterListener(this);
|
protocolBridge.getProtocolValues().eventManager.unregisterListener(this);
|
||||||
clientToServer.disconnect();
|
clientToServer.disconnect();
|
||||||
@@ -334,6 +331,9 @@ public abstract class ProtocolClient extends EventListener {
|
|||||||
public void onQuerySent(String tln, String name, String sub, INSRecordType type) {
|
public void onQuerySent(String tln, String name, String sub, INSRecordType type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract TOFUFeedback trustINS(String caFingerprint);
|
||||||
|
public abstract TOFUFeedback insFingerprintChanged(String oldCAFingerprint, String newCAFingerprint);
|
||||||
|
|
||||||
public static final class ClientCertificateFolderStructure {
|
public static final class ClientCertificateFolderStructure {
|
||||||
public final File certificatesFolder;
|
public final File certificatesFolder;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package org.openautonomousconnection.protocol.side.ins;
|
package org.openautonomousconnection.protocol.side.ins;
|
||||||
|
|
||||||
import dev.unlegitdqrk.unlegitlibrary.file.ConfigurationManager;
|
import dev.unlegitdqrk.unlegitlibrary.file.ConfigurationManager;
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.file.FileUtils;
|
||||||
import dev.unlegitdqrk.unlegitlibrary.network.system.server.NetworkServer;
|
import dev.unlegitdqrk.unlegitlibrary.network.system.server.NetworkServer;
|
||||||
import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientAuthMode;
|
import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientAuthMode;
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.network.utils.NetworkUtils;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
|
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
|
||||||
import org.openautonomousconnection.protocol.side.server.ProtocolCustomServer;
|
import org.openautonomousconnection.protocol.side.server.ProtocolCustomServer;
|
||||||
@@ -14,6 +16,7 @@ import javax.net.ssl.SSLContext;
|
|||||||
import javax.net.ssl.SSLServerSocketFactory;
|
import javax.net.ssl.SSLServerSocketFactory;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -58,8 +61,17 @@ public abstract class ProtocolINSServer extends ProtocolCustomServer {
|
|||||||
this.insFrontendSite = insFrontendSite;
|
this.insFrontendSite = insFrontendSite;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(int tcpPort) throws IOException, InterruptedException {
|
public void start(int tcpPort) throws IOException, InterruptedException, NoSuchAlgorithmException {
|
||||||
getNetwork().start(tcpPort, -1);
|
getNetwork().start(tcpPort, -1);
|
||||||
|
|
||||||
|
String caPrefix = getFolderStructure().getCaPrefix() + NetworkUtils.getPublicIPAddress();
|
||||||
|
File caPemFile = new File(getFolderStructure().publicCAFolder, caPrefix + ".pem");
|
||||||
|
|
||||||
|
byte[] caBytes = FileUtils.readFileFull(caPemFile).getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
||||||
|
java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");
|
||||||
|
String fp = java.util.HexFormat.of().formatHex(md.digest(caBytes));
|
||||||
|
|
||||||
|
System.out.println("CA Fingerprint: " + fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
|
||||||
|
|
||||||
|
public enum TOFUFeedback {
|
||||||
|
|
||||||
|
TRUST, TRUST_ONCE, DISCONNECT
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user