diff --git a/src/buttondevteam/website/AcmeClient.java b/src/buttondevteam/website/AcmeClient.java index 2564651..6a4765b 100644 --- a/src/buttondevteam/website/AcmeClient.java +++ b/src/buttondevteam/website/AcmeClient.java @@ -153,6 +153,12 @@ public class AcmeClient { private Registration findOrRegisterAccount(Session session) throws AcmeException, IOException { Registration reg; + URI loc = ButtonWebsiteModule.getRegistration(); + if (loc != null) { + LOG.info("Loading account from file"); + return Registration.bind(session, loc); + } + try { // Try to create a new Registration. reg = new RegistrationBuilder().create(session); @@ -169,6 +175,7 @@ public class AcmeClient { // URL of the existing registration's location. Bind it to the session. reg = Registration.bind(session, ex.getLocation()); LOG.info("Account does already exist, URI: " + reg.getLocation(), ex); + ButtonWebsiteModule.storeRegistration(ex.getLocation()); } return reg; @@ -261,7 +268,7 @@ public class AcmeClient { /* * LOG.info("Press any key to continue..."); if (ButtonWebsiteModule.PORT != 443) try { System.in.read(); } catch (IOException e) { e.printStackTrace(); } */ - AcmeChallengePage.setValues(challenge.getToken(), challenge.getAuthorization()); + ButtonWebsiteModule.addHttpPage(new AcmeChallengePage(challenge.getToken(), challenge.getAuthorization())); return challenge; } diff --git a/src/buttondevteam/website/ButtonWebsiteModule.java b/src/buttondevteam/website/ButtonWebsiteModule.java index 2130f52..5ad5ce4 100644 --- a/src/buttondevteam/website/ButtonWebsiteModule.java +++ b/src/buttondevteam/website/ButtonWebsiteModule.java @@ -3,6 +3,8 @@ package buttondevteam.website; import java.io.*; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.URI; +import java.net.URISyntaxException; import java.security.KeyPair; import java.security.KeyStore; import java.security.PrivateKey; @@ -23,20 +25,28 @@ import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpsConfigurator; import com.sun.net.httpserver.HttpsParameters; import com.sun.net.httpserver.HttpsServer; import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.website.io.IOHelper; import buttondevteam.website.page.*; public class ButtonWebsiteModule extends JavaPlugin { public static final int PORT = 443; private static HttpsServer server; + /** + * For ACME validation and user redirection + */ + private static HttpsServer httpserver; public ButtonWebsiteModule() { try { server = HttpsServer.create(new InetSocketAddress((InetAddress) null, PORT), 10); + httpserver = HttpsServer.create(new InetSocketAddress((InetAddress) null, 80), 10); SSLContext sslContext = SSLContext.getInstance("TLS"); // initialise the keystore @@ -120,13 +130,16 @@ public class ButtonWebsiteModule extends JavaPlugin { server.setExecutor( new ThreadPoolExecutor(4, 8, 30, TimeUnit.SECONDS, new ArrayBlockingQueue(100))); final Calendar calendar = Calendar.getInstance(); - if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY && !TBMCCoreAPI.IsTestServer()) { // Only update every week - addPage(new AcmeChallengePage()); // Add before the server gets started - Thread t = new Thread(() -> AcmeClient.main("server.figytuna.com")); - t.setContextClassLoader(getClass().getClassLoader()); - t.start(); - } + if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY && !TBMCCoreAPI.IsTestServer()) // Only update every week + AcmeClient.main("server.figytuna.com"); // Task is running async so we don't need an extra thread ((Runnable) server::start).run(); // Totally normal way of calling a method + httpserver.createContext("/", new HttpHandler() { + @Override + public void handle(HttpExchange exchange) throws IOException { + IOHelper.SendResponse(IOHelper.Redirect("https://server.figytuna.com/", exchange)); + } + }); + httpserver.start(); this.getLogger().info("Webserver started"); }); } @@ -138,6 +151,29 @@ public class ButtonWebsiteModule extends JavaPlugin { server.createContext("/" + page.GetName(), page); } + /** + * Adds an insecure endpoint to the website. This should be avoided when possible. + */ + public static void addHttpPage(Page page) { + httpserver.createContext("/" + page.GetName(), page); + } + + static void storeRegistration(URI location) { + final ButtonWebsiteModule plugin = getPlugin(ButtonWebsiteModule.class); + plugin.getConfig().set("registration", location.toString()); + plugin.saveConfig(); + } + + static URI getRegistration() { + try { + String str = getPlugin(ButtonWebsiteModule.class).getConfig().getString("registration"); + return str == null ? null : new URI(str); + } catch (URISyntaxException e) { + e.printStackTrace(); + return null; + } + } + private static InputStream fullStream(String fname) throws IOException { FileInputStream fis = new FileInputStream(fname); DataInputStream dis = new DataInputStream(fis); diff --git a/src/buttondevteam/website/page/AcmeChallengePage.java b/src/buttondevteam/website/page/AcmeChallengePage.java index 353a9fe..a7a4e91 100644 --- a/src/buttondevteam/website/page/AcmeChallengePage.java +++ b/src/buttondevteam/website/page/AcmeChallengePage.java @@ -6,6 +6,11 @@ import buttondevteam.website.io.Response; public class AcmeChallengePage extends Page { + public AcmeChallengePage(String token, String content) { // The page name needs to be known before server start + AcmeChallengePage.token = token; + AcmeChallengePage.content = content; + } + @Override public String GetName() { return ".well-known/acme-challenge/" + token; @@ -21,9 +26,4 @@ public class AcmeChallengePage extends Page { private static String token; private static String content; - public static void setValues(String token, String content) { - AcmeChallengePage.token = token; - AcmeChallengePage.content = content; - } - }