Author: nextgens
Date: 2006-09-05 14:14:13 +0000 (Tue, 05 Sep 2006)
New Revision: 10395

Added:
   
trunk/freenet/src/freenet/io/comm/ReferenceSignatureVerificationException.java
Modified:
   trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/PeerManager.java
   trunk/freenet/src/freenet/node/PeerNode.java
   trunk/freenet/src/freenet/node/TextModeClientInterface.java
   trunk/freenet/src/freenet/node/fcp/AddPeer.java
Log:
Implement most of #51: Reference signature

Maybe error messages ought to be polished ... 
It's probably possible to improve the cache mechanism on Node.exportFieldSet() 
...
So far it hasn't broken anything for me, but it has to be reviewed carefully!

Modified: trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2006-09-05 13:29:07 UTC (rev 10394)
+++ trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2006-09-05 14:14:13 UTC (rev 10395)
@@ -20,6 +20,7 @@
 import freenet.client.HighLevelSimpleClient;
 import freenet.io.comm.IOStatisticCollector;
 import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
 import freenet.node.FSParseException;
 import freenet.node.Node;
 import freenet.node.NodeClientCore;
@@ -586,6 +587,9 @@
                        } catch (PeerParseException e1) {
                                this.sendErrorPage(ctx, 200, "Failed To Add 
Node", "Unable to parse the given text as a node reference. Please try again.");
                                return;
+                       } catch (ReferenceSignatureVerificationException e1){
+                               this.sendErrorPage(ctx, 200, "Failed To Add 
Node", "Unable to verify the signature of the given reference.");
+                               return;
                        }
                        if(pn.getIdentityHash()==node.getIdentityHash()) {
                                this.sendErrorPage(ctx, 200, "Failed To Add 
Node", "You can\u2019t add your own node to the list of remote peers.");

Added: 
trunk/freenet/src/freenet/io/comm/ReferenceSignatureVerificationException.java
===================================================================
--- 
trunk/freenet/src/freenet/io/comm/ReferenceSignatureVerificationException.java  
    2006-09-05 13:29:07 UTC (rev 10394)
+++ 
trunk/freenet/src/freenet/io/comm/ReferenceSignatureVerificationException.java  
    2006-09-05 14:14:13 UTC (rev 10395)
@@ -0,0 +1,21 @@
+package freenet.io.comm;
+
+/**
+ * Thown when we can't parse a string to a Peer.
+ * @author amphibian
+ */
+public class ReferenceSignatureVerificationException extends Exception {
+       private static final long serialVersionUID = -1;
+    public ReferenceSignatureVerificationException(Exception e) {
+        super(e);
+    }
+
+    public ReferenceSignatureVerificationException() {
+        super();
+    }
+
+       public ReferenceSignatureVerificationException(String string) {
+               super(string);
+       }
+
+}

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-09-05 13:29:07 UTC (rev 
10394)
+++ trunk/freenet/src/freenet/node/Node.java    2006-09-05 14:14:13 UTC (rev 
10395)
@@ -17,6 +17,7 @@
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.MalformedURLException;
 import java.net.UnknownHostException;
@@ -39,9 +40,11 @@
 import freenet.config.LongCallback;
 import freenet.config.StringCallback;
 import freenet.config.SubConfig;
+import freenet.crypt.DSA;
 import freenet.crypt.DSAGroup;
 import freenet.crypt.DSAPrivateKey;
 import freenet.crypt.DSAPublicKey;
+import freenet.crypt.DSASignature;
 import freenet.crypt.Global;
 import freenet.crypt.RandomSource;
 import freenet.io.comm.DMT;
@@ -332,8 +335,12 @@
        /** Hash of identity. Used as setup key. */
        byte[] identityHash;
        /** Hash of hash of identity i.e. hash of setup key. */
-       byte[] identityHashHash; 
-       String myName;
+       byte[] identityHashHash;        
+       /** The signature of the above fieldset */
+       private DSASignature myReferenceSignature = null;
+       /** An ordered version of the FieldSet, without the signature */
+       private String mySignedReference = null;
+       private String myName;
        final LocationManager lm;
        final PeerManager peers; // my peers
        /** Directory to put node, peers, etc into */
@@ -1649,6 +1656,14 @@
                fs.put("dsaPubKey", myPubKey.asFieldSet());
                fs.put("ark.number", Long.toString(this.myARKNumber));
                fs.put("ark.pubURI", this.myARK.getURI().toString(false));
+               
+               // TODO: maybe synchronize ?
+               if(myReferenceSignature == null || mySignedReference == null || 
!mySignedReference.equals(fs.toOrderedString())){
+                       mySignedReference = fs.toOrderedString();
+                       myReferenceSignature = DSA.sign(myCryptoGroup, 
myPrivKey, new BigInteger(mySignedReference.getBytes()), random);
+               }
+               fs.put("sig", myReferenceSignature.toString());
+               
                if(logMINOR) Logger.minor(this, "My reference: "+fs);
                return fs;
        }

Modified: trunk/freenet/src/freenet/node/PeerManager.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerManager.java     2006-09-05 13:29:07 UTC 
(rev 10394)
+++ trunk/freenet/src/freenet/node/PeerManager.java     2006-09-05 14:14:13 UTC 
(rev 10395)
@@ -18,6 +18,7 @@
 import freenet.io.comm.NotConnectedException;
 import freenet.io.comm.Peer;
 import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
 import freenet.node.useralerts.PeerManagerUserAlert;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
@@ -111,7 +112,10 @@
                 } catch (PeerParseException e2) {
                     Logger.error(this, "Could not parse peer: 
"+e2+"\n"+fs.toString(),e2);
                     continue;
-                }
+                } catch (ReferenceSignatureVerificationException e2) {
+                       Logger.error(this, "Could not parse peer: 
"+e2+"\n"+fs.toString(),e2);
+                    continue;
+                               }
                 addPeer(pn);
                 gotSome = true;
             }
@@ -276,7 +280,7 @@
     /**
      * Connect to a node provided the fieldset representing it.
      */
-    public void connect(SimpleFieldSet noderef) throws FSParseException, 
PeerParseException {
+    public void connect(SimpleFieldSet noderef) throws FSParseException, 
PeerParseException, ReferenceSignatureVerificationException {
         PeerNode pn = new PeerNode(noderef, node, false);
         for(int i=0;i<myPeers.length;i++) {
             if(Arrays.equals(myPeers[i].identity, pn.identity)) return;

Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java        2006-09-05 13:29:07 UTC 
(rev 10394)
+++ trunk/freenet/src/freenet/node/PeerNode.java        2006-09-05 14:14:13 UTC 
(rev 10395)
@@ -12,6 +12,7 @@
 import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
+import java.math.BigInteger;
 import java.net.MalformedURLException;
 import java.net.UnknownHostException;
 import java.security.MessageDigest;
@@ -28,6 +29,10 @@
 import freenet.client.async.USKRetriever;
 import freenet.client.async.USKRetrieverCallback;
 import freenet.crypt.BlockCipher;
+import freenet.crypt.DSA;
+import freenet.crypt.DSAGroup;
+import freenet.crypt.DSAPublicKey;
+import freenet.crypt.DSASignature;
 import freenet.crypt.DiffieHellmanContext;
 import freenet.crypt.UnsupportedCipherException;
 import freenet.crypt.ciphers.Rijndael;
@@ -40,6 +45,7 @@
 import freenet.io.comm.Peer;
 import freenet.io.comm.PeerContext;
 import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
 import freenet.keys.ClientSSK;
 import freenet.keys.FreenetURI;
 import freenet.keys.USK;
@@ -206,6 +212,14 @@
     /** Version of the node */
     private String version;

+    /** Peer node crypto group */
+    private DSAGroup peerCryptoGroup;
+
+    /** Peer node public key */
+    private DSAPublicKey peerPubKey;
+    
+    private boolean isSignatureVerificationSuccessfull;
+    
     /** Incoming setup key. Used to decrypt incoming auth packets.
      * Specifically: K_node XOR H(setupKey).
      */
@@ -308,7 +322,7 @@
      * @param fs The SimpleFieldSet to parse
      * @param node2 The running Node we are part of.
      */
-    public PeerNode(SimpleFieldSet fs, Node node2, boolean fromLocal) throws 
FSParseException, PeerParseException {
+    public PeerNode(SimpleFieldSet fs, Node node2, boolean fromLocal) throws 
FSParseException, PeerParseException, ReferenceSignatureVerificationException {
        logMINOR = Logger.shouldLog(Logger.MINOR, this);
         this.node = node2;
         String identityString = fs.get("identity");
@@ -378,6 +392,28 @@
                detectedPeer = (Peer) nominalPeer.firstElement();
         }

+        /* Read the DSA key material for the peer */
+        try {
+               this.peerCryptoGroup = DSAGroup.create(fs.subset("dsaGroup"));
+               this.peerPubKey = DSAPublicKey.create(fs.subset("dsaPubKey"), 
peerCryptoGroup);
+               String signature = fs.get("sig");
+               fs.removeValue("sig");
+               this.isSignatureVerificationSuccessfull = 
DSA.verify(peerPubKey, new DSASignature(signature), new 
BigInteger(fs.toOrderedString().getBytes()));
+               if(!isSignatureVerificationSuccessfull){
+                       Logger.error(this, "The integrity of the reference has 
been compromized!");
+                       throw new ReferenceSignatureVerificationException("The 
integrity of the reference has been compromized!");
+               }
+        } catch (IllegalBase64Exception e) {
+               Logger.error(this, "Caught "+e, e);
+               throw new FSParseException(e);
+        } catch (NullPointerException npe){
+               /* FIXME: REMOVE: backward compatibility hack */
+               Logger.normal(this, "Probably trying to add an old reference : 
"+npe);
+               this.isSignatureVerificationSuccessfull=false;
+        }
+
+        /* FIXME: All the following is useless once we have definitely 
switched to STS! */
+        
         // Setup incoming and outgoing setup ciphers
         byte[] nodeKey = node.identityHash;
         byte[] nodeKeyHash = node.identityHashHash;
@@ -1829,6 +1865,8 @@
         fs.put("testnet", Boolean.toString(testnetEnabled));
         fs.put("version", version);
         fs.put("myName", getName());
+        fs.put("dsaGroup", peerCryptoGroup.asFieldSet());
+        fs.put("dsaPubKey", peerPubKey.asFieldSet());
                if(myARK != null) {
                        // Decrement it because we keep the number we would 
like to fetch, not the last one fetched.
                        fs.put("ark.number", 
Long.toString(myARK.suggestedEdition - 1));
@@ -2852,4 +2890,8 @@
        public synchronized long getTotalOutputBytes() {
                return totalBytesOut;
        }
+
+       public boolean isSignatureVerificationSuccessfull() {
+               return isSignatureVerificationSuccessfull;
+       }
 }

Modified: trunk/freenet/src/freenet/node/TextModeClientInterface.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-09-05 
13:29:07 UTC (rev 10394)
+++ trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-09-05 
14:14:13 UTC (rev 10395)
@@ -30,6 +30,7 @@
 import freenet.crypt.RandomSource;
 import freenet.io.comm.Peer;
 import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
 import freenet.keys.FreenetURI;
 import freenet.keys.InsertableClientSSK;
 import freenet.support.HexUtil;
@@ -608,7 +609,7 @@
             addPeer(content);

         } else if(uline.startsWith("NAME:")) {
-            outsb.append("Node name currently: "+n.myName);
+            outsb.append("Node name currently: 
"+n.config.get("node").getOption("name").getValueString());
             String key = line.substring("NAME:".length());
             while((key.length() > 0) && (key.charAt(0) == ' '))
                 key = key.substring(1);
@@ -905,7 +906,11 @@
             System.err.println("Did not parse: "+e1);
             Logger.error(this, "Did not parse: "+e1, e1);
             return;
-        }
+        } catch (ReferenceSignatureVerificationException e1) {
+               System.err.println("Did not parse: "+e1);
+            Logger.error(this, "Did not parse: "+e1, e1);
+            return;
+               }
         if(n.peers.addPeer(pn))
             System.out.println("Added peer: "+pn);
         n.peers.writePeers();

Modified: trunk/freenet/src/freenet/node/fcp/AddPeer.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/AddPeer.java     2006-09-05 13:29:07 UTC 
(rev 10394)
+++ trunk/freenet/src/freenet/node/fcp/AddPeer.java     2006-09-05 14:14:13 UTC 
(rev 10395)
@@ -11,6 +11,7 @@
 import java.net.URLConnection;

 import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
 import freenet.node.FSParseException;
 import freenet.node.Node;
 import freenet.node.PeerNode;
@@ -107,6 +108,9 @@
                        throw new 
MessageInvalidException(ProtocolErrorMessage.REF_PARSE_ERROR, "Error parsing 
retrieved ref: "+e.getMessage(), null);
                } catch (PeerParseException e) {
                        throw new 
MessageInvalidException(ProtocolErrorMessage.REF_PARSE_ERROR, "Error parsing 
retrieved ref: "+e.getMessage(), null);
+               } catch (ReferenceSignatureVerificationException e) {
+                       // TODO: maybe a special ProtocolErrorMessage ?
+                       throw new 
MessageInvalidException(ProtocolErrorMessage.REF_PARSE_ERROR, "Error parsing 
retrieved ref: "+e.getMessage(), null);
                }
                // **FIXME** Handle duplicates somehow maybe?  What about when 
node.addDarknetConnection() fails for some reason?
                if(node.addDarknetConnection(pn))


Reply via email to