Fixed certificate handling

This commit is contained in:
Ziver Koc 2021-08-20 23:10:13 +02:00
parent e8270d4027
commit d9ce3af5aa
6 changed files with 84 additions and 25 deletions

0
gradlew vendored Executable file → Normal file
View file

View file

@ -24,6 +24,7 @@ public class HalContext {
public static final String CONFIG_HTTP_PORT = "hal_core.http_port"; public static final String CONFIG_HTTP_PORT = "hal_core.http_port";
public static final String CONFIG_HTTP_EXTERNAL_PORT = "hal_core.http_external_port"; public static final String CONFIG_HTTP_EXTERNAL_PORT = "hal_core.http_external_port";
public static final String CONFIG_HTTP_EXTERNAL_DOMAIN = "hal_core.http_external_domain"; public static final String CONFIG_HTTP_EXTERNAL_DOMAIN = "hal_core.http_external_domain";
public static final String CONFIG_HTTP_EXTERNAL_ACME_TYPE = "hal_core.http_external_acme_type";
public static final String CONFIG_MAP_BACKGROUND_IMAGE = "hal_core.map_bgimage"; public static final String CONFIG_MAP_BACKGROUND_IMAGE = "hal_core.map_bgimage";
public static final String RESOURCE_ROOT; public static final String RESOURCE_ROOT;
@ -104,10 +105,10 @@ public class HalContext {
registerProperty(key); registerProperty(key);
String value = null; String value = null;
if (dbConf != null)
value = dbConf.getProperty(key);
if (fileConf != null) if (fileConf != null)
value = fileConf.getProperty(key); value = fileConf.getProperty(key);
if (value == null && dbConf != null)
value = dbConf.getProperty(key);
return value != null ? value : defaultValue; return value != null ? value : defaultValue;
} }
@ -116,7 +117,7 @@ public class HalContext {
} }
public static int getIntegerProperty(String key, int defaultValue){ public static int getIntegerProperty(String key, int defaultValue){
String value = getStringProperty(key); String value = getStringProperty(key);
return value != null ? getIntegerProperty(key) : defaultValue; return value != null ? Integer.parseInt(getStringProperty(key)) : defaultValue;
} }
public static boolean getBooleanProperty(String key) { public static boolean getBooleanProperty(String key) {

View file

@ -8,7 +8,10 @@ import se.hal.util.HalAcmeDataStore;
import zutil.db.DBConnection; import zutil.db.DBConnection;
import zutil.io.file.FileUtil; import zutil.io.file.FileUtil;
import zutil.log.LogUtil; import zutil.log.LogUtil;
import zutil.net.acme.AcmeChallengeFactory;
import zutil.net.acme.AcmeClient; import zutil.net.acme.AcmeClient;
import zutil.net.acme.AcmeHttpChallengeFactory;
import zutil.net.acme.AcmeManualDnsChallengeFactory;
import zutil.net.http.HttpPage; import zutil.net.http.HttpPage;
import zutil.net.http.HttpServer; import zutil.net.http.HttpServer;
import zutil.net.http.page.HttpFilePage; import zutil.net.http.page.HttpFilePage;
@ -79,16 +82,35 @@ public class HalServer {
if (HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_PORT) && if (HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_PORT) &&
HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_DOMAIN)) { HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_DOMAIN)) {
// Start a non secure server to retrieve handle the ACME protocol challenge AcmeClient acme;
HttpServer tmpHttpExternal = new HttpServer(HalContext.getIntegerProperty(CONFIG_HTTP_EXTERNAL_PORT)); HttpServer tmpHttpServer = null;
tmpHttpExternal.start();
AcmeClient acme = new AcmeClient(new HalAcmeDataStore()); if ("dns".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, ""))) {
Certificate certificate = acme.fetchCertificate(tmpHttpExternal, HalContext.getStringProperty(CONFIG_HTTP_EXTERNAL_DOMAIN)); acme = new AcmeClient(new HalAcmeDataStore(), new AcmeManualDnsChallengeFactory(), AcmeClient.ACME_SERVER_LETSENCRYPT_STAGING);
} else if ("http".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, "http"))) {
tmpHttpServer = new HttpServer(80);
tmpHttpServer.start();
tmpHttpExternal.close(); acme = new AcmeClient(new HalAcmeDataStore(), new AcmeHttpChallengeFactory(tmpHttpServer), AcmeClient.ACME_SERVER_LETSENCRYPT_STAGING);
httpExternal = new HttpServer(HalContext.getIntegerProperty(CONFIG_HTTP_EXTERNAL_PORT)); } else {
throw new IllegalArgumentException("Unknown config value for " + HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE + ": " +
HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE));
}
acme.addDomain(HalContext.getStringProperty(CONFIG_HTTP_EXTERNAL_DOMAIN));
acme.prepareRequest();
Certificate certificate = acme.requestCertificate();
httpExternal = new HttpServer(HalContext.getIntegerProperty(CONFIG_HTTP_EXTERNAL_PORT), certificate);
httpExternal.start(); httpExternal.start();
// Cleanup
if ("http".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, "http"))) {
tmpHttpServer.close();
}
logger.info("External https server up and running at: https://" + HalContext.getStringProperty(CONFIG_HTTP_EXTERNAL_DOMAIN) + ":" + HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_PORT));
} else { } else {
logger.warning("Missing '" + CONFIG_HTTP_EXTERNAL_PORT + "' and '" + CONFIG_HTTP_EXTERNAL_DOMAIN + "' configuration, will not setup external http server."); logger.warning("Missing '" + CONFIG_HTTP_EXTERNAL_PORT + "' and '" + CONFIG_HTTP_EXTERNAL_DOMAIN + "' configuration, will not setup external http server.");
return; return;

View file

@ -1,30 +1,66 @@
package se.hal.util; package se.hal.util;
import org.shredzone.acme4j.util.KeyPairUtils;
import se.hal.HalContext;
import zutil.log.LogUtil;
import zutil.net.acme.AcmeDataStore; import zutil.net.acme.AcmeDataStore;
import zutil.parser.Base64Decoder;
import zutil.parser.Base64Encoder;
import java.io.*;
import java.security.KeyPair; import java.security.KeyPair;
import java.util.logging.Level;
import java.util.logging.Logger;
public class HalAcmeDataStore implements AcmeDataStore { public class HalAcmeDataStore implements AcmeDataStore {
private static final Logger logger = LogUtil.getLogger();
private static final String CONFIG_HTTP_EXTERNAL_USER_KEY = "hal_core.http_external_user_key"; private static final String CONFIG_HTTP_EXTERNAL_USER_KEY = "hal_core.http_external_user_key";
private static final String CONFIG_HTTP_EXTERNAL_DOMAIN_KEY = "hal_core.http_external_domain_key"; private static final String CONFIG_HTTP_EXTERNAL_DOMAIN_KEY = "hal_core.http_external_domain_key";
@Override @Override
public KeyPair loadUserKeyPair() { public KeyPair loadUserKeyPair() {
return null; return loadKeyPair(CONFIG_HTTP_EXTERNAL_USER_KEY);
}
@Override
public void storeUserKeyPair(KeyPair keyPair) {
} }
@Override @Override
public KeyPair loadDomainKeyPair() { public KeyPair loadDomainKeyPair() {
return loadKeyPair(CONFIG_HTTP_EXTERNAL_DOMAIN_KEY);
}
private KeyPair loadKeyPair(String configName) {
if (HalContext.containsProperty(configName)) {
try {
byte[] data = Base64Decoder.decodeToByte(
HalContext.getStringProperty(configName));
return KeyPairUtils.readKeyPair(new InputStreamReader(new ByteArrayInputStream(data)));
} catch (IOException e) {
logger.log(Level.SEVERE, "Was unable to load KeyPair from DB.", e);
}
}
return null; return null;
} }
@Override
public void storeUserKeyPair(KeyPair keyPair) {
storeKeyPair(keyPair, CONFIG_HTTP_EXTERNAL_USER_KEY);
}
@Override @Override
public void storeDomainKeyPair(KeyPair keyPair) { public void storeDomainKeyPair(KeyPair keyPair) {
storeKeyPair(keyPair, CONFIG_HTTP_EXTERNAL_DOMAIN_KEY);
}
private void storeKeyPair(KeyPair keyPair, String configName) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(out);
KeyPairUtils.writeKeyPair(keyPair, writer);
HalContext.setProperty(configName, Base64Encoder.encode(out.toByteArray()));
} catch (IOException e) {
logger.log(Level.SEVERE, "Was unable to store KeyPair to DB.", e);
}
} }
} }

