Author: toad
Date: 2007-12-22 00:12:28 +0000 (Sat, 22 Dec 2007)
New Revision: 16775
Added:
trunk/freenet/src/freenet/crypt/SSL.java
trunk/freenet/src/freenet/io/SSLNetworkInterface.java
Modified:
trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
trunk/freenet/src/freenet/node/NodeStarter.java
trunk/freenet/src/freenet/node/TextModeClientInterfaceServer.java
trunk/freenet/src/freenet/node/fcp/FCPServer.java
Log:
Patch from ET at mj+bSV4hxRMtCj9fcwy4Ww9_3mc on Frost: Add SSL support for FCP,
HTTP, TMCI.
Request testing!
Modified: trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
2007-12-22 00:06:33 UTC (rev 16774)
+++ trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
2007-12-22 00:12:28 UTC (rev 16775)
@@ -25,8 +25,10 @@
import freenet.config.EnumerableOptionCallback;
import freenet.config.InvalidConfigValueException;
import freenet.config.SubConfig;
+import freenet.crypt.SSL;
import freenet.io.AllowedHosts;
import freenet.io.NetworkInterface;
+import freenet.io.SSLNetworkInterface;
import freenet.l10n.L10n;
import freenet.node.NodeClientCore;
import freenet.support.HTMLNode;
@@ -53,12 +55,13 @@
String bindTo;
final AllowedHosts allowedFullAccess;
final BucketFactory bf;
- final NetworkInterface networkInterface;
+ NetworkInterface networkInterface;
private final LinkedList toadlets;
private String cssName;
private File cssOverride;
private Thread myThread;
private boolean advancedModeEnabled;
+ private boolean ssl = false;
private boolean fProxyJavascriptEnabled;
private final PageMaker pageMaker;
private final NodeClientCore core;
@@ -67,6 +70,21 @@
static boolean isPanicButtonToBeShown;
public static final int DEFAULT_FPROXY_PORT = 8888;
+ class FProxySSLCallback implements BooleanCallback {
+
+ public boolean get() {
+ return ssl;
+ }
+ public void set(boolean val) throws InvalidConfigValueException
{
+ if(val == get()) return;
+ if(!SSL.available()) {
+ throw new InvalidConfigValueException("Enable
SSL support before use ssl with Fproxy");
+ }
+ ssl = val;
+ throw new InvalidConfigValueException("Cannot change
SSL on the fly, please restart freenet");
+ }
+ }
+
class FProxyPortCallback implements IntCallback {
public int get() {
@@ -272,7 +290,8 @@
themes.add("clean");
}
}
-
+ fproxyConfig.register("ssl", false, configItemOrder++, true,
true, "SimpleToadletServer.ssl", "SimpleToadletServer.sslLong",
+ new FProxySSLCallback());
fproxyConfig.register("port", DEFAULT_FPROXY_PORT,
configItemOrder++, true, true, "SimpleToadletServer.port",
"SimpleToadletServer.portLong",
new FProxyPortCallback());
fproxyConfig.register("bindTo",
NetworkInterface.DEFAULT_BIND_TO, configItemOrder++, true, true,
"SimpleToadletServer.bindTo", "SimpleToadletServer.bindToLong",
@@ -340,9 +359,17 @@
this.advancedModeEnabled =
fproxyConfig.getBoolean("advancedModeEnabled");
toadlets = new LinkedList();
+
+ if(SSL.available()) {
+ ssl = fproxyConfig.getBoolean("ssl");
+ }
+
+ if(ssl) {
+ this.networkInterface =
SSLNetworkInterface.create(port, this.bindTo,
fproxyConfig.getString("allowedHosts"), core.getExecutor(), true);
+ } else {
+ this.networkInterface = NetworkInterface.create(port,
this.bindTo, fproxyConfig.getString("allowedHosts"), core.getExecutor(), true);
+ }
- this.networkInterface = NetworkInterface.create(port,
this.bindTo, fproxyConfig.getString("allowedHosts"), core.getExecutor(), true);
-
if(!enabled) {
Logger.normal(core, "Not starting FProxy as it's
disabled");
System.out.println("Not starting FProxy as it's
disabled");
Added: trunk/freenet/src/freenet/crypt/SSL.java
===================================================================
--- trunk/freenet/src/freenet/crypt/SSL.java (rev 0)
+++ trunk/freenet/src/freenet/crypt/SSL.java 2007-12-22 00:12:28 UTC (rev
16775)
@@ -0,0 +1,269 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package freenet.crypt;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import javax.net.ServerSocketFactory;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+
+import freenet.config.InvalidConfigValueException;
+import freenet.config.SubConfig;
+import freenet.support.Logger;
+import freenet.support.api.BooleanCallback;
+import freenet.support.api.StringCallback;
+
+import sun.security.x509.X500Name;
+import sun.security.x509.CertAndKeyGen;
+
+public class SSL {
+
+ private static boolean enable;
+ private static KeyStore keystore;
+ private static ServerSocketFactory ssf;
+ private static String keyStore;
+ private static String keyStorePass;
+ private static String keyPass;
+ private static String version;
+
+ private SSL() {
+
+ }
+
+ /**
+ * Call this function before ask ServerSocket
+ * @return True is ssl is available
+ */
+ public static boolean available() {
+ return (ssf != null);
+ }
+
+ /**
+ * Configure SSL support
+ * @param sslConfig
+ */
+ public static void init(SubConfig sslConfig) {
+ int configItemOrder = 0;
+
+ // Tracks config parameters related to a SSL
+ sslConfig.register("sslEnable", false, configItemOrder++, true,
true, "SSL.enable", "SSL.enableLong",
+ new BooleanCallback() {
+ public boolean get() {
+ return enable;
+ }
+
+ public void set(boolean newValue) throws
InvalidConfigValueException {
+ if (newValue != get()) {
+ enable = newValue;
+ if(enable) {
+ try {
+ loadKeyStore();
+ createSSLContext();
+ } catch (Exception e) {
+ enable = false;
+
e.printStackTrace(System.out);
+ throw new
InvalidConfigValueException("Cannot enabled ssl, config error");
+ }
+ } else {
+ ssf = null;
+ keyStore = null;
+ }
+ }
+ }
+ }
+ );
+
+ sslConfig.register("sslKeyStore", "datastore/certs",
configItemOrder++, true, true, "SSL.keyStore", "SSL.keyStoreLong",
+ new StringCallback() {
+ public String get() {
+ return keyStore;
+ }
+
+ public void set(String newKeyStore) throws
InvalidConfigValueException {
+ if (!newKeyStore.equals(get())) {
+ String oldKeyStore = keyStore;
+ keyStore = newKeyStore;
+ try {
+ loadKeyStore();
+ } catch (Exception e) {
+ keyStore = oldKeyStore;
+
e.printStackTrace(System.out);
+ throw new
InvalidConfigValueException("Cannot change keystore file");
+ }
+ }
+ }
+ }
+ );
+
+ sslConfig.register("sslKeyStorePass", "freenet",
configItemOrder++, true, true, "SSL.keyStorePass", "SSL.keyStorePassLong",
+ new StringCallback() {
+ public String get() {
+ return keyStorePass;
+ }
+
+ public void set(String newKeyStorePass) throws
InvalidConfigValueException {
+ if (!newKeyStorePass.equals(get())) {
+ String oldKeyStorePass =
keyStorePass;
+ keyStorePass = newKeyStorePass;
+ try {
+ storeKeyStore();
+ } catch (Exception e) {
+ keyStorePass = oldKeyStorePass;
+
e.printStackTrace(System.out);
+ throw new
InvalidConfigValueException("Cannot change keystore password");
+ }
+ }
+ }
+ }
+ );
+
+ sslConfig.register("sslKeyPass", "freenet", configItemOrder++,
true, true, "SSL.keyPass", "SSL.keyPassLong",
+ new StringCallback() {
+ public String get() {
+ return keyPass;
+ }
+
+ public void set(String newKeyPass) throws
InvalidConfigValueException {
+ if (!newKeyPass.equals(get())) {
+ String oldKeyPass = keyPass;
+ keyPass = newKeyPass;
+ try {
+ Certificate[] chain =
keystore.getCertificateChain("freenet");
+ Key privKey =
keystore.getKey("freenet", oldKeyPass.toCharArray());
+ keystore.setKeyEntry("freenet",
privKey, keyPass.toCharArray(), chain);
+ createSSLContext();
+ } catch (Exception e) {
+ keyPass = oldKeyPass;
+
e.printStackTrace(System.out);
+ throw new
InvalidConfigValueException("Cannot change private key password");
+ }
+ }
+ }
+ }
+ );
+
+ sslConfig.register("sslVersion", "SSLv3", configItemOrder++,
true, true, "SSL.version", "SSL.versionLong",
+ new StringCallback() {
+ public String get() {
+ return version;
+ }
+
+ public void set(String newVersion) throws
InvalidConfigValueException {
+ if (!newVersion.equals(get())) {
+ String oldVersion = version;
+ version = newVersion;
+ try {
+ createSSLContext();
+ } catch (Exception e) {
+ version = oldVersion;
+
e.printStackTrace(System.out);
+ throw new
InvalidConfigValueException("Cannot change ssl version, wrong value");
+ }
+ }
+ }
+ }
+ );
+
+ enable = sslConfig.getBoolean("sslEnable");
+ keyStore = sslConfig.getString("sslKeyStore");
+ keyStorePass = sslConfig.getString("sslKeyStorePass");
+ keyPass = sslConfig.getString("sslKeyPass");
+ version = sslConfig.getString("sslVersion");
+
+ try {
+ keystore = KeyStore.getInstance("PKCS12");
+ loadKeyStore();
+ createSSLContext();
+ } catch (Exception e) {
+ Logger.error(SSL.class, "Cannot load keystore, ssl is
disable", e);
+ }
+
+ }
+
+ /**
+ * Create ServerSocket with ssl support
+ * @return ServerSocket with ssl support
+ * @throws IOException
+ */
+ public static ServerSocket createServerSocket() throws IOException {
+ if(ssf == null)
+ throw new IOException("SSL not initialized");
+ return ssf.createServerSocket();
+ }
+
+ private static void loadKeyStore() throws Exception {
+ if(enable) {
+ // A keystore is where keys and certificates are kept
+ // Both the keystore and individual private keys should
be password protected
+ try {
+ FileInputStream fis = new
FileInputStream(keyStore);
+ keystore.load(fis, keyStorePass.toCharArray());
+ } catch (FileNotFoundException fnfe) {
+ //If keystore not exist, create keystore and
server certificat
+ keystore.load(null, keyStorePass.toCharArray());
+ CertAndKeyGen keypair = new
CertAndKeyGen("DSA", "SHA1WithDSA");
+ X500Name x500Name = new X500Name (
+ "Freenet",
+ "Freenet",
+ "Freenet",
+ "",
+ "",
+ ""
+ );
+ keypair.generate(1024);
+ PrivateKey privKey = keypair.getPrivateKey();
+ X509Certificate[] chain = new
X509Certificate[1];
+ chain[0] = keypair.getSelfCertificate(x500Name,
(long)365*24*60*60);
+ keystore.setKeyEntry("freenet", privKey,
keyPass.toCharArray(), chain);
+ storeKeyStore();
+ createSSLContext();
+ }
+ }
+ }
+
+ private static void storeKeyStore() throws Exception {
+ if(enable) {
+ FileOutputStream fos = new FileOutputStream(keyStore);
+ keystore.store(fos, keyStorePass.toCharArray());
+ fos.close();
+ }
+ }
+
+ private static void createSSLContext() throws Exception {
+ if(enable) {
+ // A KeyManagerFactory is used to create key managers
+ KeyManagerFactory kmf =
KeyManagerFactory.getInstance("SunX509");
+ // Initialize the KeyManagerFactory to work with our
keystore
+ kmf.init(keystore, keyPass.toCharArray());
+ // An SSLContext is an environment for implementing JSSE
+ // It is used to create a ServerSocketFactory
+ SSLContext sslc = SSLContext.getInstance(version);
+ // Initialize the SSLContext to work with our key
managers
+ sslc.init(kmf.getKeyManagers(), null, null);
+ ssf = sslc.getServerSocketFactory();
+ }
+ }
+}
Added: trunk/freenet/src/freenet/io/SSLNetworkInterface.java
===================================================================
--- trunk/freenet/src/freenet/io/SSLNetworkInterface.java
(rev 0)
+++ trunk/freenet/src/freenet/io/SSLNetworkInterface.java 2007-12-22
00:12:28 UTC (rev 16775)
@@ -0,0 +1,75 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package freenet.io;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+
+import javax.net.ssl.SSLServerSocket;
+
+import freenet.crypt.SSL;
+import freenet.support.Executor;
+import freenet.support.Logger;
+
+/**
+ * An SSL extension to the {@link NetworkInterface}
+ * @author ET
+ */
+public class SSLNetworkInterface extends NetworkInterface {
+
+ private boolean requireClientAuthentication;
+
+ public static NetworkInterface create(int port, String bindTo, String
allowedHosts, Executor executor, boolean ignoreUnbindableIP6) throws
IOException {
+ NetworkInterface iface = new SSLNetworkInterface(port,
allowedHosts, executor);
+ try {
+ iface.setBindTo(bindTo, ignoreUnbindableIP6);
+ } catch (IOException e) {
+ try {
+ iface.close();
+ } catch (IOException e1) {
+ Logger.error(NetworkInterface.class, "Caught
"+e1+" closing after catching "+e+" binding while constructing", e1);
+ // Ignore
+ }
+ throw e;
+ }
+ return iface;
+ }
+
+ /**
+ * See {@link NetworkInterface}
+ */
+ protected SSLNetworkInterface(int port, String allowedHosts, Executor
executor) throws IOException {
+ super(port, allowedHosts, executor);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected ServerSocket createServerSocket() throws IOException {
+ ServerSocket serverSocket = SSL.createServerSocket();
+
((SSLServerSocket)serverSocket).setNeedClientAuth(requireClientAuthentication);
+ return serverSocket;
+ }
+
+ /**
+ * Set true if client authentication is required
+ * @param value true or false
+ */
+ public void setRequireClientAuthentication(boolean value) {
+ requireClientAuthentication = value;
+ }
+}
Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties 2007-12-22
00:06:33 UTC (rev 16774)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties 2007-12-22
00:12:28 UTC (rev 16775)
@@ -89,6 +89,7 @@
ConfigToadlet.reset=Reset
ConfigToadlet.returnToNodeConfig=Return to node configuration
ConfigToadlet.shortTitle=Configuration
+ConfigToadlet.ssl=SSL (not affect active servers if change, restart is
necessary)
ConfigToadlet.title=Freenet Node Configuration
ConfigToadlet.toadletsymlinker=toadletsymlinker
ConfigToadlet.true=true
@@ -350,6 +351,8 @@
FcpServer.isEnabledLong=Is FCP server enabled ?
FcpServer.portNumber=FCP port number
FcpServer.portNumberLong=FCP port number.
+FcpServer.ssl=Enable ssl?
+FcpServer.sslLong=Enable ssl?
FetchException.longError.10=File not in archive
FetchException.longError.11=Too many path components - not a manifest? Try
removing one
FetchException.longError.12=Internal temp files error, maybe disk full or
permissions problem?
@@ -914,6 +917,18 @@
SimpleToadletServer.panicButtonLong=Whether to show or not the panic button on
the /queue/ page.
SimpleToadletServer.port=FProxy port number
SimpleToadletServer.portLong=FProxy port number
+SimpleToadletServer.ssl=Enable ssl?
+SimpleToadletServer.sslLong=Enable ssl?
+SSL.enable=Activate SSL support?
+SSL.enableLong=Activate SSL support?
+SSL.keyStore=Name and path of key store file
+SSL.keyStoreLong=Name and path of key store file
+SSL.keyStorePass=Password for access of key store file
+SSL.keyStorePassLong=Password for access of key store file
+SSL.keyPass=Password of private key access
+SSL.keyPassLong=Password of private key access
+SSL.version=Version of SSL
+SSL.versionLong=Version of SSL, SSLv3 or TLSv1 (default SSLv3)
StaticToadlet.pathInvalidChars=The given URI contains disallowed characters.
StaticToadlet.pathNotFound=The path you specified doesn't exist.
StaticToadlet.pathNotFoundTitle=Path Not Found
@@ -960,6 +975,8 @@
TextModeClientInterfaceServer.enableInputOutputLong=Enable text mode client
interface on standard input/output? (.enabled refers to providing a
telnet-style server, this runs it over a socket)
TextModeClientInterfaceServer.enabled=Enable TMCI
TextModeClientInterfaceServer.enabledLong=Whether to enable the TMCI
+TextModeClientInterfaceServer.ssl=Enable ssl?
+TextModeClientInterfaceServer.sslLong=Enable ssl?
TextModeClientInterfaceServer.telnetPortNumber=Telnet port
TextModeClientInterfaceServer.telnetPortNumberLong=Telnet port number
TimeSkewDetectedUserAlert.title=Time skew detected!
Modified: trunk/freenet/src/freenet/node/NodeStarter.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeStarter.java 2007-12-22 00:06:33 UTC
(rev 16774)
+++ trunk/freenet/src/freenet/node/NodeStarter.java 2007-12-22 00:12:28 UTC
(rev 16775)
@@ -15,6 +15,7 @@
import freenet.config.SubConfig;
import freenet.crypt.DiffieHellman;
import freenet.crypt.RandomSource;
+import freenet.crypt.SSL;
import freenet.crypt.Yarrow;
import freenet.support.Executor;
import freenet.support.Logger;
@@ -147,6 +148,10 @@
plug.setDaemon(false);
plug.start();
+ // Initialize SSL
+ SubConfig sslConfig = new SubConfig("ssl", cfg);
+ SSL.init(sslConfig);
+
WrapperManager.signalStarting(500000);
try {
node = new Node(cfg, random, logConfigHandler,this, executor);
Modified: trunk/freenet/src/freenet/node/TextModeClientInterfaceServer.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterfaceServer.java
2007-12-22 00:06:33 UTC (rev 16774)
+++ trunk/freenet/src/freenet/node/TextModeClientInterfaceServer.java
2007-12-22 00:12:28 UTC (rev 16775)
@@ -17,7 +17,9 @@
import freenet.config.InvalidConfigValueException;
import freenet.config.SubConfig;
import freenet.crypt.RandomSource;
+import freenet.crypt.SSL;
import freenet.io.NetworkInterface;
+import freenet.io.SSLNetworkInterface;
import freenet.support.Logger;
import freenet.support.api.BooleanCallback;
import freenet.support.api.IntCallback;
@@ -35,6 +37,7 @@
String bindTo;
String allowedHosts;
boolean isEnabled;
+ private static boolean ssl = false;
final NetworkInterface networkInterface;
TextModeClientInterfaceServer(Node node, NodeClientCore core, int port,
String bindTo, String allowedHosts) throws IOException {
@@ -47,7 +50,11 @@
this.bindTo=bindTo;
this.allowedHosts = allowedHosts;
this.isEnabled=true;
- networkInterface = NetworkInterface.create(port, bindTo, allowedHosts,
n.executor, true);
+ if(ssl) {
+ networkInterface = SSLNetworkInterface.create(port, bindTo,
allowedHosts, n.executor, true);
+ } else {
+ networkInterface = NetworkInterface.create(port, bindTo,
allowedHosts, n.executor, true);
+ }
}
void start() {
@@ -64,6 +71,7 @@
SubConfig TMCIConfig = new SubConfig("console", config);
TMCIConfig.register("enabled", false, 1, true, true /* FIXME
only because can't be changed on the fly */,
"TextModeClientInterfaceServer.enabled",
"TextModeClientInterfaceServer.enabledLong", new TMCIEnabledCallback(core));
+ TMCIConfig.register("ssl", false, 1, true, true ,
"TextModeClientInterfaceServer.ssl", "TextModeClientInterfaceServer.sslLong",
new TMCISSLCallback());
TMCIConfig.register("bindTo", NetworkInterface.DEFAULT_BIND_TO,
2, true, false, "TextModeClientInterfaceServer.bindTo",
"TextModeClientInterfaceServer.bindToLong", new TMCIBindtoCallback(core));
TMCIConfig.register("allowedHosts",
NetworkInterface.DEFAULT_BIND_TO, 2, true, false,
"TextModeClientInterfaceServer.allowedHosts",
"TextModeClientInterfaceServer.allowedHostsLong", new
TMCIAllowedHostsCallback(core));
TMCIConfig.register("port", 2323, 1, true, false,
"TextModeClientInterfaceServer.telnetPortNumber",
"TextModeClientInterfaceServer.telnetPortNumberLong", new
TCMIPortNumberCallback(core));
@@ -74,6 +82,9 @@
String bind_ip = TMCIConfig.getString("bindTo");
String allowedHosts = TMCIConfig.getString("allowedHosts");
boolean direct = TMCIConfig.getBoolean("directEnabled");
+ if(SSL.available()) {
+ ssl = TMCIConfig.getBoolean("ssl");
+ }
if(TMCIEnabled)
server = new TextModeClientInterfaceServer(node, core,
port, bind_ip, allowedHosts);
@@ -113,6 +124,22 @@
}
}
+ static class TMCISSLCallback implements BooleanCallback {
+
+ public boolean get() {
+ return ssl;
+ }
+
+ public void set(boolean val) throws InvalidConfigValueException {
+ if(val == get()) return;
+ if(!SSL.available()) {
+ throw new InvalidConfigValueException("Enable
SSL support before use ssl with TMCI");
+ }
+ ssl = val;
+ throw new InvalidConfigValueException("Cannot change SSL on the
fly, please restart freenet");
+ }
+ }
+
static class TMCIDirectEnabledCallback implements BooleanCallback {
final NodeClientCore core;
Modified: trunk/freenet/src/freenet/node/fcp/FCPServer.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPServer.java 2007-12-22 00:06:33 UTC
(rev 16774)
+++ trunk/freenet/src/freenet/node/fcp/FCPServer.java 2007-12-22 00:12:28 UTC
(rev 16775)
@@ -30,8 +30,10 @@
import freenet.config.Config;
import freenet.config.InvalidConfigValueException;
import freenet.config.SubConfig;
+import freenet.crypt.SSL;
import freenet.io.AllowedHosts;
import freenet.io.NetworkInterface;
+import freenet.io.SSLNetworkInterface;
import freenet.keys.FreenetURI;
import freenet.l10n.L10n;
import freenet.node.Node;
@@ -59,6 +61,7 @@
final NodeClientCore core;
final Node node;
final int port;
+ private static boolean ssl = false;
public final boolean enabled;
String bindTo;
AllowedHosts allowedHostsFullAccess;
@@ -118,7 +121,11 @@
NetworkInterface tempNetworkInterface = null;
try {
- tempNetworkInterface = NetworkInterface.create(port,
bindTo, allowedHosts, node.executor, true);
+ if(ssl) {
+ tempNetworkInterface =
SSLNetworkInterface.create(port, bindTo, allowedHosts, node.executor, true);
+ } else {
+ tempNetworkInterface =
NetworkInterface.create(port, bindTo, allowedHosts, node.executor, true);
+ }
} catch (IOException be) {
Logger.error(this, "Couldn't bind to FCP Port "+bindTo+
':' +port+". FCP Server not started.", be);
System.out.println("Couldn't bind to FCP Port "+bindTo+
':' +port+". FCP Server not started.");
@@ -215,6 +222,22 @@
}
}
+ static class FCPSSLCallback implements BooleanCallback{
+
+ public boolean get() {
+ return ssl;
+ }
+
+ public void set(boolean val) throws InvalidConfigValueException
{
+ if(val == get()) return;
+ if(!SSL.available()) {
+ throw new InvalidConfigValueException("Enable
SSL support before use ssl with FCP");
+ }
+ ssl = val;
+ throw new InvalidConfigValueException("Cannot change
SSL on the fly, please restart freenet");
+ }
+ }
+
// FIXME: Consider moving everything except enabled into constructor
// Actually we could move enabled in too with an exception???
@@ -368,6 +391,7 @@
SubConfig fcpConfig = new SubConfig("fcp", config);
short sortOrder = 0;
fcpConfig.register("enabled", true, sortOrder++, true, false,
"FcpServer.isEnabled", "FcpServer.isEnabledLong", new FCPEnabledCallback(core));
+ fcpConfig.register("ssl", false, sortOrder++, true, true,
"FcpServer.ssl", "FcpServer.sslLong", new FCPSSLCallback());
fcpConfig.register("port", FCPServer.DEFAULT_FCP_PORT /*
anagram of 1984, and 1000 up from old number */, 2, true, true,
"FcpServer.portNumber", "FcpServer.portNumberLong", new
FCPPortNumberCallback(core));
fcpConfig.register("bindTo", NetworkInterface.DEFAULT_BIND_TO,
sortOrder++, false, true, "FcpServer.bindTo", "FcpServer.bindToLong", new
FCPBindtoCallback(core));
fcpConfig.register("allowedHosts",
NetworkInterface.DEFAULT_BIND_TO, sortOrder++, false, true,
"FcpServer.allowedHosts", "FcpServer.allowedHostsLong", new
FCPAllowedHostsCallback(core));
@@ -386,6 +410,10 @@
AssumeDDAUploadIsAllowedCallback cb5;
fcpConfig.register("assumeDownloadDDAIsAllowed", false,
sortOrder++, true, false, "FcpServer.assumeDownloadDDAIsAllowed",
"FcpServer.assumeDownloadDDAIsAllowedLong", cb4 = new
AssumeDDADownloadIsAllowedCallback());
fcpConfig.register("assumeUploadDDAIsAllowed", false,
sortOrder++, true, false, "FcpServer.assumeUploadDDAIsAllowed",
"FcpServer.assumeUploadDDAIsAllowedLong", cb5 = new
AssumeDDAUploadIsAllowedCallback());
+
+ if(SSL.available()) {
+ ssl = fcpConfig.getBoolean("ssl");
+ }
FCPServer fcp = new FCPServer(fcpConfig.getString("bindTo"),
fcpConfig.getString("allowedHosts"),
fcpConfig.getString("allowedHostsFullAccess"), fcpConfig.getInt("port"), node,
core, persistentDownloadsEnabled, persistentDownloadsDir,
persistentDownloadsInterval, fcpConfig.getBoolean("enabled"),
fcpConfig.getBoolean("assumeDownloadDDAIsAllowed"),
fcpConfig.getBoolean("assumeUploadDDAIsAllowed"));