├── .gitignore ├── .travis.yml ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── cjdrs ├── address.rs ├── config.rs ├── crypto.rs ├── device │ ├── mod.rs │ ├── tun.rs │ └── udp.rs ├── encoding_scheme │ ├── fixed4.rs │ ├── fixed8.rs │ ├── mod.rs │ ├── variable3x5x8.rs │ └── variable4x8.rs ├── error.rs ├── event_handler.rs ├── identity.rs ├── lib.rs ├── macros.rs ├── packet │ ├── cryptoauth.rs │ ├── ipv6.rs │ ├── mod.rs │ └── tun.rs ├── route.rs ├── router.rs └── util │ ├── base32.rs │ ├── big_endian.rs │ ├── debug.rs │ └── mod.rs └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | cjdrs.conf 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | sudo: false 3 | install: 4 | - wget http://download.libsodium.org/libsodium/releases/libsodium-1.0.2.tar.gz 5 | - tar -zxvf libsodium-1.0.2.tar.gz 6 | - cd libsodium-1.0.2 && ./configure --prefix=$PWD/install && make && make check && make install 7 | - export CPATH=$CPATH:$PWD/install/include 8 | - export LIBRARY_PATH=$LIBRARY_PATH:$PWD/install/lib 9 | - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/install/lib 10 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [root] 2 | name = "cjdrs" 3 | version = "0.0.1" 4 | dependencies = [ 5 | "docopt 0.6.32 (git+git://github.com/docopt/docopt.rs)", 6 | "mio 0.0.1 (git+https://github.com/carllerche/mio.git)", 7 | "rustc-serialize 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", 8 | "sodiumoxide 0.0.1 (git+https://github.com/dnaq/sodiumoxide.git)", 9 | "tuntap 0.0.1 (git+https://github.com/Randati/tuntap-rust.git)", 10 | ] 11 | 12 | [[package]] 13 | name = "bitflags" 14 | version = "0.1.0" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | 17 | [[package]] 18 | name = "docopt" 19 | version = "0.6.32" 20 | source = "git+git://github.com/docopt/docopt.rs#35a5b9de2dc9962f6b3649fb2a63a5aa41722db0" 21 | dependencies = [ 22 | "regex 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", 23 | "rustc-serialize 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", 24 | ] 25 | 26 | [[package]] 27 | name = "gcc" 28 | version = "0.1.7" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | 31 | [[package]] 32 | name = "libc" 33 | version = "0.1.1" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | 36 | [[package]] 37 | name = "libsodium-sys" 38 | version = "0.0.1" 39 | source = "git+https://github.com/dnaq/sodiumoxide.git#93046df7c37ed8eadb41b074d3bf32e2d20ac2a8" 40 | 41 | [[package]] 42 | name = "log" 43 | version = "0.2.1" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | 46 | [[package]] 47 | name = "mio" 48 | version = "0.0.1" 49 | source = "git+https://github.com/carllerche/mio.git#977ec309fb5accbb069351301067840648c6ab9e" 50 | dependencies = [ 51 | "bitflags 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 52 | "log 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 53 | "nix 0.1.2 (git+https://github.com/carllerche/nix-rust)", 54 | "time 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", 55 | ] 56 | 57 | [[package]] 58 | name = "nix" 59 | version = "0.1.2" 60 | source = "git+https://github.com/carllerche/nix-rust#3743a257c69ee45656cbfbbf0d0e853145dbf55f" 61 | dependencies = [ 62 | "bitflags 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 63 | ] 64 | 65 | [[package]] 66 | name = "regex" 67 | version = "0.1.11" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | 70 | [[package]] 71 | name = "rustc-serialize" 72 | version = "0.2.10" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | 75 | [[package]] 76 | name = "sodiumoxide" 77 | version = "0.0.1" 78 | source = "git+https://github.com/dnaq/sodiumoxide.git#93046df7c37ed8eadb41b074d3bf32e2d20ac2a8" 79 | dependencies = [ 80 | "libsodium-sys 0.0.1 (git+https://github.com/dnaq/sodiumoxide.git)", 81 | ] 82 | 83 | [[package]] 84 | name = "time" 85 | version = "0.1.15" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | dependencies = [ 88 | "gcc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 89 | "libc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 90 | ] 91 | 92 | [[package]] 93 | name = "tuntap" 94 | version = "0.0.1" 95 | source = "git+https://github.com/Randati/tuntap-rust.git#2e36271f23c082d6c6c8437a8504693948e44eed" 96 | 97 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cjdrs" 3 | version = "0.0.1" 4 | authors = ["Vanhala Antti "] 5 | license = "MIT" 6 | 7 | [lib] 8 | name = "cjdrs" 9 | path = "src/cjdrs/lib.rs" 10 | 11 | [[bin]] 12 | name = "cjdrs" 13 | doc = false 14 | 15 | [dependencies] 16 | rustc-serialize = "*" 17 | 18 | [dependencies.tuntap] 19 | git = "https://github.com/Randati/tuntap-rust.git" 20 | 21 | [dependencies.sodiumoxide] 22 | git = "https://github.com/dnaq/sodiumoxide.git" 23 | 24 | [dependencies.mio] 25 | git = "https://github.com/carllerche/mio.git" 26 | 27 | [dependencies.docopt] 28 | git = "git://github.com/docopt/docopt.rs" 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2015 Antti Vanhala 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cjdrs – cjdns implementation in Rust 2 | 3 | [![Build Status](https://travis-ci.org/Randati/cjdrs.svg)](https://travis-ci.org/Randati/cjdrs) 4 | 5 | cjdrs will be an implementation of the [cjdns](https://github.com/cjdelisle/cjdns/) protocol. Currently very much incomplete and not usable in any way. 6 | 7 | * [cjdns on GitHub](https://github.com/cjdelisle/cjdns/) 8 | * [cjdns on Wikipedia](https://en.wikipedia.org/wiki/Cjdns) 9 | 10 | ## Getting it up and running 11 | ```shell 12 | # Install Rust and Cargo 13 | curl -s https://static.rust-lang.org/rustup.sh | sudo sh 14 | 15 | # Install libsodium 16 | wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.2.tar.gz 17 | tar -zxvf libsodium-1.0.2.tar.gz 18 | cd libsodium-1.0.2 19 | ./configure --prefix=/usr 20 | make && make check 21 | sudo make install 22 | cd .. 23 | 24 | # Clone repository 25 | git clone https://github.com/Randati/cjdrs.git 26 | cd cjdrs 27 | 28 | cargo build # Build 29 | cargo test # Run tests 30 | ./target/cjdrs init # Generate configuration file 31 | editor cjdrs.conf # Edit configuration 32 | sudo ./target/cjdrs run # Run 33 | ``` 34 | -------------------------------------------------------------------------------- /src/cjdrs/address.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::mem; 3 | use std::num::Int; 4 | use std::cmp::Ordering; 5 | use std::slice::bytes::copy_memory; 6 | use sodiumoxide::crypto::hash::sha512; 7 | use PublicKey; 8 | 9 | const ADDRESS_SIZE: usize = 16; 10 | 11 | 12 | #[derive(Copy, Clone, Eq, PartialEq, Hash)] 13 | pub struct Address { 14 | bytes: [u8; ADDRESS_SIZE] 15 | } 16 | 17 | impl Address { 18 | pub fn is_valid(slice: &[u8]) -> bool { 19 | assert_eq!(slice.len(), ADDRESS_SIZE); 20 | slice[0] == 0xFC 21 | } 22 | 23 | pub fn from_bytes(bytes: &[u8; ADDRESS_SIZE]) -> Option
{ 24 | if Address::is_valid(bytes.as_slice()) { 25 | Some(Address { bytes: *bytes }) 26 | } else { 27 | None 28 | } 29 | } 30 | 31 | pub fn from_slice(slice: &[u8]) -> Option
{ 32 | if Address::is_valid(slice) { 33 | let mut bytes = [0u8; ADDRESS_SIZE]; 34 | copy_memory(&mut bytes, slice); 35 | Some(Address { bytes: bytes }) 36 | } else { 37 | None 38 | } 39 | } 40 | 41 | pub fn from_public_key(public_key: &PublicKey) -> Option
{ 42 | let first_sha = sha512::hash(public_key.as_slice()); 43 | let second_sha = sha512::hash(first_sha.as_slice()); 44 | let raw_address = &second_sha.as_slice()[..ADDRESS_SIZE]; 45 | Address::from_slice(raw_address) 46 | } 47 | 48 | pub fn as_slice(&self) -> &[u8] { 49 | self.bytes.as_slice() 50 | } 51 | 52 | 53 | #[inline] 54 | pub fn as_u64_be(&self) -> [u64; 2] { 55 | [ 56 | unsafe { *mem::transmute::<*const u8, *const u64>((&self.bytes[0..]).as_ptr()) }.to_be(), 57 | unsafe { *mem::transmute::<*const u8, *const u64>((&self.bytes[8..]).as_ptr()) }.to_be(), 58 | ] 59 | } 60 | 61 | #[inline] 62 | pub fn as_u32_be(&self) -> [u32; 4] { 63 | [ 64 | unsafe { *mem::transmute::<*const u8, *const u32>((&self.bytes[ 0..]).as_ptr()) }.to_be(), 65 | unsafe { *mem::transmute::<*const u8, *const u32>((&self.bytes[ 4..]).as_ptr()) }.to_be(), 66 | unsafe { *mem::transmute::<*const u8, *const u32>((&self.bytes[ 8..]).as_ptr()) }.to_be(), 67 | unsafe { *mem::transmute::<*const u8, *const u32>((&self.bytes[12..]).as_ptr()) }.to_be(), 68 | ] 69 | } 70 | 71 | #[inline] 72 | pub fn as_u16_be(&self) -> [u16; 8] { 73 | [ 74 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[ 0..]).as_ptr()) }.to_be(), 75 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[ 2..]).as_ptr()) }.to_be(), 76 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[ 4..]).as_ptr()) }.to_be(), 77 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[ 6..]).as_ptr()) }.to_be(), 78 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[ 8..]).as_ptr()) }.to_be(), 79 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[10..]).as_ptr()) }.to_be(), 80 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[12..]).as_ptr()) }.to_be(), 81 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[14..]).as_ptr()) }.to_be(), 82 | ] 83 | } 84 | 85 | #[inline] 86 | pub fn as_u64_le(&self) -> [u64; 2] { 87 | [ 88 | unsafe { *mem::transmute::<*const u8, *const u64>((&self.bytes[0..]).as_ptr()) }.to_le(), 89 | unsafe { *mem::transmute::<*const u8, *const u64>((&self.bytes[8..]).as_ptr()) }.to_le(), 90 | ] 91 | } 92 | 93 | #[inline] 94 | pub fn as_u32_le(&self) -> [u32; 4] { 95 | [ 96 | unsafe { *mem::transmute::<*const u8, *const u32>((&self.bytes[ 0..]).as_ptr()) }.to_le(), 97 | unsafe { *mem::transmute::<*const u8, *const u32>((&self.bytes[ 4..]).as_ptr()) }.to_le(), 98 | unsafe { *mem::transmute::<*const u8, *const u32>((&self.bytes[ 8..]).as_ptr()) }.to_le(), 99 | unsafe { *mem::transmute::<*const u8, *const u32>((&self.bytes[12..]).as_ptr()) }.to_le(), 100 | ] 101 | } 102 | 103 | #[inline] 104 | pub fn as_u16_le(&self) -> [u16; 8] { 105 | [ 106 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[ 0..]).as_ptr()) }.to_le(), 107 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[ 2..]).as_ptr()) }.to_le(), 108 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[ 4..]).as_ptr()) }.to_le(), 109 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[ 6..]).as_ptr()) }.to_le(), 110 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[ 8..]).as_ptr()) }.to_le(), 111 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[10..]).as_ptr()) }.to_le(), 112 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[12..]).as_ptr()) }.to_le(), 113 | unsafe { *mem::transmute::<*const u8, *const u16>((&self.bytes[14..]).as_ptr()) }.to_le(), 114 | ] 115 | } 116 | 117 | pub fn xor_distance(&self, other: &Address) -> (u64, u64) { 118 | let a = self.as_u64_be(); 119 | let b = other.as_u64_be(); 120 | (a[1] ^ b[1], a[0] ^ b[0]) 121 | } 122 | 123 | pub fn xor_compare(ab: (&Address, &Address), cd: (&Address, &Address)) -> Ordering { 124 | let a = ab.0.as_u64_be(); 125 | let b = ab.1.as_u64_be(); 126 | let c = cd.0.as_u64_be(); 127 | let d = cd.1.as_u64_be(); 128 | 129 | match (a[1] ^ b[1]).cmp(&(c[1] ^ d[1])) { 130 | Ordering::Less => return Ordering::Less, 131 | Ordering::Greater => return Ordering::Greater, 132 | Ordering::Equal => return (a[0] ^ b[0]).cmp(&(c[0] ^ d[0])) 133 | } 134 | } 135 | } 136 | 137 | impl fmt::Display for Address { 138 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 139 | let b = &self.bytes; 140 | write!(f, 141 | "{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}", 142 | b[ 0], b[ 1], b[ 2], b[ 3], b[ 4], b[ 5], b[ 6], b[ 7], 143 | b[ 8], b[ 9], b[10], b[11], b[12], b[13], b[14], b[15]) 144 | } 145 | } 146 | 147 | impl fmt::Debug for Address { 148 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 149 | write!(f, "{}", self) 150 | } 151 | } 152 | 153 | 154 | #[cfg(test)] 155 | mod tests { 156 | use address::Address; 157 | use std::cmp::Ordering; 158 | 159 | #[test] 160 | fn test_as_u64_be() { 161 | let address = Address::from_bytes(&[ 162 | 0xfc, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 163 | 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15]).unwrap(); 164 | let address_64 = [0xfc01020304050607, 0x0809101112131415]; 165 | assert_eq!(address.as_u64_be(), address_64); 166 | } 167 | 168 | #[test] 169 | fn test_as_u32_be() { 170 | let address = Address::from_bytes(&[ 171 | 0xfc, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 172 | 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15]).unwrap(); 173 | let address_32 = [0xfc010203, 0x04050607, 0x08091011, 0x12131415]; 174 | assert_eq!(address.as_u32_be(), address_32); 175 | } 176 | 177 | #[test] 178 | fn test_as_u16_be() { 179 | let address = Address::from_bytes(&[ 180 | 0xfc, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 181 | 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15]).unwrap(); 182 | let address_16 = [0xfc01, 0x0203, 0x0405, 0x0607, 0x0809, 0x1011, 0x1213, 0x1415]; 183 | assert_eq!(address.as_u16_be(), address_16); 184 | } 185 | 186 | #[test] 187 | fn test_as_u64_le() { 188 | let address = Address::from_bytes(&[ 189 | 0xfc, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 190 | 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15]).unwrap(); 191 | let address_64 = [0x07060504030201fc, 0x1514131211100908]; 192 | assert_eq!(address.as_u64_le(), address_64); 193 | } 194 | 195 | #[test] 196 | fn test_as_u32_le() { 197 | let address = Address::from_bytes(&[ 198 | 0xfc, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 199 | 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15]).unwrap(); 200 | let address_32 = [0x030201fc, 0x07060504, 0x11100908, 0x15141312]; 201 | assert_eq!(address.as_u32_le(), address_32); 202 | } 203 | 204 | #[test] 205 | fn test_as_u16_le() { 206 | let address = Address::from_bytes(&[ 207 | 0xfc, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 208 | 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15]).unwrap(); 209 | let address_16 = [0x01fc, 0x0302, 0x0504, 0x0706, 0x0908, 0x1110, 0x1312, 0x1514]; 210 | assert_eq!(address.as_u16_le(), address_16); 211 | } 212 | 213 | #[test] 214 | fn test_xor_distance() { 215 | // TODO Real data 216 | 217 | let a = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]).unwrap(); 218 | let b = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 219 | assert_eq!(Address::xor_distance(&a, &b), (0x01, 0x00)); 220 | 221 | let a = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 222 | let b = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 223 | assert_eq!(Address::xor_distance(&a, &b), (0x00, 0x01)); 224 | 225 | let a = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 226 | let b = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]).unwrap(); 227 | assert_eq!(Address::xor_distance(&a, &b), (0x0100, 0x0101)); 228 | } 229 | 230 | #[test] 231 | fn test_xor_compare() { 232 | // TODO Real data 233 | 234 | let a = Address::from_bytes(&[0xfc, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15]).unwrap(); 235 | let b = Address::from_bytes(&[0xfc, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15]).unwrap(); 236 | let c = Address::from_bytes(&[0xfc, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15]).unwrap(); 237 | let d = Address::from_bytes(&[0xfc, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15]).unwrap(); 238 | assert_eq!(Address::xor_compare((&a, &b), (&c, &d)), Ordering::Equal); 239 | 240 | let a = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]).unwrap(); 241 | let b = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 242 | let c = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 243 | let d = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 244 | assert_eq!(Address::xor_compare((&a, &b), (&c, &d)), Ordering::Greater); 245 | 246 | let a = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 247 | let b = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 248 | let c = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]).unwrap(); 249 | let d = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 250 | assert_eq!(Address::xor_compare((&a, &b), (&c, &d)), Ordering::Less); 251 | 252 | let a = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 253 | let b = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 254 | let c = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 255 | let d = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 256 | assert_eq!(Address::xor_compare((&a, &b), (&c, &d)), Ordering::Greater); 257 | 258 | let a = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 259 | let b = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 260 | let c = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]).unwrap(); 261 | let d = Address::from_bytes(&[0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap(); 262 | assert_eq!(Address::xor_compare((&a, &b), (&c, &d)), Ordering::Less); 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /src/cjdrs/config.rs: -------------------------------------------------------------------------------- 1 | use rustc_serialize::Encodable; 2 | use rustc_serialize::json::{self, Encoder}; 3 | use std::old_io::File; 4 | use std::old_io::fs::PathExtensions; 5 | use crypto::random_password; 6 | use PrivateIdentity; 7 | use CjdrsResult; 8 | use CjdrsError; 9 | 10 | #[derive(Debug, RustcEncodable, RustcDecodable)] 11 | #[allow(non_snake_case)] 12 | pub struct Config { 13 | pub privateKey: String, 14 | pub tunDevice: String, 15 | pub udpBind: String, 16 | pub authorizedPasswords: Vec 17 | } 18 | 19 | impl Config { 20 | pub fn get_default(identity: &PrivateIdentity) -> Config { 21 | Config { 22 | privateKey: identity.private_key.as_string(), 23 | tunDevice: "tun%d".to_string(), 24 | udpBind: "0.0.0.0:3300".to_string(), 25 | authorizedPasswords: vec![ 26 | random_password() 27 | ] 28 | } 29 | } 30 | 31 | pub fn write(&self, path: &Path) -> CjdrsResult<()> { 32 | if path.exists() { 33 | fail!(CjdrsError::ConfigAlreadyExists(path.clone())); 34 | } 35 | 36 | let encoded_str = { 37 | let mut s = String::new(); 38 | { 39 | let mut encoder = Encoder::new_pretty(&mut s); 40 | try!(self.encode(&mut encoder)); 41 | } 42 | s 43 | }; 44 | 45 | let mut file = try!(File::create(path)); 46 | Ok(try!(file.write_str(encoded_str.as_slice()))) 47 | } 48 | 49 | pub fn load(path: &Path) -> CjdrsResult { 50 | let mut file = try!(File::open(path)); 51 | let content = try!(file.read_to_string()); 52 | Ok(try!(json::decode(content.as_slice()))) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/cjdrs/crypto.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use sodiumoxide::crypto::asymmetricbox::curve25519xsalsa20poly1305 as crypto_box; 3 | use sodiumoxide::crypto::scalarmult::curve25519; 4 | use sodiumoxide::crypto::hash::sha256; 5 | use PrivateKey; 6 | use PublicKey; 7 | 8 | pub use sodiumoxide::randombytes::{randombytes, randombytes_into}; 9 | 10 | 11 | const PASSWORD_CHARS: &'static str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 12 | 13 | pub fn random_password() -> String { 14 | let length = 32; 15 | let mut password = "".to_string(); 16 | while password.len() < length { 17 | let n = randombytes(1)[0] as usize; 18 | if n < PASSWORD_CHARS.len() { 19 | password.push(PASSWORD_CHARS.as_bytes()[n] as char); 20 | } 21 | } 22 | password 23 | } 24 | 25 | 26 | 27 | #[derive(Debug, Copy, Eq, PartialEq)] 28 | pub struct PasswordHash([u8; 32]); 29 | 30 | impl PasswordHash { 31 | pub fn from_password(password: &str) -> PasswordHash { 32 | let sha256::Digest(hash) = sha256::hash(password.as_bytes()); 33 | PasswordHash(hash) 34 | } 35 | 36 | fn as_slice(&self) -> &[u8] { 37 | &self.0 38 | } 39 | } 40 | 41 | 42 | 43 | pub struct SharedSecret(crypto_box::PrecomputedKey); 44 | 45 | impl SharedSecret { 46 | pub fn without_password(my_private_key: &PrivateKey, 47 | her_public_key: &PublicKey) 48 | -> SharedSecret { 49 | let public = crypto_box::PublicKey(*her_public_key.as_slice()); 50 | let secret = crypto_box::SecretKey(*my_private_key.as_slice()); 51 | let key = crypto_box::precompute(&public, &secret); 52 | SharedSecret(key) 53 | } 54 | 55 | pub fn with_password(my_private_key: &PrivateKey, 56 | her_public_key: &PublicKey, 57 | password_hash: &PasswordHash) 58 | -> SharedSecret { 59 | let curve25519::GroupElement(mult_res) = curve25519::scalarmult( 60 | &curve25519::Scalar(*my_private_key.as_slice()), 61 | &curve25519::GroupElement(*her_public_key.as_slice())); 62 | assert_eq!(mult_res.len(), 32); 63 | 64 | let mut hash_input_buffer = Vec::with_capacity(64); 65 | hash_input_buffer.push_all(&mult_res); 66 | hash_input_buffer.push_all(password_hash.as_slice()); 67 | assert_eq!(hash_input_buffer.len(), 64); 68 | 69 | let sha256::Digest(hash) = sha256::hash(hash_input_buffer.as_slice()); 70 | match crypto_box::PrecomputedKey::from_slice(hash.as_slice()) { 71 | Some(precomputed_key) => SharedSecret(precomputed_key), 72 | None => unreachable!() 73 | } 74 | } 75 | 76 | fn get_key(&self) -> &crypto_box::PrecomputedKey { 77 | &self.0 78 | } 79 | } 80 | 81 | impl fmt::Debug for SharedSecret { 82 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 83 | write!(f, "SharedSecret({:?})", self.get_key().as_slice()) 84 | } 85 | } 86 | 87 | 88 | 89 | #[derive(Debug, Copy, Eq, PartialEq)] 90 | pub enum Nonce { 91 | Mine([u8; 24]), 92 | Hers([u8; 24]) 93 | } 94 | 95 | impl Nonce { 96 | fn get_bytes(&self) -> &[u8; 24] { 97 | match *self { 98 | Nonce::Mine(ref bytes) => bytes, 99 | Nonce::Hers(ref bytes) => bytes 100 | } 101 | } 102 | } 103 | 104 | 105 | 106 | #[derive(Debug, Copy)] 107 | pub struct CryptoBox; 108 | 109 | impl CryptoBox { 110 | pub fn encrypt(message: &[u8], 111 | nonce: &Nonce, 112 | shared_secret: &SharedSecret) -> Vec { 113 | crypto_box::seal_precomputed( 114 | message, 115 | &crypto_box::Nonce(*nonce.get_bytes()), 116 | shared_secret.get_key()) 117 | } 118 | 119 | pub fn decrypt(message: &[u8], 120 | nonce: &Nonce, 121 | shared_secret: &SharedSecret) -> Option> { 122 | crypto_box::open_precomputed( 123 | message, 124 | &crypto_box::Nonce(*nonce.get_bytes()), 125 | shared_secret.get_key()) 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/cjdrs/device/mod.rs: -------------------------------------------------------------------------------- 1 | pub use self::tun::Tun; 2 | pub use self::udp::Udp; 3 | 4 | use std::fmt; 5 | use mio::net::SockAddr; 6 | use CjdrsResult; 7 | use EventReceiver; 8 | use Task; 9 | 10 | mod tun; 11 | mod udp; 12 | 13 | 14 | pub trait NetDevice: EventReceiver + fmt::Debug { 15 | fn send_message(&mut self, message: &[u8], to: Option<&SockAddr>) -> CjdrsResult<()>; 16 | fn receive_message<'a>(&'a mut self, buffer: &'a mut [u8]) -> Option; 17 | } 18 | -------------------------------------------------------------------------------- /src/cjdrs/device/tun.rs: -------------------------------------------------------------------------------- 1 | use std::ffi::CString; 2 | use std::os::unix::prelude::AsRawFd; 3 | use mio; 4 | use mio::net::SockAddr; 5 | use tuntap::{TunTap, Tun}; 6 | use Address; 7 | use CjdrsResult; 8 | use EventReceiver; 9 | use NetDevice; 10 | use packet; 11 | use Task; 12 | 13 | 14 | #[derive(Debug)] 15 | pub struct Tun { 16 | tun: TunTap, 17 | io_desc: mio::IoDesc 18 | } 19 | 20 | 21 | impl Tun { 22 | pub fn new(name: &str, address: &Address) -> Tun { 23 | let tun = TunTap::create_named(Tun, &CString::from_slice(name.as_bytes())); 24 | let fd = tun.file.as_raw_fd(); 25 | 26 | tun.add_address(address.as_slice()); 27 | 28 | Tun { 29 | tun: tun, 30 | io_desc: mio::IoDesc { fd: fd } 31 | } 32 | } 33 | 34 | pub fn get_name(&self) -> String { 35 | let name = self.tun.get_name(); 36 | let mut name_vec = Vec::with_capacity(name.len()); 37 | name_vec.push_all(name.as_bytes()); 38 | 39 | match String::from_utf8(name_vec) { 40 | Ok(s) => s, 41 | Err(e) => panic!(e) 42 | } 43 | } 44 | } 45 | 46 | impl NetDevice for Tun { 47 | fn send_message(&mut self, message: &[u8], to: Option<&SockAddr>) -> CjdrsResult<()> { 48 | assert!(to.is_none()); 49 | 50 | Ok(try!(self.tun.write(message))) 51 | } 52 | 53 | fn receive_message<'a>(&'a mut self, buffer: &'a mut [u8]) -> Option { 54 | let data_slice = self.tun.read(buffer).ok().expect("Reading did not succeed"); 55 | let packet = packet::Tun::from_buffer(data_slice); 56 | 57 | match packet { 58 | Ok(tun_packet) => { 59 | let ipv6_packet = tun_packet.get_data(); 60 | Some(Task::HandleOutgoingPacket(*ipv6_packet)) 61 | }, 62 | Err(e) => { 63 | println!("Received an invalid packet from tun device: {}", e); 64 | None 65 | } 66 | } 67 | } 68 | } 69 | 70 | impl EventReceiver for Tun { 71 | fn register(&self, event_loop: &mut mio::EventLoop, token: mio::Token) 72 | -> mio::MioResult<()> { 73 | event_loop.register(self, token) 74 | } 75 | 76 | fn receive<'a>(&'a mut self, buffer: &'a mut [u8]) -> Option { 77 | self.receive_message(buffer) 78 | } 79 | } 80 | 81 | impl mio::IoHandle for Tun { 82 | fn desc(&self) -> &mio::IoDesc { 83 | &self.io_desc 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/cjdrs/device/udp.rs: -------------------------------------------------------------------------------- 1 | use mio; 2 | use mio::net::SockAddr; 3 | use mio::net::udp::UdpSocket; 4 | use mio::{event, IoReader}; 5 | use mio::buf::SliceBuf; 6 | use mio::net::UnconnectedSocket; 7 | use CjdrsResult; 8 | use CjdrsError; 9 | use EventReceiver; 10 | use NetDevice; 11 | use Task; 12 | use packet; 13 | 14 | 15 | #[derive(Debug)] 16 | pub struct Udp { 17 | send_sock: UdpSocket, 18 | recv_sock: UdpSocket 19 | } 20 | 21 | impl Udp { 22 | pub fn create(bind: &str) -> CjdrsResult { 23 | let send_sock = try!(UdpSocket::v4()); 24 | let recv_sock = try!(UdpSocket::v4()); 25 | 26 | let bind_addr = match SockAddr::parse(bind) { 27 | Some(a) => a, 28 | None => fail!(CjdrsError::InvalidBindAddress(bind.to_string())) 29 | }; 30 | 31 | try!(recv_sock.bind(&bind_addr)); 32 | 33 | Ok(Udp { 34 | send_sock: send_sock, 35 | recv_sock: recv_sock 36 | }) 37 | } 38 | } 39 | 40 | impl NetDevice for Udp { 41 | fn send_message(&mut self, message: &[u8], to: Option<&SockAddr>) -> CjdrsResult<()> { 42 | let address = match to { 43 | Some(a) => a, 44 | None => unreachable!() 45 | }; 46 | 47 | let mut buf = SliceBuf::wrap(message); 48 | try!(self.send_sock.send_to(&mut buf, address)); 49 | Ok(()) 50 | } 51 | 52 | fn receive_message<'a>(&'a mut self, buffer: &'a mut [u8]) -> Option { 53 | let len = self.recv_sock.read_slice(buffer).unwrap().unwrap(); 54 | let data = &buffer[..len]; 55 | 56 | match packet::CryptoAuth::from_buffer(data) { 57 | Ok(ca_packet) => { 58 | Some(Task::HandleIncomingPacket(ca_packet)) 59 | }, 60 | Err(e) => { 61 | println!("Received an invalid packet from udp device: {}", e); 62 | None 63 | } 64 | } 65 | } 66 | } 67 | 68 | 69 | impl EventReceiver for Udp { 70 | fn register(&self, event_loop: &mut mio::EventLoop, token: mio::Token) 71 | -> mio::MioResult<()> { 72 | event_loop.register_opt(&self.recv_sock, token, event::READABLE, event::EDGE) 73 | } 74 | 75 | fn receive<'a>(&'a mut self, buffer: &'a mut [u8]) -> Option { 76 | self.receive_message(buffer) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/cjdrs/encoding_scheme/fixed4.rs: -------------------------------------------------------------------------------- 1 | 2 | pub fn bits_used_for_label(_label: u64) -> u8 { 3 | 4 4 | } 5 | 6 | pub fn bits_used_for_number(_number: u32) -> u8 { 7 | 4 8 | } 9 | 10 | pub fn compress(number: u32) -> u64 { 11 | assert!(number <= 0b1111); 12 | number as u64 13 | } 14 | 15 | pub fn decompress(label: u64) -> u32 { 16 | assert!(label <= 0b1111); 17 | label as u32 18 | } 19 | 20 | 21 | #[cfg(test)] 22 | mod tests { 23 | use super::*; 24 | 25 | #[test] 26 | fn test_compress_decompress() { 27 | for i in range(0, 16) { 28 | assert_eq!(i, decompress(compress(i))) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/cjdrs/encoding_scheme/fixed8.rs: -------------------------------------------------------------------------------- 1 | 2 | pub fn bits_used_for_label(label: u64) -> u8 { 3 | if label & 0b1111 == 0b0001 { 4 | 4 5 | } else { 6 | 8 7 | } 8 | } 9 | 10 | pub fn bits_used_for_number(number: u32) -> u8 { 11 | if number == 1 { 12 | 4 13 | } else { 14 | 8 15 | } 16 | } 17 | 18 | pub fn compress(number: u32) -> u64 { 19 | assert!(number <= 0b1111_0000); 20 | 21 | let low = number & 0b0000_1111; 22 | let high = (number & 0b1111_0000) >> 4; 23 | 24 | match (high, low) { 25 | (0b0000, 0b0001) => 0b0000_0001, 26 | (0b1111, 0b0000) => 0b0001_0000, 27 | (0b0000, _) => (low << 4) as u64, 28 | ( _, _) => ((low << 4) | (high + 1)) as u64 29 | } 30 | } 31 | 32 | pub fn decompress(label: u64) -> u32 { 33 | assert!(label <= 0b1111_1111); 34 | 35 | let low = label & 0b0000_1111; 36 | let high = (label & 0b1111_0000) >> 4; 37 | 38 | match (high, low) { 39 | ( _, 0b0001) => 0b0000_0001, 40 | (0b0001, 0b0000) => 0b1111_0000, 41 | ( _, 0b0000) => high as u32, 42 | ( _, _) => (((low - 1) << 4) | high) as u32 43 | } 44 | } 45 | 46 | 47 | #[cfg(test)] 48 | mod tests { 49 | use super::*; 50 | 51 | #[test] 52 | fn test_compress_decompress() { 53 | for i in range(0, 241) { 54 | assert_eq!(i, decompress(compress(i))) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/cjdrs/encoding_scheme/mod.rs: -------------------------------------------------------------------------------- 1 | //! Self interface (1) must be encoded as 1 with 3 or more leading zeros. 2 | //! Route label's 3 highest bits must not be all zero. 3 | 4 | pub mod fixed4; 5 | pub mod fixed8; 6 | pub mod variable3x5x8; 7 | pub mod variable4x8; 8 | 9 | // trait EncodingScheme { 10 | // fn bits_used_for_label(label: u64) -> u8; 11 | // fn bits_used_for_number(number: u32) -> u8; 12 | // fn compress(number: u32) -> u64; 13 | // fn decompress(label: u64) -> u32; 14 | // } 15 | 16 | // TODO Use a trait 17 | // TODO Tests 18 | -------------------------------------------------------------------------------- /src/cjdrs/encoding_scheme/variable3x5x8.rs: -------------------------------------------------------------------------------- 1 | 2 | pub fn bits_used_for_label(label: u64) -> u8 { 3 | if label & 0b1 != 0 { 4 | 3 + 1 5 | } else if label & 0b10 != 0 { 6 | 5 + 2 7 | } else { 8 | 8 + 2 9 | } 10 | } 11 | 12 | pub fn bits_used_for_number(number: u32) -> u8 { 13 | match number { 14 | n if n < 8 => 3 + 1, 15 | n if n < 33 => 5 + 2, 16 | _ => 8 + 2 17 | } 18 | } 19 | 20 | pub fn compress(number: u32) -> u64 { 21 | if number == 1 { 22 | return 1; 23 | } 24 | 25 | match bits_used_for_number(number) { 26 | 4 => { 27 | match number { 28 | 0 => 0b0011, 29 | n => ((n << 1) | 0b1) as u64 30 | } 31 | }, 32 | 7 => { 33 | match number { 34 | 0 => 0b000_0010, 35 | n => (((n - 1) << 2) | 0b10) as u64 36 | } 37 | }, 38 | 10 => { 39 | match number { 40 | 0 => 0b00_0000_0000, 41 | n => ((n - 1) << 2) as u64 42 | } 43 | }, 44 | _ => unreachable!() 45 | } 46 | } 47 | 48 | pub fn decompress(label: u64) -> u32 { 49 | match bits_used_for_label(label) { 50 | 4 => { 51 | match (label >> 1) & 0b111 { 52 | 0b000 => 1, 53 | 0b001 => 0, 54 | n => n as u32 55 | } 56 | }, 57 | 7 => { 58 | match (label >> 2) & 0b1_1111 { 59 | 0b0_0000 => 0, 60 | n => (n + 1) as u32 61 | } 62 | }, 63 | 10 => { 64 | match (label >> 2) & 0b1111_1111 { 65 | 0b0000_0000 => 0, 66 | n => (n + 1) as u32 67 | } 68 | }, 69 | _ => unreachable!() 70 | } 71 | } 72 | 73 | 74 | #[cfg(test)] 75 | mod tests { 76 | use super::*; 77 | 78 | #[test] 79 | fn test_compress_decompress() { 80 | for i in range(0, 257) { 81 | assert_eq!(i, decompress(compress(i))) 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/cjdrs/encoding_scheme/variable4x8.rs: -------------------------------------------------------------------------------- 1 | 2 | pub fn bits_used_for_label(label: u64) -> u8 { 3 | if label & 0b1 != 0 { 4 | 4 + 1 5 | } else { 6 | 8 + 1 7 | } 8 | } 9 | 10 | pub fn bits_used_for_number(number: u32) -> u8 { 11 | if number < 15 { 12 | 4 + 1 13 | } else { 14 | 8 + 1 15 | } 16 | } 17 | 18 | pub fn compress(number: u32) -> u64 { 19 | if number == 1 { 20 | return 1; 21 | } 22 | 23 | match bits_used_for_number(number) { 24 | 5 => { 25 | match number { 26 | 0 => 0b0_0011, 27 | n => ((n << 1) | 0b1) as u64 28 | } 29 | }, 30 | 9 => { 31 | match number { 32 | 0 => 0b0_0000_0000, 33 | n => ((n - 1) << 1) as u64 34 | } 35 | }, 36 | _ => unreachable!() 37 | } 38 | } 39 | 40 | pub fn decompress(label: u64) -> u32 { 41 | if label & 0b0_0001_1111 == 1 { 42 | return 1; 43 | } 44 | 45 | match bits_used_for_label(label) { 46 | 5 => { 47 | match (label >> 1) & 0b1111 { 48 | 0b0001 => 0, 49 | n => n as u32 50 | } 51 | }, 52 | 9 => { 53 | match (label >> 1) & 0b1111_1111 { 54 | 0b0000_0000 => 0, 55 | n => (n + 1) as u32 56 | } 57 | }, 58 | _ => unreachable!() 59 | } 60 | } 61 | 62 | 63 | #[cfg(test)] 64 | mod tests { 65 | use super::*; 66 | 67 | #[test] 68 | fn test_compress_decompress() { 69 | for i in range(0, 257) { 70 | assert_eq!(i, decompress(compress(i))) 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/cjdrs/error.rs: -------------------------------------------------------------------------------- 1 | use std::{old_io, error, fmt}; 2 | use mio; 3 | use rustc_serialize::{hex, json}; 4 | use identity::PRIV_KEY_SIZE; 5 | use PrivateKey; 6 | use PublicKey; 7 | 8 | use CjdrsError::{ 9 | ConfigAlreadyExists, 10 | InvalidPrivateKey, 11 | InvalidPublicKey, 12 | NoAddressForPrivateKey, 13 | NoAddressForPublicKey, 14 | InvalidBindAddress, 15 | JsonDecodingError, 16 | JsonEncodingError, 17 | MioError, 18 | FmtError, 19 | IoError, 20 | }; 21 | 22 | pub type CjdrsResult = Result; 23 | 24 | #[derive(Debug)] 25 | pub enum CjdrsError { 26 | ConfigAlreadyExists(Path), 27 | InvalidPrivateKey(Option), 28 | InvalidPublicKey, 29 | NoAddressForPrivateKey(PrivateKey), 30 | NoAddressForPublicKey(PublicKey), 31 | InvalidBindAddress(String), 32 | JsonDecodingError(json::DecoderError), 33 | JsonEncodingError(json::EncoderError), 34 | MioError(mio::MioError), 35 | FmtError(fmt::Error), 36 | IoError(old_io::IoError), 37 | } 38 | 39 | 40 | impl error::Error for CjdrsError { 41 | fn description(&self) -> &str { 42 | match *self { 43 | ConfigAlreadyExists(..) => "Configuration file aready exists", 44 | InvalidPrivateKey(..) => "Invalid private key", 45 | InvalidPublicKey => "Invalid public key", 46 | NoAddressForPrivateKey(..) => "Private key has no valid IP address", 47 | NoAddressForPublicKey(..) => "Public key has no valid IP address", 48 | InvalidBindAddress(..) => "Invalid bind address", 49 | JsonDecodingError(..) => "JSON decoding error", 50 | JsonEncodingError(..) => "JSON encoding error", 51 | MioError(..) => "Event handler error", 52 | FmtError(..) => "Formatting error", 53 | IoError(..) => "I/O error", 54 | } 55 | } 56 | 57 | fn cause(&self) -> Option<&error::Error> { 58 | match *self { 59 | JsonDecodingError(ref e) => Some(e as &error::Error), 60 | JsonEncodingError(ref e) => Some(e as &error::Error), 61 | IoError(ref e) => Some(e as &error::Error), 62 | _ => None, 63 | } 64 | } 65 | } 66 | 67 | impl fmt::Display for CjdrsError { 68 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 69 | try!(write!(f, "{}. ", error::Error::description(self))); 70 | 71 | match *self { 72 | ConfigAlreadyExists(ref path) => 73 | write!(f, "Path '{}'", path.display()), 74 | 75 | InvalidPrivateKey(Some(ref e)) => 76 | write!(f, "{:?}", e), 77 | 78 | InvalidPrivateKey(None) => 79 | write!(f, "Private key must be {} characters long", PRIV_KEY_SIZE * 2), 80 | 81 | InvalidPublicKey => 82 | write!(f, "Public key must be 54 character base32 encoded string including '.k'"), 83 | 84 | NoAddressForPrivateKey(ref k) => 85 | write!(f, "Private key '{}'", k), 86 | 87 | NoAddressForPublicKey(ref k) => 88 | write!(f, "Public key '{}'", k), 89 | 90 | InvalidBindAddress(ref s) => 91 | write!(f, "Bind address '{}' is invalid", s), 92 | 93 | JsonDecodingError(ref e) => 94 | write!(f, "{:?}", e), 95 | 96 | JsonEncodingError(ref e) => 97 | write!(f, "{:?}", e), 98 | 99 | MioError(ref e) => 100 | write!(f, "{:?}", e), 101 | 102 | FmtError(ref e) => 103 | write!(f, "{:?}", e), 104 | 105 | IoError(ref e) => 106 | write!(f, "{:?}", e), 107 | } 108 | } 109 | } 110 | 111 | 112 | impl error::FromError for CjdrsError { 113 | fn from_error(e: old_io::IoError) -> CjdrsError { 114 | CjdrsError::IoError(e) 115 | } 116 | } 117 | 118 | impl error::FromError for CjdrsError { 119 | fn from_error(e: fmt::Error) -> CjdrsError { 120 | CjdrsError::FmtError(e) 121 | } 122 | } 123 | 124 | impl error::FromError> for CjdrsError { 125 | fn from_error(e: mio::EventLoopError) -> CjdrsError { 126 | CjdrsError::MioError(e.error) 127 | } 128 | } 129 | 130 | impl error::FromError for CjdrsError { 131 | fn from_error(e: mio::MioError) -> CjdrsError { 132 | CjdrsError::MioError(e) 133 | } 134 | } 135 | 136 | impl error::FromError for CjdrsError { 137 | fn from_error(e: json::DecoderError) -> CjdrsError { 138 | CjdrsError::JsonDecodingError(e) 139 | } 140 | } 141 | 142 | 143 | impl error::FromError for CjdrsError { 144 | fn from_error(e: json::EncoderError) -> CjdrsError { 145 | CjdrsError::JsonEncodingError(e) 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/cjdrs/event_handler.rs: -------------------------------------------------------------------------------- 1 | use std::time::duration::Duration; 2 | use mio; 3 | use crypto::{PasswordHash, SharedSecret}; 4 | use debug::as_hex; 5 | use device::NetDevice; 6 | use packet; 7 | use PrivateIdentity; 8 | use Router; 9 | 10 | 11 | #[derive(Debug)] 12 | pub enum Task<'a> { 13 | HandleIncomingPacket(packet::CryptoAuth<'a>), 14 | HandleOutgoingPacket(packet::IPv6<'a>) 15 | } 16 | 17 | 18 | pub trait EventReceiver { 19 | fn register(&self, event_loop: &mut mio::EventLoop, token: mio::Token) 20 | -> mio::MioResult<()>; 21 | fn receive<'a>(&'a mut self, buffer: &'a mut [u8]) -> Option; 22 | } 23 | 24 | 25 | #[derive(Debug)] 26 | pub struct EventHandler<'a> { 27 | my_identity: PrivateIdentity, 28 | devices: Vec>, 29 | router: Router 30 | } 31 | 32 | impl<'a> EventHandler<'a> { 33 | pub fn new(my_identity: PrivateIdentity, 34 | devices: Vec>, 35 | router: Router) -> EventHandler<'a> { 36 | 37 | EventHandler { 38 | my_identity: my_identity, 39 | devices: devices, 40 | router: router 41 | } 42 | } 43 | 44 | pub fn register_handlers(&self, event_loop: &mut mio::EventLoop) 45 | -> mio::MioResult<()> { 46 | for (i, device) in self.devices.iter().enumerate() { 47 | try!(device.register(event_loop, mio::Token(i))); 48 | } 49 | event_loop.timeout(1000, Duration::milliseconds(0)).unwrap(); 50 | Ok(()) 51 | } 52 | } 53 | 54 | impl<'a> mio::Handler for EventHandler<'a> { 55 | fn timeout(&mut self, event_loop: &mut mio::EventLoop, timeout: usize) { 56 | assert_eq!(timeout, 1000); 57 | 58 | event_loop.timeout(1000, Duration::milliseconds(1000)).unwrap(); 59 | } 60 | 61 | fn readable(&mut self, _event_loop: &mut mio::EventLoop, 62 | token: mio::Token, _hint: mio::event::ReadHint) { 63 | 64 | let mut buffer = [0u8; 1500]; 65 | 66 | let device_idx = token.as_usize(); 67 | let maybe_task = self.devices[device_idx].receive(&mut buffer); 68 | 69 | if let Some(task) = maybe_task { 70 | match task { 71 | Task::HandleIncomingPacket(mut ca_packet) => { 72 | println!("Handling incoming packet"); 73 | 74 | let password_hash = PasswordHash::from_password("aaa"); 75 | 76 | let shared_secret = SharedSecret::with_password( 77 | &self.my_identity.private_key, 78 | &ca_packet.public_key(), 79 | &password_hash); 80 | 81 | match ca_packet.decrypt(&shared_secret) { 82 | Some(message) => println!("Decrypted message: {}", as_hex(message.as_slice())), 83 | None => println!("Couldn't decrypt the message!") 84 | } 85 | 86 | }, 87 | Task::HandleOutgoingPacket(ipv6_packet) => { 88 | let destination = ipv6_packet.get_destination().unwrap(); 89 | println!("Handling outgoing packet to {}", destination); 90 | 91 | let route = self.router.get_route(&destination); 92 | println!(" Route: {}", route); 93 | } 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/cjdrs/identity.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use rustc_serialize::hex::{FromHex, ToHex}; 3 | use sodiumoxide::crypto::scalarmult::curve25519; 4 | use Address; 5 | use crypto; 6 | use util::base32; 7 | use CjdrsResult; 8 | use CjdrsError; 9 | 10 | 11 | pub const PRIV_KEY_SIZE: usize = 32; 12 | pub const PUB_KEY_SIZE: usize = 32; 13 | 14 | 15 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 16 | pub struct PrivateKey([u8; PRIV_KEY_SIZE]); 17 | 18 | impl PrivateKey { 19 | pub fn from_string(string: &str) -> CjdrsResult { 20 | match string.from_hex() { 21 | Ok(bytes) => { 22 | if bytes.len() != PRIV_KEY_SIZE { 23 | fail!(CjdrsError::InvalidPrivateKey(None)); 24 | } 25 | 26 | let buffer = { 27 | let mut buffer = [0u8; PRIV_KEY_SIZE]; 28 | buffer.clone_from_slice(bytes.as_slice()); 29 | buffer 30 | }; 31 | 32 | Ok(PrivateKey(buffer)) 33 | } 34 | Err(e) => Err(CjdrsError::InvalidPrivateKey(Some(e))) 35 | } 36 | } 37 | 38 | pub fn as_slice(&self) -> &[u8; PRIV_KEY_SIZE] { 39 | &self.0 40 | } 41 | 42 | pub fn as_string(&self) -> String { 43 | self.as_slice().to_hex() 44 | } 45 | } 46 | 47 | impl fmt::Display for PrivateKey { 48 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 49 | write!(f, "{}", self.as_string()) 50 | } 51 | } 52 | 53 | 54 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 55 | pub struct PublicKey([u8; PUB_KEY_SIZE]); 56 | 57 | impl PublicKey { 58 | pub fn from_buffer(buffer: &[u8; PUB_KEY_SIZE]) -> PublicKey { 59 | PublicKey(*buffer) 60 | } 61 | 62 | pub fn from_slice(slice: &[u8]) -> PublicKey { 63 | assert_eq!(slice.len(), PUB_KEY_SIZE); 64 | 65 | let buffer = { 66 | let mut buffer = [0u8; PUB_KEY_SIZE]; 67 | buffer.clone_from_slice(slice); 68 | buffer 69 | }; 70 | 71 | PublicKey(buffer) 72 | } 73 | 74 | pub fn from_string(key_str: &str) -> CjdrsResult { 75 | if key_str.len() != 52 + 2 { 76 | fail!(CjdrsError::InvalidPublicKey); 77 | } else if !key_str.ends_with(".k") { 78 | fail!(CjdrsError::InvalidPublicKey); 79 | } 80 | 81 | let hex_str = &key_str[..52]; 82 | 83 | match base32::decode(hex_str) { 84 | Some(bytes) => { 85 | assert_eq!(bytes.len(), PUB_KEY_SIZE); 86 | Ok(PublicKey::from_slice(bytes.as_slice())) 87 | }, 88 | None => Err(CjdrsError::InvalidPublicKey) 89 | } 90 | } 91 | 92 | pub fn as_slice(&self) -> &[u8; PUB_KEY_SIZE] { 93 | &self.0 94 | } 95 | 96 | pub fn as_string(&self) -> String { 97 | base32::encode(self.as_slice()) + ".k" 98 | } 99 | } 100 | 101 | impl fmt::Display for PublicKey { 102 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 103 | write!(f, "{}", self.as_string()) 104 | } 105 | } 106 | 107 | 108 | 109 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 110 | pub struct PrivateIdentity { 111 | pub private_key: PrivateKey, 112 | pub public_key: PublicKey, 113 | pub address: Address 114 | } 115 | 116 | impl PrivateIdentity { 117 | pub fn generate() -> PrivateIdentity { 118 | loop { 119 | let private_key = { 120 | let mut private_key_buf = [0; PRIV_KEY_SIZE]; 121 | crypto::randombytes_into(&mut private_key_buf); 122 | PrivateKey(private_key_buf) 123 | }; 124 | 125 | if let Some(identity) = PrivateIdentity::from_private_key(&private_key) { 126 | return identity; 127 | } 128 | } 129 | } 130 | 131 | pub fn from_private_key(private_key: &PrivateKey) -> Option { 132 | let input = curve25519::Scalar(*private_key.as_slice()); 133 | let public_key_buf = curve25519::scalarmult_base(&input).0; 134 | let public_key = PublicKey::from_buffer(&public_key_buf); 135 | 136 | match Address::from_public_key(&public_key) { 137 | Some(address) => Some(PrivateIdentity { 138 | private_key: *private_key, 139 | public_key: public_key, 140 | address: address 141 | }), 142 | None => None 143 | } 144 | } 145 | } 146 | 147 | 148 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 149 | pub struct PublicIdentity { 150 | pub public_key: PublicKey, 151 | pub address: Address 152 | } 153 | 154 | impl PublicIdentity { 155 | pub fn from_public_key(public_key: &PublicKey) -> Option { 156 | match Address::from_public_key(public_key) { 157 | Some(address) => Some(PublicIdentity { 158 | public_key: *public_key, 159 | address: address 160 | }), 161 | None => None 162 | } 163 | } 164 | } 165 | 166 | 167 | 168 | #[cfg(test)] 169 | mod tests { 170 | use identity::{ 171 | PrivateKey, 172 | PrivateIdentity}; 173 | use address::Address; 174 | use test::Bencher; 175 | 176 | 177 | #[test] 178 | fn test_private_generate() { 179 | let identity = PrivateIdentity::generate(); 180 | assert_eq!(identity.address.as_slice()[0], 0xFC); 181 | } 182 | 183 | #[test] 184 | fn test_private_from_key() { 185 | let priv_key = PrivateKey([ 186 | 0x4c, 0x80, 0xb5, 0xfe, 0xe2, 0xad, 0xbd, 0x9a, 187 | 0xeb, 0x80, 0xed, 0xe1, 0xd7, 0x5b, 0xd2, 0xba, 188 | 0x93, 0xc2, 0xa6, 0xea, 0xbe, 0xf3, 0x8b, 0xe1, 189 | 0x8d, 0x4b, 0x8a, 0x41, 0x8d, 0x9a, 0xa0, 0xbc]); 190 | let ip = Address::from_bytes(&[ 191 | 0xfc, 0x50, 0x71, 0xae, 0x09, 0xd6, 0xf7, 0x94, 192 | 0x75, 0x54, 0x20, 0x83, 0x87, 0x3e, 0x88, 0xa9]).unwrap(); 193 | 194 | let identity = PrivateIdentity::from_private_key(&priv_key).unwrap(); 195 | assert_eq!(identity.address, ip); 196 | 197 | 198 | let priv_key = PrivateKey([ 199 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 200 | 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 201 | 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 202 | 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32]); 203 | assert!(PrivateIdentity::from_private_key(&priv_key).is_none()); 204 | } 205 | 206 | #[bench] 207 | fn bench_generate_identity(b: &mut Bencher) { 208 | b.iter(|| { 209 | PrivateIdentity::generate() 210 | }) 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /src/cjdrs/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(collections, core, hash, io, std_misc)] 2 | 3 | #[cfg(test)] extern crate test; 4 | extern crate mio; 5 | extern crate sodiumoxide; 6 | extern crate "rustc-serialize" as rustc_serialize; 7 | extern crate tuntap; 8 | 9 | pub use address::Address; 10 | pub use config::Config; 11 | pub use error::{CjdrsError, CjdrsResult}; 12 | pub use event_handler::{EventHandler, EventReceiver, Task}; 13 | pub use identity::{ 14 | PrivateIdentity, 15 | PublicIdentity, 16 | PrivateKey, 17 | PublicKey}; 18 | pub use device::NetDevice; 19 | pub use route::Route; 20 | pub use router::Router; 21 | pub use util::debug; 22 | 23 | mod macros; 24 | 25 | pub mod crypto; 26 | pub mod encoding_scheme; 27 | pub mod device; 28 | pub mod packet; 29 | pub mod util; 30 | 31 | mod address; 32 | mod config; 33 | mod error; 34 | mod event_handler; 35 | mod identity; 36 | mod route; 37 | mod router; 38 | 39 | 40 | pub fn init() { 41 | sodiumoxide::init(); 42 | } 43 | -------------------------------------------------------------------------------- /src/cjdrs/macros.rs: -------------------------------------------------------------------------------- 1 | #![macro_use] 2 | 3 | macro_rules! fail { 4 | ($expr:expr) => ( 5 | return Err(::std::error::FromError::from_error($expr)); 6 | ) 7 | } 8 | -------------------------------------------------------------------------------- /src/cjdrs/packet/cryptoauth.rs: -------------------------------------------------------------------------------- 1 | use std::mem::{size_of, transmute}; 2 | use std::raw::Slice; 3 | use crypto::{SharedSecret, Nonce, CryptoBox}; 4 | use packet::{ParseResult, Packet, buffer_to_type}; 5 | use identity::{PublicKey, PUB_KEY_SIZE}; 6 | use util::BigEndian; 7 | use debug::as_hex; 8 | 9 | #[cfg(test)] pub const CRYPTOAUTH_HEADER_LENGTH: usize = 120; 10 | 11 | 12 | 13 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 14 | #[repr(packed)] 15 | pub struct Challenge { 16 | challenge_type: u8, 17 | lookup: [u8; 7], 18 | require_auth_and_derivation_count: BigEndian, 19 | additional: BigEndian 20 | } 21 | 22 | impl Challenge { 23 | pub fn require_auth(&self) -> bool { 24 | self.require_auth_and_derivation_count.val() >> 15 != 0 25 | } 26 | 27 | pub fn derivations(&self) -> u16 { 28 | self.require_auth_and_derivation_count.val() & (!0 >> 1) 29 | } 30 | } 31 | 32 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 33 | #[repr(packed)] 34 | pub struct CryptoAuthHeader { 35 | stage: BigEndian, 36 | auth_challenge: Challenge, 37 | nonce: [u8; 24], 38 | public_key: [u8; PUB_KEY_SIZE], 39 | authenticator: [u8; 16], 40 | encrypted_temp_key: [u8; 32] 41 | } 42 | 43 | 44 | 45 | pub type CryptoAuth<'a> = Packet<'a, CryptoAuthHeader, &'a [u8]>; 46 | 47 | impl<'a> CryptoAuth<'a> { 48 | pub fn from_buffer(buffer: &[u8]) -> ParseResult { 49 | let stage_or_nonce: &BigEndian = try!(buffer_to_type(buffer)); 50 | 51 | match stage_or_nonce.val() { 52 | 0 | 1 => { 53 | let header: &CryptoAuthHeader = try!(buffer_to_type(buffer)); 54 | let data = &buffer[size_of::()..]; 55 | 56 | println!(""); 57 | println!("Stage: 0x{:08X}", header.stage.val()); 58 | println!("Auth challenge"); 59 | println!(" Challenge type: {}", header.auth_challenge.challenge_type); 60 | println!(" Lookup: {}", as_hex(&header.auth_challenge.lookup)); 61 | println!(" Require auth: {}", header.auth_challenge.require_auth()); 62 | println!(" Derivations: {}", header.auth_challenge.derivations()); 63 | println!(" Additional: 0x{:04X}", header.auth_challenge.additional.val()); 64 | println!("Nonce: {}", as_hex(&header.nonce)); 65 | println!("Perm public key: {}", PublicKey::from_slice(&header.public_key)); 66 | println!("Poly1305 authenticator: {}", as_hex(&header.authenticator)); 67 | println!("Temporary public key: {}", as_hex(&header.encrypted_temp_key)); 68 | println!("Data: {}", as_hex(data)); 69 | println!(""); 70 | 71 | 72 | 73 | Ok(CryptoAuth { 74 | slice: buffer, 75 | header: header, 76 | data: data 77 | }) 78 | }, 79 | n => { 80 | println!("Unknown type {}", n); 81 | unimplemented!(); 82 | } 83 | } 84 | } 85 | 86 | pub fn challenge(&self) -> &Challenge { 87 | &self.header.auth_challenge 88 | } 89 | 90 | pub fn public_key(&self) -> PublicKey { 91 | PublicKey::from_buffer(&self.header.public_key) 92 | } 93 | 94 | pub fn decrypt(&mut self, shared_secret: &SharedSecret) -> Option> { 95 | let encrypted_part: &[u8] = unsafe { 96 | transmute(Slice { 97 | data: &self.header.authenticator, 98 | len: 16 + 32 + self.data.len() 99 | }) 100 | }; 101 | 102 | CryptoBox::decrypt( 103 | encrypted_part, 104 | &Nonce::Hers(self.header.nonce), 105 | shared_secret) 106 | } 107 | } 108 | 109 | 110 | 111 | 112 | #[cfg(test)] 113 | mod tests { 114 | use super::*; 115 | use std::mem::size_of; 116 | 117 | #[test] 118 | fn test_sizeof() { 119 | assert_eq!(size_of::(), CRYPTOAUTH_HEADER_LENGTH); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/cjdrs/packet/ipv6.rs: -------------------------------------------------------------------------------- 1 | use std::mem::size_of; 2 | use Address; 3 | use packet::{ParseResult, Packet, buffer_to_type}; 4 | use util::BigEndian; 5 | 6 | #[cfg(test)] pub const IPV6_HEADER_LENGTH: usize = 40; 7 | 8 | 9 | 10 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 11 | #[repr(packed)] 12 | pub struct IPv6Header { 13 | version_class_flow: BigEndian, 14 | flow_label_low: BigEndian, 15 | payload_length: BigEndian, 16 | next_header: u8, 17 | hop_limit: u8, 18 | source_addr: [u8; 16], 19 | destination_addr: [u8; 16] 20 | } 21 | 22 | impl IPv6Header { 23 | fn get_version(&self) -> u8 { 24 | ((self.version_class_flow.val() & 0xF000) >> 12) as u8 25 | } 26 | } 27 | 28 | 29 | 30 | pub type IPv6<'a> = Packet<'a, IPv6Header, &'a [u8]>; 31 | 32 | impl<'a> IPv6<'a> { 33 | pub fn from_buffer(buffer: &[u8]) -> ParseResult { 34 | let header: &IPv6Header = try!(buffer_to_type(buffer)); 35 | 36 | if header.get_version() != 6 { 37 | return Err("Packet not IPv6") 38 | } 39 | if !Address::is_valid(&header.source_addr) { 40 | return Err("Source address not valid") 41 | } 42 | if !Address::is_valid(&header.destination_addr) { 43 | return Err("Destination address not valid") 44 | } 45 | 46 | 47 | let data = &buffer[size_of::()..]; 48 | 49 | Ok(IPv6 { 50 | slice: buffer, 51 | header: header, 52 | data: data 53 | }) 54 | } 55 | 56 | pub fn get_data(&self) -> &'a [u8] { 57 | self.data 58 | } 59 | 60 | pub fn get_destination(&self) -> Option
{ 61 | Address::from_slice(&self.header.destination_addr) 62 | } 63 | } 64 | 65 | 66 | 67 | #[cfg(test)] 68 | mod tests { 69 | use super::*; 70 | use std::mem::size_of; 71 | 72 | #[test] 73 | fn test_sizeof() { 74 | assert_eq!(size_of::(), IPV6_HEADER_LENGTH); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/cjdrs/packet/mod.rs: -------------------------------------------------------------------------------- 1 | pub use self::ipv6::IPv6; 2 | pub use self::tun::Tun; 3 | pub use self::cryptoauth::CryptoAuth; 4 | 5 | use std::mem; 6 | 7 | mod ipv6; 8 | mod cryptoauth; 9 | mod tun; 10 | 11 | pub type ParseResult

