Author: toad
Date: 2008-09-02 22:43:59 +0000 (Tue, 02 Sep 2008)
New Revision: 22362

Added:
   trunk/freenet/src/freenet/node/SecurityLevelListener.java
   trunk/freenet/src/freenet/node/SecurityLevels.java
Modified:
   trunk/freenet/src/freenet/clients/http/ConfigToadlet.java
   trunk/freenet/src/freenet/clients/http/PageMaker.java
   trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
   trunk/freenet/src/freenet/node/Node.java
Log:
Beginnings of security level support.
Cannot yet change the seclevel, and it doesn't change anything yet.


Modified: trunk/freenet/src/freenet/clients/http/ConfigToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ConfigToadlet.java   2008-09-02 
20:27:10 UTC (rev 22361)
+++ trunk/freenet/src/freenet/clients/http/ConfigToadlet.java   2008-09-02 
22:43:59 UTC (rev 22362)
@@ -20,6 +20,7 @@
 import freenet.l10n.L10n;
 import freenet.node.Node;
 import freenet.node.NodeClientCore;
+import freenet.node.SecurityLevels.NETWORK_THREAT_LEVEL;
 import freenet.node.useralerts.AbstractUserAlert;
 import freenet.node.useralerts.UserAlert;
 import freenet.support.HTMLNode;
@@ -215,6 +216,8 @@
                return L10n.getString("ConfigToadlet." + string);
        }

+       public static final int MODE_SECURITY_LEVELS = 3;
+       
        @Override
     public void handleGet(URI uri, HTTPRequest req, ToadletContext ctx) throws 
