diff options
author | David Barksdale <amatus.amongus@gmail.com> | 2010-10-10 20:38:29 -0700 |
---|---|---|
committer | David Barksdale <amatus.amongus@gmail.com> | 2010-10-10 20:38:29 -0700 |
commit | 38345495f9f0b8370f2a47ffb04b38d486d7b3c9 (patch) | |
tree | 7dfdfe1388898972aa9c5920daaebf2f648fd270 /src | |
parent | bee80f0989c090de9e72adb7af130a69bc92cdb5 (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.clj | 17 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/message.clj | 3 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/transport.clj | 108 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/udp.clj | 7 |
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] |