summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Barksdale <amatus.amongus@gmail.com>2010-10-10 20:38:29 -0700
committerDavid Barksdale <amatus.amongus@gmail.com>2010-10-10 20:38:29 -0700
commit38345495f9f0b8370f2a47ffb04b38d486d7b3c9 (patch)
tree7dfdfe1388898972aa9c5920daaebf2f648fd270 /src
parentbee80f0989c090de9e72adb7af130a69bc92cdb5 (diff)
We now handle incoming HELLO and PONG messages and verify addresses accordingly!
Diffstat (limited to 'src')
-rw-r--r--src/org/gnu/clojure/gnunet/crypto.clj17
-rw-r--r--src/org/gnu/clojure/gnunet/message.clj3
-rw-r--r--src/org/gnu/clojure/gnunet/transport.clj108
-rw-r--r--src/org/gnu/clojure/gnunet/udp.clj7
4 files changed, 125 insertions, 10 deletions
diff --git a/src/org/gnu/clojure/gnunet/crypto.clj b/src/org/gnu/clojure/gnunet/crypto.clj
index 4d4e92f..43688ee 100644
--- a/src/org/gnu/clojure/gnunet/crypto.clj
+++ b/src/org/gnu/clojure/gnunet/crypto.clj
@@ -1,11 +1,13 @@
(ns org.gnu.clojure.gnunet.crypto
(:use (org.gnu.clojure.gnunet parser message)
clojure.contrib.monads)
- (:import (java.security KeyPairGenerator KeyFactory MessageDigest)
+ (:import (java.security KeyPairGenerator KeyFactory MessageDigest Signature)
(java.security.spec RSAKeyGenParameterSpec RSAPublicKeySpec
RSAPrivateCrtKeySpec)
(java.math.BigInteger)))
+(def signature-size 256)
+
(defn generate-rsa-keypair
"Generate a 2048 bit RSA keypair."
[]
@@ -28,6 +30,19 @@
keyspec (RSAPrivateCrtKeySpec. n e d p q dp dq u)]
(.generatePrivate keyfactory keyspec)))
+(defn rsa-sign
+ [private-key bytes]
+ (.sign (doto (Signature/getInstance "SHA512withRSA")
+ (.initSign private-key)
+ (.update (byte-array bytes)))))
+
+(defn rsa-verify
+ [public-key bytes signature]
+ (.verify (doto (Signature/getInstance "SHA512withRSA")
+ (.initVerify public-key)
+ (.update (byte-array bytes)))
+ (byte-array signature)))
+
(defn sha-512
"Compute the SHA-512 digest of a sequence of bytes."
[x]
diff --git a/src/org/gnu/clojure/gnunet/message.clj b/src/org/gnu/clojure/gnunet/message.clj
index 3266e0a..7a7bf3f 100644
--- a/src/org/gnu/clojure/gnunet/message.clj
+++ b/src/org/gnu/clojure/gnunet/message.clj
@@ -46,6 +46,9 @@
(def parse-uint32
(domonad parser-m [xs (items 4)] (long (decode-uint xs))))
+(def parse-int32
+ (domonad parser-m [xs (items 4)] (.intValue (decode-uint xs))))
+
(def parse-uint64
(domonad parser-m [xs (items 8)] (decode-uint xs)))
diff --git a/src/org/gnu/clojure/gnunet/transport.clj b/src/org/gnu/clojure/gnunet/transport.clj
index 4800a06..12c6d00 100644
--- a/src/org/gnu/clojure/gnunet/transport.clj
+++ b/src/org/gnu/clojure/gnunet/transport.clj
@@ -1,9 +1,14 @@
(ns org.gnu.clojure.gnunet.transport
- (:use (org.gnu.clojure.gnunet parser message hello peer util)
+ (:use (org.gnu.clojure.gnunet parser message hello peer util crypto)
clojure.contrib.monads)
(:import (java.util Date Calendar)))
+(defn hello-address-expiration
+ []
+ (.getTime (doto (Calendar/getInstance) (.add Calendar/HOUR_OF_DAY 12))))
+
(def message-type-ping 32)
+(def message-type-pong 33)
(defn encode-ping
[ping]
@@ -25,6 +30,51 @@
:transport transport
:encoded-address encoded-address}))
+(defn encode-pong
+ [pong]
+ (let [transport (encode-utf8 (:transport pong))
+ address-length (+ (count transport) (count (:encoded-address pong)))]
+ (concat
+ (encode-int32 (:challenge pong))
+ (:signature pong)
+ (encode-int32 (:signature-size pong))
+ (encode-int32 (:signature-purpose pong))
+ (encode-date (:expiration pong))
+ (:peer-id pong)
+ (encode-int32 address-length)
+ transport
+ (:encoded-address pong))))
+
+(def signature-purpose-transport-pong-own 1)
+(def signature-purpose-transport-pong-using 2)
+(def pong-signature-offset (+ 4 signature-size))
+
+(def parse-pong
+ (domonad parser-m [challenge parse-int32
+ signature (items signature-size)
+ signature-size parse-uint32
+ signature-purpose parse-uint32
+ expiration parse-date
+ peer-id (items id-size)
+ address-length parse-uint32
+ transport parse-utf8
+ :when (>= address-length (count (encode-utf8 transport)))
+ encoded-address (items
+ (- address-length
+ (count (encode-utf8 transport))))
+ :when (= signature-size
+ (+ 4 4 8 id-size 4 address-length))
+ residue (none-or-more item)
+ :when (= 0 (count residue))]
+ {:challenge challenge
+ :signature signature
+ :signature-size signature-size
+ :signature-purpose signature-purpose
+ :expiration expiration
+ :peer-id peer-id
+ :transport transport
+ :encoded-address encoded-address}))
+
(defn list-transport-addresses
"Generate a list of transport descriptions."
[addresses-map]
@@ -142,9 +192,14 @@
[peer hello]
(let [peer-id (generate-id (:public-key hello))]
(if (not (= peer-id (:id peer)))
- (do
- (send (:remote-peers-agent peer) update-remote-peers peer-id hello)
- (send (:remote-peers-agent peer) verify-remote-peers peer)))))
+ (let [remote-peers-agent (:remote-peers-agent peer)]
+ (send remote-peers-agent update-remote-peers peer-id hello)
+ (send remote-peers-agent verify-remote-peers peer)))))
+
+(defn handle-hello!
+ [peer message]
+ (when-let [hello (first (parse-hello (:bytes message)))]
+ (admit-hello! peer hello)))
(defn best-transport
[peer remote-peer]
@@ -172,6 +227,44 @@
(conj {:transport transport :address address}
((:connect! transport) peer remote-peer address)))))))
+(defn handle-ping!
+ [peer sender-id source-address message]
+
+ )
+
+(defn check-pending-validation
+ [addresses remote-peer pong encoded-pong]
+ (if-let [transport (addresses (:transport pong))]
+ (if-let [address (transport (:encoded-address pong))]
+ (cond
+ (not (= (:challenge address) (:challenge pong)))
+ addresses
+ (= signature-purpose-transport-pong-own (:signature-purpose pong))
+ (if (rsa-verify (:public-key remote-peer)
+ (drop pong-signature-offset encoded-pong)
+ (:signature pong))
+ (assoc addresses (:transport pong)
+ (assoc transport (:encoded-address pong)
+ {:expiration (hello-address-expiration)
+ :latency (- (.getTime (Date.))
+ (.getTime (:send-time address)))}))
+ addresses)
+ (= signature-purpose-transport-pong-using (:signature-purpose pong))
+ ;; TODO - fill in this case
+ addresses
+ :else addresses)
+ addresses)
+ addresses))
+
+(defn handle-pong!
+ [peer sender-id source-address message]
+ (when-let [pong (first (parse-pong (:bytes message)))]
+ (if (>= 0 (.compareTo (Date.) (:expiration pong)))
+ (when-let [remote-peer ((deref (:remote-peers-agent peer))
+ (:peer-id pong))]
+ (send (:transport-addresses-agent remote-peer) check-pending-validation
+ remote-peer pong (:bytes message))))))
+
(defn admit-message!
[peer sender-id source-address message]
(let [string-builder (StringBuilder. "Received message type ")]
@@ -181,4 +274,9 @@
(.append string-builder " id ")
(.append string-builder sender-id)
(.append string-builder "\n")
- (.write *out* (.toString string-builder))))
+ (.write *out* (.toString string-builder)))
+ (condp = (:message-type message)
+ message-type-hello (handle-hello! peer message)
+ message-type-ping (handle-ping! peer sender-id source-address message)
+ message-type-pong (handle-pong! peer sender-id source-address message)
+ nil))
diff --git a/src/org/gnu/clojure/gnunet/udp.clj b/src/org/gnu/clojure/gnunet/udp.clj
index ad1b413..b84aec4 100644
--- a/src/org/gnu/clojure/gnunet/udp.clj
+++ b/src/org/gnu/clojure/gnunet/udp.clj
@@ -29,8 +29,8 @@
{:sender-id (:id peer) :messages messages})}))
(defn configure-udp-addresses!
- "Adds new addresses for the udp transport to peer's transports-agent expiring
- in 12 hours and removes expired addresses."
+ "Adds new addresses for the udp transport to peer's transports-agent and
+ removes expired addresses."
[peer reachable-addresses port]
(send (:transport-addresses-agent peer)
(fn [addresses]
@@ -41,8 +41,7 @@
{:transport "udp"
:encoded-address (encode-address (InetSocketAddress. address
port))
- :expiration (.getTime (doto (Calendar/getInstance)
- (.add Calendar/HOUR_OF_DAY 12)))})))))))
+ :expiration (hello-address-expiration)})))))))
(defn emit-messages-udp!
[peer transport encoded-address messages]