= Result; 12 | 13 | 14 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 15 | pub struct Packet<'a, H: 'a, D> { 16 | pub slice: &'a [u8], 17 | pub header: &'a H, 18 | pub data: D 19 | } 20 | 21 | 22 | fn buffer_to_type(buffer: &[u8]) -> ParseResult<&S> { 23 | if buffer.len() < mem::size_of::() { 24 | Err("Buffer too short for conversion to type") 25 | } else { 26 | Ok(unsafe { mem::transmute(buffer.as_ptr()) }) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/cjdrs/packet/tun.rs: -------------------------------------------------------------------------------- 1 | use std::mem::size_of; 2 | use packet::{ParseResult, Packet, buffer_to_type}; 3 | use packet; 4 | use util::BigEndian; 5 | 6 | #[cfg(test)] pub const TUN_HEADER_LENGTH: usize = 4; 7 | 8 | 9 | 10 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 11 | #[repr(packed)] 12 | pub struct TunHeader { 13 | _unused: BigEndian, 14 | protocol_type: BigEndian 15 | } 16 | 17 | impl TunHeader { 18 | fn is_ipv6(&self) -> bool { 19 | self.protocol_type.val() == 0x86DD 20 | } 21 | } 22 | 23 | 24 | 25 | pub type Tun<'a> = Packet<'a, TunHeader, packet::IPv6<'a>>; 26 | 27 | impl<'a> Tun<'a> { 28 | pub fn from_buffer(buffer: &[u8]) -> ParseResult { 29 | let header: &TunHeader = try!(buffer_to_type(buffer)); 30 | 31 | if !header.is_ipv6() { 32 | return Err("Tun packet not IPv6"); 33 | } 34 | 35 | let payload = { 36 | let data_slice = &buffer[size_of::()..]; 37 | try!(packet::IPv6::from_buffer(data_slice)) 38 | }; 39 | 40 | Ok(Tun { 41 | slice: buffer, 42 | header: header, 43 | data: payload 44 | }) 45 | } 46 | 47 | pub fn get_data(&self) -> &packet::IPv6<'a> { 48 | &self.data 49 | } 50 | } 51 | 52 | 53 | 54 | #[cfg(test)] 55 | mod tests { 56 | use super::*; 57 | use std::mem::size_of; 58 | 59 | #[test] 60 | fn test_sizeof() { 61 | assert_eq!(size_of::(), TUN_HEADER_LENGTH); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/cjdrs/route.rs: -------------------------------------------------------------------------------- 1 | use std::num::Int; 2 | use std::fmt; 3 | use std::u64; 4 | 5 | #[derive(Copy, Clone, Eq, PartialEq)] 6 | pub struct Route { 7 | bits: u64 8 | } 9 | 10 | impl Route { 11 | #[inline] 12 | pub fn new(bits: u64) -> Route { 13 | Route { bits: bits } 14 | } 15 | 16 | /// AB + BC = AC 17 | /// Splice 18 | #[inline] 19 | pub fn combine(&self, other: &Route) -> Option { 20 | if (self.bit_len() - 1) + (self.bit_len() - 1) > 59 { // TODO Why 59? 21 | // Route too long 22 | return None 23 | } 24 | 25 | let combined_route = ((other.bits ^ 1) << (self.bit_len() - 1)) ^ self.bits; 26 | Some(Route { bits: combined_route }) 27 | } 28 | 29 | /// AC - AB = BC 30 | /// Unsplice 31 | #[inline] 32 | pub fn get_end(&self, front: &Route) -> Route { 33 | Route { bits: self.bits >> (front.bit_len() - 1) } 34 | } 35 | 36 | /// ABCD.goes_through(A/AB/ABC) 37 | #[inline] 38 | pub fn goes_through(&self, other: &Route) -> bool { 39 | if other.bits > self.bits { 40 | false 41 | } 42 | else if other.bits == 0 || other.bits == 1 { 43 | true 44 | } 45 | else { 46 | let mask = u64::MAX >> (other.bits.leading_zeros() + 1); 47 | (self.bits & mask) == (other.bits & mask) 48 | } 49 | } 50 | 51 | #[inline] 52 | pub fn bit_len(&self) -> u8 { 53 | 64 - self.bits.leading_zeros() as u8 54 | } 55 | } 56 | 57 | impl fmt::Display for Route { 58 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 59 | write!(f, "{:064b}", self.bits) 60 | } 61 | } 62 | 63 | impl fmt::Debug for Route { 64 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 65 | write!(f, "{}", self) 66 | } 67 | } 68 | 69 | 70 | 71 | #[cfg(test)] 72 | mod tests { 73 | use route::Route; 74 | 75 | #[test] 76 | fn test_combine() { 77 | let ab = Route::new(0b0000000000000000000000000000000000000000000001011101110101011001); 78 | let bc = Route::new(0b0000000000000000000000000000000000000000000000000000110101010100); 79 | let ac = Route::new(0b0000000000000000000000000000000000110101010100011101110101011001); 80 | assert_eq!(ab.combine(&bc).unwrap(), ac); 81 | } 82 | 83 | 84 | #[test] 85 | fn test_bit_len() { 86 | assert_eq!(Route::new(0b0000000000000000000000000000000000000000000000000000000000000000).bit_len(), 0); 87 | assert_eq!(Route::new(0b0000000000000000000000000000000000000000000000000000000000000001).bit_len(), 1); 88 | assert_eq!(Route::new(0b0000000000000000000000000000000000000000000000000000000000000010).bit_len(), 2); 89 | assert_eq!(Route::new(0b0000000000000000000000000000000000000000000000000000000000000011).bit_len(), 2); 90 | assert_eq!(Route::new(0b0000000000000000000000000000000000000000000000000000000000000011).bit_len(), 2); 91 | assert_eq!(Route::new(0b1000000000000000000000000000000000000000000000000000000000000000).bit_len(), 64); 92 | assert_eq!(Route::new(0b0100000000000000000000000000000000000000000000000000000000000000).bit_len(), 63); 93 | assert_eq!(Route::new(0b1111111111111111111111111111111111111111111111111111111111111111).bit_len(), 64); 94 | assert_eq!(Route::new(0b0000000000000000000000000000000000000000000001011101110101011001).bit_len(), 19); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/cjdrs/router.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use Address; 3 | use Route; 4 | 5 | #[derive(Debug)] 6 | pub struct Router { 7 | node_store: HashMap 8 | } 9 | 10 | impl Router { 11 | pub fn new(own_ip: &Address) -> Router { 12 | let mut router = Router { node_store: HashMap::new() }; 13 | router.node_store.insert(own_ip.clone(), Route::new(0b1)); 14 | router 15 | } 16 | 17 | pub fn get_route(&self, address: &Address) -> Route { 18 | match self.node_store.get(address) { 19 | Some(route) => route.clone(), 20 | None => Route::new(0b10) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/cjdrs/util/base32.rs: -------------------------------------------------------------------------------- 1 | //! http://dnscurve.org/in-implement.html 2 | 3 | use std::char; 4 | 5 | static NUM_TO_ASCII: &'static str = "0123456789bcdfghjklmnpqrstuvwxyz"; 6 | 7 | static ASCII_TO_NUM: [u8; 128] = [ 8 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 9 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 10 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 11 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 12 | 255, 255, 10, 11, 12, 255, 13, 14, 15, 255, 16, 17, 18, 19, 20, 255, 13 | 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 255, 255, 255, 255, 255, 14 | 255, 255, 10, 11, 12, 255, 13, 14, 15, 255, 16, 17, 18, 19, 20, 255, 15 | 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 255, 255, 255, 255, 255 16 | ]; 17 | 18 | 19 | #[inline] 20 | pub fn bytes_needed_to_encode(data_len: usize) -> usize { 21 | (data_len * 8 + 4) / 5 22 | } 23 | 24 | pub fn encode(bytes: &[u8]) -> String { 25 | let ascii_bytes = NUM_TO_ASCII.as_bytes(); 26 | let mut ret = String::with_capacity(bytes_needed_to_encode(bytes.len())); 27 | 28 | for chunk in bytes.chunks(5) { 29 | let buf = { 30 | let mut buf = [0u8; 5]; 31 | buf.clone_from_slice(chunk); 32 | buf 33 | }; 34 | 35 | let chars = [ 36 | ascii_bytes[ (buf[0] & 0b0001_1111) as usize], 37 | ascii_bytes[(((buf[0] & 0b1110_0000) >> 5) | ((buf[1] & 0b0000_0011) << 3)) as usize], 38 | ascii_bytes[ ((buf[1] & 0b0111_1100) >> 2) as usize], 39 | ascii_bytes[(((buf[1] & 0b1000_0000) >> 7) | ((buf[2] & 0b0000_1111) << 1)) as usize], 40 | ascii_bytes[(((buf[2] & 0b1111_0000) >> 4) | ((buf[3] & 0b0000_0001) << 4)) as usize], 41 | ascii_bytes[ ((buf[3] & 0b0011_1110) >> 1) as usize], 42 | ascii_bytes[(((buf[3] & 0b1100_0000) >> 6) | ((buf[4] & 0b0000_0111) << 2)) as usize], 43 | ascii_bytes[ ((buf[4] & 0b1111_1000) >> 3) as usize] 44 | ]; 45 | 46 | for &c in (&chars[..bytes_needed_to_encode(chunk.len())]).iter() { 47 | match char::from_u32(c as u32) { 48 | Some(c) => ret.push(c), 49 | None => unreachable!() 50 | } 51 | } 52 | } 53 | 54 | ret 55 | } 56 | 57 | #[inline] 58 | pub fn bytes_needed_to_decode(encoded_len: usize) -> usize { 59 | encoded_len * 5 / 8 60 | } 61 | 62 | pub fn decode(encoded: &str) -> Option> { 63 | let encoded = encoded.as_bytes(); 64 | let mut ret = Vec::with_capacity(bytes_needed_to_decode(encoded.len())); 65 | 66 | for chunk in encoded.chunks(8) { 67 | let buf = { 68 | let mut buf = [0u8; 8]; 69 | for (i, &c) in chunk.iter().enumerate() { 70 | if c >= 128 { return None; } 71 | let b = ASCII_TO_NUM[c as usize]; 72 | if b >= 32 { return None; } 73 | buf[i] = b; 74 | } 75 | buf 76 | }; 77 | 78 | let bytes = [ 79 | buf[0] | (buf[1] << 5), 80 | (buf[1] >> 3) | (buf[2] << 2) | (buf[3] << 7), 81 | (buf[3] >> 1) | (buf[4] << 4), 82 | (buf[4] >> 4) | (buf[5] << 1) | (buf[6] << 6), 83 | (buf[6] >> 2) | (buf[7] << 3) 84 | ]; 85 | 86 | ret.push_all(&bytes[..bytes_needed_to_decode(chunk.len())]); 87 | } 88 | 89 | Some(ret) 90 | } 91 | 92 | 93 | #[cfg(test)] 94 | mod tests { 95 | use super::*; 96 | 97 | #[test] 98 | fn test_encode() { 99 | assert_eq!(encode(&[]), ""); 100 | 101 | assert_eq!(encode(&[0x64, 0x88]), "4321"); 102 | 103 | let pub_key = [ 104 | 70, 197, 17, 133, 42, 61, 168, 77, 30, 202, 145, 14, 129, 130, 124, 194, 105 | 6, 77, 78, 144, 95, 114, 235, 169, 42, 35, 167, 1, 124, 66, 200, 40]; 106 | assert_eq!(encode(&pub_key), "6bk3k2b5x1bv4h8tkn3281lh2q1u471lzlwqynb53t930y9886b0"); 107 | } 108 | 109 | #[test] 110 | fn test_decode() { 111 | assert_eq!(decode("").unwrap(), []); 112 | 113 | assert_eq!(decode("4321").unwrap(), [0x64, 0x88]); 114 | 115 | let pub_key = [ 116 | 70, 197, 17, 133, 42, 61, 168, 77, 30, 202, 145, 14, 129, 130, 124, 194, 117 | 6, 77, 78, 144, 95, 114, 235, 169, 42, 35, 167, 1, 124, 66, 200, 40]; 118 | assert_eq!(decode("6bk3k2b5x1bv4h8tkn3281lh2q1u471lzlwqynb53t930y9886b0").unwrap(), pub_key); 119 | } 120 | 121 | #[test] 122 | fn test_encode_decode() { 123 | let data = []; 124 | let processed = decode(encode(&data).as_slice()).unwrap(); 125 | assert_eq!(processed.as_slice(), data.as_slice()); 126 | 127 | let data = [0x01]; 128 | let processed = decode(encode(&data).as_slice()).unwrap(); 129 | assert_eq!(processed.as_slice(), data.as_slice()); 130 | 131 | let data = [0x01, 0x02]; 132 | let processed = decode(encode(&data).as_slice()).unwrap(); 133 | assert_eq!(processed.as_slice(), data.as_slice()); 134 | 135 | let data = [0x01, 0x02, 0x03]; 136 | let processed = decode(encode(&data).as_slice()).unwrap(); 137 | assert_eq!(processed.as_slice(), data.as_slice()); 138 | 139 | let data = [0x01, 0x02, 0x03, 0x04]; 140 | let processed = decode(encode(&data).as_slice()).unwrap(); 141 | assert_eq!(processed.as_slice(), data.as_slice()); 142 | 143 | let data = [0x01, 0x02, 0x03, 0x04, 0x05]; 144 | let processed = decode(encode(&data).as_slice()).unwrap(); 145 | assert_eq!(processed.as_slice(), data.as_slice()); 146 | 147 | let data = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06]; 148 | let processed = decode(encode(&data).as_slice()).unwrap(); 149 | assert_eq!(processed.as_slice(), data.as_slice()); 150 | 151 | let data = [ 152 | 70, 197, 17, 133, 42, 61, 168, 77, 30, 202, 145, 14, 129, 130, 124, 194, 153 | 6, 77, 78, 144, 95, 114, 235, 169, 42, 35, 167, 1, 124, 66, 200, 40]; 154 | let processed = decode(encode(&data).as_slice()).unwrap(); 155 | assert_eq!(processed.as_slice(), data.as_slice()); 156 | } 157 | 158 | #[test] 159 | fn test_bytes_needed_to_encode() { 160 | assert_eq!(bytes_needed_to_encode(0), 0); 161 | assert_eq!(bytes_needed_to_encode(1), 2); 162 | assert_eq!(bytes_needed_to_encode(2), 4); 163 | assert_eq!(bytes_needed_to_encode(3), 5); 164 | assert_eq!(bytes_needed_to_encode(4), 7); 165 | assert_eq!(bytes_needed_to_encode(5), 8); 166 | assert_eq!(bytes_needed_to_encode(6), 10); 167 | assert_eq!(bytes_needed_to_encode(32), 52); 168 | } 169 | 170 | #[test] 171 | fn test_bytes_needed_to_decode() { 172 | assert_eq!(bytes_needed_to_decode(0), 0); 173 | assert_eq!(bytes_needed_to_decode(2), 1); 174 | assert_eq!(bytes_needed_to_decode(4), 2); 175 | assert_eq!(bytes_needed_to_decode(5), 3); 176 | assert_eq!(bytes_needed_to_decode(7), 4); 177 | assert_eq!(bytes_needed_to_decode(8), 5); 178 | assert_eq!(bytes_needed_to_decode(10), 6); 179 | assert_eq!(bytes_needed_to_decode(52), 32); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/cjdrs/util/big_endian.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::num::Int; 3 | 4 | #[derive(Copy, Clone, Eq, PartialEq)] 5 | pub struct BigEndian(T); 6 | 7 | impl BigEndian { 8 | #[inline] 9 | pub fn val(&self) -> T { 10 | Int::from_be(self.val_be()) 11 | } 12 | 13 | #[inline] 14 | pub fn val_be(&self) -> T { 15 | self.0 16 | } 17 | } 18 | 19 | impl fmt::Debug for BigEndian { 20 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 21 | write!(f, "{:?}", self.val()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/cjdrs/util/debug.rs: -------------------------------------------------------------------------------- 1 | 2 | pub fn as_hex(slice: &[u8]) -> String { 3 | let mut ret = "".to_string(); 4 | ret.push_str(format!("({})[", slice.len()).as_slice()); 5 | for &b in slice.iter() { 6 | let s = format!("{:02x}", b); 7 | ret.push_str(s.as_slice()); 8 | } 9 | ret + "]" 10 | } 11 | -------------------------------------------------------------------------------- /src/cjdrs/util/mod.rs: -------------------------------------------------------------------------------- 1 | pub use self::big_endian::BigEndian; 2 | 3 | pub mod base32; 4 | pub mod debug; 5 | 6 | mod big_endian; 7 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![cfg(not(test))] 2 | #![feature(core, io, os, path)] 3 | 4 | 5 | extern crate cjdrs; 6 | extern crate mio; 7 | extern crate "rustc-serialize" as rustc_serialize; 8 | extern crate docopt; 9 | 10 | use std::{os, old_io}; 11 | use docopt::Docopt; 12 | use cjdrs::CjdrsError; 13 | use cjdrs::CjdrsResult; 14 | use cjdrs::Config; 15 | use cjdrs::EventHandler; 16 | use cjdrs::device::{self, NetDevice}; 17 | use cjdrs::Router; 18 | use cjdrs::{PrivateKey, PrivateIdentity}; 19 | 20 | 21 | static USAGE: &'static str = " 22 | Usage: cjdrs --help 23 | cjdrs init [--cfg=] 24 | cjdrs run [--cfg=] 25 | 26 | Options: 27 | -h, --help Show this message. 28 | --cfg= Configuration file [default: cjdrs.conf] 29 | 30 | 1. Run 'cjdrs init' to generate a configuration file. 31 | 2. Edit the configuration file as needed. 32 | 2. Run 'cjdrs run' to start cjdrs. 33 | 34 | Configuration file defaults to 'cjdrs.conf' if not given. 35 | "; 36 | 37 | #[derive(RustcDecodable, Debug)] 38 | struct Args { 39 | cmd_init: bool, 40 | cmd_run: bool, 41 | flag_cfg: String, 42 | } 43 | 44 | fn main() { 45 | if let Err(e) = choose_command() { 46 | os::set_exit_status(1); 47 | 48 | let mut stderr = old_io::stdio::stderr(); 49 | writeln!(&mut stderr, "Error: {}", e).unwrap(); 50 | } 51 | } 52 | 53 | 54 | fn choose_command() -> CjdrsResult<()> { 55 | let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit()); 56 | let config_path = Path::new(args.flag_cfg); 57 | 58 | cjdrs::init(); 59 | 60 | if args.cmd_init { 61 | init_config(&config_path) 62 | } else { 63 | assert!(args.cmd_run); 64 | let config = try!(Config::load(&config_path)); 65 | run_cjdrs(&config) 66 | } 67 | } 68 | 69 | 70 | fn init_config(config_path: &Path) -> CjdrsResult<()> { 71 | let identity = PrivateIdentity::generate(); 72 | 73 | let config = Config::get_default(&identity); 74 | try!(config.write(config_path)); 75 | 76 | println!("Created a new configuration file '{}'", config_path.display()); 77 | println!("Public key: {}", identity.public_key); 78 | println!("Address: {}", identity.address); 79 | 80 | Ok(()) 81 | } 82 | 83 | 84 | fn run_cjdrs(config: &Config) -> CjdrsResult<()> { 85 | // Create identity 86 | let my_identity = { 87 | let private_key = try!(PrivateKey::from_string(config.privateKey.as_slice())); 88 | try!(PrivateIdentity::from_private_key(&private_key).ok_or( 89 | CjdrsError::NoAddressForPrivateKey(private_key))) 90 | }; 91 | 92 | println!("Public key: {}", my_identity.public_key); 93 | println!("Address: {}", my_identity.address); 94 | 95 | 96 | // Turn on devices 97 | let tun_device = device::Tun::new( 98 | config.tunDevice.as_slice(), 99 | &my_identity.address); 100 | println!("Opened tun device '{}'", tun_device.get_name()); 101 | 102 | let udp_device = try!(device::Udp::create(config.udpBind.as_slice())); 103 | 104 | let devices: Vec> = vec![ 105 | Box::new(tun_device) as Box, 106 | Box::new(udp_device) as Box, 107 | ]; 108 | 109 | 110 | let router = Router::new(&my_identity.address); 111 | 112 | 113 | // Start up the event loop 114 | let mut mio_loop: mio::EventLoop = try!(mio::EventLoop::new()); 115 | 116 | let event_handler = EventHandler::new( 117 | my_identity, 118 | devices, 119 | router); 120 | 121 | try!(event_handler.register_handlers(&mut mio_loop)); 122 | try!(mio_loop.run(event_handler)); 123 | 124 | Ok(()) 125 | } 126 | --------------------------------------------------------------------------------