ToadletContextClosedException, IOException {

@@ -231,8 +234,12 @@

                contentNode.addChild(core.alerts.createSummary());

-               final int mode = 
ctx.getPageMaker().drawModeSelectionArray(core, req, contentNode);
+               final int mode = 
ctx.getPageMaker().drawModeSelectionArray(core, req, contentNode, 
MODE_SECURITY_LEVELS, "SecurityLevels.title", "SecurityLevels.tooltip");

+               if(mode == MODE_SECURITY_LEVELS) {
+                       drawSecurityLevelsPage(contentNode, ctx);
+               } else {
+               
                if(mode >= PageMaker.MODE_ADVANCED){
                        HTMLNode navigationBar = 
ctx.getPageMaker().getInfobox("navbar", l10n("configNavTitle"));
                        HTMLNode navigationContent = 
ctx.getPageMaker().getContentNode(navigationBar).addChild("ul");
@@ -243,6 +250,7 @@
                        HTMLNode nextTableCell = navigationTableRow;

                        for(int i=0; i<sc.length;i++){
+                               if(sc[i].getPrefix().equals("security-levels")) 
continue;
                                nextTableCell.addChild("td", "class", 
"config_navigation").addChild("li").addChild("a", "href", '#' 
+sc[i].getPrefix(), l10n(sc[i].getPrefix()));
                        }
                        contentNode.addChild(navigationBar);
@@ -271,6 +279,7 @@
                for(int i=0; i<sc.length;i++){
                        short displayedConfigElements = 0;

+                       if(sc[i].getPrefix().equals("security-levels")) 
continue;
                        Option<?>[] o = sc[i].getOptions();
                        HTMLNode configGroupUlNode = new HTMLNode("ul", 
"class", "config");

@@ -321,9 +330,48 @@
                formNode.addChild("input", new String[] { "type", "value" }, 
new String[] { "submit", l10n("apply")});
                formNode.addChild("input", new String[] { "type", "value" }, 
new String[] { "reset",  l10n("reset")});

+               }
+               
                this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
        }

+       private void drawSecurityLevelsPage(HTMLNode contentNode, 
ToadletContext ctx) {
+               HTMLNode infobox = contentNode.addChild("div", "class", 
"infobox infobox-normal");
+               infobox.addChild("div", "class", "infobox-header", 
l10nSec("title"));
+               HTMLNode configNode = infobox.addChild("div", "class", 
"infobox-content");
+               HTMLNode formNode = ctx.addFormChild(configNode, ".", 
"configFormSecLevels");
+               // Network security level
+               formNode.addChild("div", "class", "configprefix", 
l10nSec("networkThreatLevelShort"));
+               HTMLNode ul = formNode.addChild("ul", "class", "config");
+               HTMLNode seclevelGroup = ul.addChild("li");
+               seclevelGroup.addChild("#", l10nSec("networkThreatLevel"));
+               
+               NETWORK_THREAT_LEVEL networkLevel = 
node.securityLevels.getNetworkThreatLevel();
+               
+               String controlName = "security-levels.networkThreatLevel";
+               for(NETWORK_THREAT_LEVEL level : NETWORK_THREAT_LEVEL.values()) 
{
+                       HTMLNode input;
+                       if(level == networkLevel) {
+                               input = 
seclevelGroup.addChild("p").addChild("input", new String[] { "type", "checked", 
"name" }, new String[] { "radio", "on", controlName });
+                       } else {
+                               input = 
seclevelGroup.addChild("p").addChild("input", new String[] { "type", "name" }, 
new String[] { "radio", controlName });
+                       }
+                       input.addChild("b", 
l10nSec("networkThreatLevel.name."+level));
+                       input.addChild("#", ": ");
+                       L10n.addL10nSubstitution(input, 
"SecurityLevels.networkThreatLevel.desc."+level, new String[] { "bold", "/bold" 
}, new String[] { "<b>", "</b>" });
+               }
+               // FIXME implement the rest, it should be very similar to the 
above.
+               
+               formNode.addChild("input", new String[] { "type", "value" }, 
new String[] { "submit", l10n("apply")});
+               formNode.addChild("input", new String[] { "type", "value" }, 
new String[] { "reset",  l10n("reset")});
+       }
+
+
+       private String l10nSec(String key) {
+               return L10n.getString("SecurityLevels."+key);
+       }
+
+
        @Override
     public String supportedMethods() {
                return "GET, POST";

Modified: trunk/freenet/src/freenet/clients/http/PageMaker.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/PageMaker.java       2008-09-02 
20:27:10 UTC (rev 22361)
+++ trunk/freenet/src/freenet/clients/http/PageMaker.java       2008-09-02 
22:43:59 UTC (rev 22362)
@@ -255,6 +255,10 @@
        }

        protected int drawModeSelectionArray(NodeClientCore core, HTTPRequest 
req, HTMLNode contentNode) {
+               return drawModeSelectionArray(core, req, contentNode, -1, null, 
null);
+       }
+       
+       protected int drawModeSelectionArray(NodeClientCore core, HTTPRequest 
req, HTMLNode contentNode, int alternateMode, String alternateModeTitleKey, 
String alternateModeTooltipKey) {
                // Mode can be changed by a link, not just by the default

                int mode = core.isAdvancedModeEnabled() ? MODE_ADVANCED : 
MODE_SIMPLE;
@@ -277,6 +281,13 @@
                        cell.addChild("a", new String[] { "href", "title" }, 
new String[] { "?mode=2", l10n("modeAdvancedTooltip") }, l10n("modeAdvanced"));
                else
                        cell.addChild("b", "title", 
l10n("modeAdvancedTooltip"), l10n("modeAdvanced"));
+               if(alternateMode > -1) {
+                       cell = row.addChild("td");
+                       if(mode != alternateMode)
+                               cell.addChild("a", new String[] { "href", 
"title" }, new String[] { "?mode="+alternateMode, 
L10n.getString(alternateModeTooltipKey) }, 
L10n.getString(alternateModeTitleKey));
+                       else
+                               cell.addChild("b", "title", 
L10n.getString(alternateModeTooltipKey), L10n.getString(alternateModeTitleKey));
+               }

                return mode;
        }

Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties   2008-09-02 
20:27:10 UTC (rev 22361)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties   2008-09-02 
22:43:59 UTC (rev 22362)
@@ -1039,6 +1039,16 @@
 RequestStarterGroup.schedulerLong=Set the priority policy scheme used by the 
scheduler.
 RevocationKeyFoundUserAlert.text=Your node has found the auto-updater's 
revocation key on the network. It means that our auto-updating system is likely 
to have been COMPROMIZED! Consequently, it has been disabled on your node to 
prevent "bad things" to be installed. We strongly advise you to check the 
project's website for updates. Please take care of verifying that the website 
hasn't been spoofed either. The revocation message is the following : 
${message}.
 RevocationKeyFoundUserAlert.title=The private key of the project has been 
compromized!
+SecurityLevels.title=Security levels
+SecurityLevels.tooltip=Configure the node's degree of security
+SecurityLevels.networkThreatLevelShort=Protection against a stranger attacking 
you over the Internet
+SecurityLevels.networkThreatLevel=How much security do you need against 
Internet providers, corporations, governments, bored kids etc attempting to 
monitor your use of Freenet?
+SecurityLevels.networkThreatLevel.name.HIGH=HIGH
+SecurityLevels.networkThreatLevel.name.NORMAL=NORMAL
+SecurityLevels.networkThreatLevel.name.LOW=LOW
+SecurityLevels.networkThreatLevel.desc.HIGH=I intend to access information 
that could get me arrested, imprisoned, or worse.  I am worried about my 
government or ISP blocking Freenet. I understand that Freenet is experimental 
and ${bold}cannot${/bold} ensure security against certain known attacks, but I 
accept the risks compared to the alternatives.  Freenet will not connect to 
unknown nodes, so ${bold}I must have friends already using Freenet to select 
this mode${/bold}.
+SecurityLevels.networkThreatLevel.desc.NORMAL=I live in a relatively free 
country, but I would like to make it more difficult for others to monitor my 
communications.  Freenet will be reasonably careful to protect your anonymity, 
at some performance cost. Freenet will automatically connect to unknown nodes.  
We recommend that you add friends running Freenet and upgrade to HIGH.
+SecurityLevels.networkThreatLevel.desc.LOW=I do not care about monitoring and 
want maximum performance.  It may be quite easy for others to discover my 
identity.
 ShortOption.parseError=Cannot parse value as a string array: ${error}
 ShortOption.parseError=The value specified can't be parsed as a 16-bit integer 
: ${val}
 SimpleToadletServer.advancedMode=Enable Advanced Mode?

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2008-09-02 20:27:10 UTC (rev 
22361)
+++ trunk/freenet/src/freenet/node/Node.java    2008-09-02 22:43:59 UTC (rev 
22362)
@@ -471,6 +471,8 @@
        /** NodeUpdater **/
        public final NodeUpdateManager nodeUpdater;

+       public final SecurityLevels securityLevels;
+       
        // Things that's needed to keep track of
        public final PluginManager pluginManager;

@@ -753,6 +755,8 @@
                runningCHKOfferReplyUIDs = new HashSet();
                runningSSKOfferReplyUIDs = new HashSet();

+               this.securityLevels = new SecurityLevels(this, config);
+               
                // Directory for node-related files other than store

                nodeConfig.register("nodeDir", ".", sortOrder++, true, true /* 
because can't be changed on the fly, also for packages */, "Node.nodeDir", 
"Node.nodeDirLong", 

Added: trunk/freenet/src/freenet/node/SecurityLevelListener.java
===================================================================
--- trunk/freenet/src/freenet/node/SecurityLevelListener.java                   
        (rev 0)
+++ trunk/freenet/src/freenet/node/SecurityLevelListener.java   2008-09-02 
22:43:59 UTC (rev 22362)
@@ -0,0 +1,7 @@
+package freenet.node;
+
+public interface SecurityLevelListener<T> {
+       
+       public void onChange(T oldLevel, T newLevel);
+
+}

Added: trunk/freenet/src/freenet/node/SecurityLevels.java
===================================================================
--- trunk/freenet/src/freenet/node/SecurityLevels.java                          
(rev 0)
+++ trunk/freenet/src/freenet/node/SecurityLevels.java  2008-09-02 22:43:59 UTC 
(rev 22362)
@@ -0,0 +1,198 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.node;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import freenet.config.EnumerableOptionCallback;
+import freenet.config.InvalidConfigValueException;
+import freenet.config.NodeNeedRestartException;
+import freenet.config.PersistentConfig;
+import freenet.config.SubConfig;
+import freenet.support.Logger;
+import freenet.support.api.StringCallback;
+
+/**
+ * We have 3 basic security settings. The user chooses these in the first-time 
+ * wizard, and can reconfigure them at any time. Each impacts on many other
+ * config settings, changing their defaults and changing their values when the
+ * security level changes, but the user can change those options independantly 
if
+ * they do not change the security level. These options are important, and 
there
+ * are explanations of every option for each setting. They have their own 
+ * sub-page on the config toadlet. And the security levels are displayed on the
+ * homepage as a useralert (instead of the opennet warning).
+ * @author Matthew Toseland <toad at amphibian.dyndns.org> (0xE43DA450)
+ */
+public class SecurityLevels {
+       
+       public enum NETWORK_THREAT_LEVEL {
+               HIGH, // paranoid, darknet only
+               NORMAL, // normal setting, darknet/opennet hybrid
+               LOW // turn off every performance impacting security measure
+       }
+       
+       public enum FRIENDS_THREAT_LEVEL {
+               HIGH, // Share no/minimal information and take measures to 
reduce harm if Friends are compromized
+               NORMAL, // Share some information
+               LOW // Friends are ultimately trusted
+       }
+       
+       public enum PHYSICAL_THREAT_LEVEL {
+               NORMAL, // Encrypt temp files etc etc
+               LOW // Don't encrypt temp files etc etc
+       }
+       
+       NETWORK_THREAT_LEVEL networkThreatLevel;
+       FRIENDS_THREAT_LEVEL friendsThreatLevel;
+       PHYSICAL_THREAT_LEVEL physicalThreatLevel;
+       
+       private MyCallback<NETWORK_THREAT_LEVEL> networkThreatLevelCallback;
+       private MyCallback<FRIENDS_THREAT_LEVEL> friendsThreatLevelCallback;
+       private MyCallback<PHYSICAL_THREAT_LEVEL> physicalThreatLevelCallback;
+       
+       public SecurityLevels(Node node, PersistentConfig config) {
+               SubConfig myConfig = new SubConfig("security-levels", config);
+               int sortOrder = 0;
+               networkThreatLevelCallback = new 
MyCallback<NETWORK_THREAT_LEVEL>() {
+
+                       @Override
+                       public String get() {
+                               return networkThreatLevel.name();
+                       }
+
+                       public String[] getPossibleValues() {
+                               NETWORK_THREAT_LEVEL[] values = 
NETWORK_THREAT_LEVEL.values();
+                               String[] names = new String[values.length];
+                               for(int i=0;i<names.length;i++)
+                                       names[i] = values[i].name();
+                               return names;
+                       }
+
+                       @Override
+                       protected NETWORK_THREAT_LEVEL getValue() {
+                               return networkThreatLevel;
+                       }
+
+                       @Override
+                       protected void setValue(String val) throws 
InvalidConfigValueException {
+                               NETWORK_THREAT_LEVEL newValue = 
NETWORK_THREAT_LEVEL.valueOf(val);
+                               if(newValue != null)
+                                       throw new 
InvalidConfigValueException("Invalid value for network threat level: "+val);
+                       }
+
+               };
+               myConfig.register("networkThreatLevel", "NORMAL", sortOrder++, 
false, true, "SecurityLevels.networkThreatLevelShort", 
"SecurityLevels.networkThreatLevel", networkThreatLevelCallback);
+               networkThreatLevel = 
NETWORK_THREAT_LEVEL.valueOf(myConfig.getString("networkThreatLevel"));
+               friendsThreatLevelCallback = new 
MyCallback<FRIENDS_THREAT_LEVEL>() {
+
+                       @Override
+                       public String get() {
+                               return friendsThreatLevel.name();
+                       }
+
+                       public String[] getPossibleValues() {
+                               FRIENDS_THREAT_LEVEL[] values = 
FRIENDS_THREAT_LEVEL.values();
+                               String[] names = new String[values.length];
+                               for(int i=0;i<names.length;i++)
+                                       names[i] = values[i].name();
+                               return names;
+                       }
+
+                       @Override
+                       protected FRIENDS_THREAT_LEVEL getValue() {
+                               return friendsThreatLevel;
+                       }
+
+                       @Override
+                       protected void setValue(String val) throws 
InvalidConfigValueException {
+                               FRIENDS_THREAT_LEVEL newValue = 
FRIENDS_THREAT_LEVEL.valueOf(val);
+                               if(newValue != null)
+                                       throw new 
InvalidConfigValueException("Invalid value for friends threat level: "+val);
+                       }
+
+               };
+               myConfig.register("friendsThreatLevel", "NORMAL", sortOrder++, 
false, true, "SecurityLevels.friendsThreatLevelShort", 
"SecurityLevels.friendsThreatLevel", friendsThreatLevelCallback);
+               friendsThreatLevel = 
FRIENDS_THREAT_LEVEL.valueOf(myConfig.getString("friendsThreatLevel"));
+               physicalThreatLevelCallback = new 
MyCallback<PHYSICAL_THREAT_LEVEL>() {
+
+                       @Override
+                       public String get() {
+                               return physicalThreatLevel.name();
+                       }
+
+                       public String[] getPossibleValues() {
+                               PHYSICAL_THREAT_LEVEL[] values = 
PHYSICAL_THREAT_LEVEL.values();
+                               String[] names = new String[values.length];
+                               for(int i=0;i<names.length;i++)
+                                       names[i] = values[i].name();
+                               return names;
+                       }
+
+                       @Override
+                       protected PHYSICAL_THREAT_LEVEL getValue() {
+                               return physicalThreatLevel;
+                       }
+
+                       @Override
+                       protected void setValue(String val) throws 
InvalidConfigValueException {
+                               PHYSICAL_THREAT_LEVEL newValue = 
PHYSICAL_THREAT_LEVEL.valueOf(val);
+                               if(newValue != null)
+                                       throw new 
InvalidConfigValueException("Invalid value for physical threat level: "+val);
+                       }
+
+               };
+               myConfig.register("physicalThreatLevel", "NORMAL", sortOrder++, 
false, true, "SecurityLevels.physicalThreatLevelShort", 
"SecurityLevels.physicalThreatLevel", physicalThreatLevelCallback);
+               physicalThreatLevel = 
PHYSICAL_THREAT_LEVEL.valueOf(myConfig.getString("physicalThreatLevel"));
+       }
+       
+       public void 
addNetworkThreatLevelListener(SecurityLevelListener<NETWORK_THREAT_LEVEL> 
listener) {
+               networkThreatLevelCallback.addListener(listener);
+       }
+       
+       public void 
addFriendsThreatLevelListener(SecurityLevelListener<FRIENDS_THREAT_LEVEL> 
listener) {
+               friendsThreatLevelCallback.addListener(listener);
+       }
+       
+       public void 
addPhysicalThreatLevelListener(SecurityLevelListener<PHYSICAL_THREAT_LEVEL> 
listener) {
+               physicalThreatLevelCallback.addListener(listener);
+       }
+       
+       private abstract class MyCallback<T> extends StringCallback implements 
EnumerableOptionCallback {
+
+               private ArrayList<SecurityLevelListener<T>> listeners;
+               
+               public void addListener(SecurityLevelListener<T> listener) {
+                       if(listeners.contains(listener)) {
+                               Logger.error(this, "Already have listener 
"+listener+" in "+this);
+                               return;
+                       }
+                       listeners.add(listener);
+               }
+               
+               public void setPossibleValues(String[] val) {
+                       throw new UnsupportedOperationException();
+               }
+               
+               @Override
+               public void set(String val) throws InvalidConfigValueException, 
NodeNeedRestartException {
+                       T oldLevel = getValue();
+                       setValue(val);
+                       T newLevel = getValue();
+                       for(SecurityLevelListener<T> listener : listeners) {
+                               listener.onChange(oldLevel, newLevel);
+                       }
+               }
+
+               protected abstract void setValue(String val) throws 
InvalidConfigValueException;
+
+               protected abstract T getValue();
+               
+       }
+
+       public NETWORK_THREAT_LEVEL getNetworkThreatLevel() {
+               return networkThreatLevel;
+       }
+       
+}


Reply via email to