View file

@ -58,7 +58,7 @@ public class PCDataSynchronizationDaemon extends ThreadedTCPNetworkServer implem
public static final int PROTOCOL_VERSION = 5; // Increment for protocol changes public static final int PROTOCOL_VERSION = 5; // Increment for protocol changes
public PCDataSynchronizationDaemon() { public PCDataSynchronizationDaemon() throws IOException {
super(HalContext.getIntegerProperty(PROPERTY_SYNC_PORT)); super(HalContext.getIntegerProperty(PROPERTY_SYNC_PORT));
} }
@ -81,20 +81,20 @@ public class PCDataSynchronizationDaemon extends ThreadedTCPNetworkServer implem
private class DataSynchronizationDaemonThread implements ThreadedTCPNetworkServerThread{ private class DataSynchronizationDaemonThread implements ThreadedTCPNetworkServerThread{
private Socket s; private Socket socket;
private ObjectOutputStream out; private ObjectOutputStream out;
private ObjectInputStream in; private ObjectInputStream in;
public DataSynchronizationDaemonThread(Socket s) throws IOException{ public DataSynchronizationDaemonThread(Socket socket) throws IOException{
this.s = s; this.socket = socket;
this.out = new ObjectOutputStream(s.getOutputStream()); this.out = new ObjectOutputStream(socket.getOutputStream());
this.in = new ObjectInputStream(s.getInputStream()); this.in = new ObjectInputStream(socket.getInputStream());
} }
public void run(){ public void run(){
logger.fine("User connected: "+ s.getInetAddress().getHostName()); logger.fine("User connected: "+ socket.getInetAddress().getHostName());
DBConnection db = HalContext.getDB(); DBConnection db = HalContext.getDB();
try { try {
@ -166,12 +166,12 @@ public class PCDataSynchronizationDaemon extends ThreadedTCPNetworkServer implem
} }
out.close(); out.close();
in.close(); in.close();
s.close(); socket.close();
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.SEVERE, null, e); logger.log(Level.SEVERE, null, e);
} }
logger.fine("User disconnected: "+ s.getInetAddress().getHostName()); logger.fine("User disconnected: "+ socket.getInetAddress().getHostName());
} }
} }

0
run.sh Executable file → Normal file
View file