diff --git a/daemon/rcutil.cpp b/daemon/rcutil.cpp index 29221074d..c270714c5 100644 --- a/daemon/rcutil.cpp +++ b/daemon/rcutil.cpp @@ -261,7 +261,7 @@ main(int argc, char *argv[]) if(verifyMode) { - llarp::Crypto crypto; + llarp::Crypto crypto; llarp_crypto_init(&crypto); if(!rc.Read(rcfname)) { @@ -327,7 +327,7 @@ main(int argc, char *argv[]) // this is the only one... if(listMode) { - llarp::Crypto crypto; + llarp::Crypto crypto; llarp_crypto_init(&crypto); auto nodedb = llarp_nodedb_new(&crypto); llarp_nodedb_iter itr; @@ -467,7 +467,7 @@ main(int argc, char *argv[]) if(listMode) { - llarp::Crypto crypto; + llarp::Crypto crypto; // no longer used? // llarp_crypto_libsodium_init(&crypto); llarp_crypto_init(&crypto); diff --git a/include/llarp.hpp b/include/llarp.hpp index 5419243c4..f1732edc8 100644 --- a/include/llarp.hpp +++ b/include/llarp.hpp @@ -21,8 +21,8 @@ namespace llarp int num_nethreads = 1; bool singleThreaded = false; - std::unique_ptr crypto; - llarp::Router *router = nullptr; + std::unique_ptr< llarp::Crypto > crypto; + llarp::Router *router = nullptr; llarp_threadpool *worker = nullptr; llarp::Logic *logic = nullptr; llarp_config *config = nullptr; diff --git a/llarp/address_info.cpp b/llarp/address_info.cpp index 414975560..12bbfa0ec 100644 --- a/llarp/address_info.cpp +++ b/llarp/address_info.cpp @@ -25,7 +25,7 @@ namespace llarp } bool - operator==(const AddressInfo& lhs, const AddressInfo& rhs) + operator==(const AddressInfo &lhs, const AddressInfo &rhs) { // we don't care about rank return lhs.pubkey == rhs.pubkey && lhs.port == rhs.port @@ -33,7 +33,7 @@ namespace llarp } bool - operator<(const AddressInfo& lhs, const AddressInfo& rhs) + operator<(const AddressInfo &lhs, const AddressInfo &rhs) { return lhs.rank < rhs.rank || lhs.ip < rhs.ip || lhs.port < rhs.port; } diff --git a/llarp/address_info.hpp b/llarp/address_info.hpp index ff2f88084..05081bf20 100644 --- a/llarp/address_info.hpp +++ b/llarp/address_info.hpp @@ -84,7 +84,6 @@ namespace llarp bool operator<(const AddressInfo& lhs, const AddressInfo& rhs); - } // namespace llarp #endif diff --git a/llarp/aligned.hpp b/llarp/aligned.hpp index e7768f854..2cee52b23 100644 --- a/llarp/aligned.hpp +++ b/llarp/aligned.hpp @@ -2,7 +2,6 @@ #define LLARP_ALIGNED_HPP #include -#include #include #include diff --git a/llarp/context.cpp b/llarp/context.cpp index c36bcd392..4a3d779ba 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -14,7 +14,6 @@ #include #endif - namespace llarp { Context::~Context() @@ -81,7 +80,8 @@ namespace llarp int Context::LoadDatabase() { - crypto = std::unique_ptr(new llarp::Crypto{llarp::Crypto::sodium{}}); + crypto = std::unique_ptr< llarp::Crypto >( + new llarp::Crypto{llarp::Crypto::sodium{}}); nodedb = new llarp_nodedb(crypto.get()); if(!llarp_nodedb::ensure_dir(nodedb_dir.c_str())) diff --git a/llarp/crypto.cpp b/llarp/crypto.cpp index caf42a76f..799537154 100644 --- a/llarp/crypto.cpp +++ b/llarp/crypto.cpp @@ -1,4 +1,6 @@ #include +#include +#include namespace llarp { @@ -14,4 +16,46 @@ namespace llarp char buf[(PUBKEYSIZE + 1) * 2] = {0}; return HexEncode(*this, buf); } + + bool + SecretKey::LoadFromFile(const char* fname) + { + std::ifstream f; + f.open(fname, std::ios::binary); + if(!f.is_open()) + return false; + size_t sz = 0; + f.seekg(0, std::ios::end); + sz = f.tellg(); + f.seekg(0, std::ios::beg); + if(sz == size()) + { + // is raw buffer + f.read((char*)data(), 64); + return true; + } + byte_t tmp[128]; + auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); + if(sz > sizeof(tmp)) + return false; + f.read((char*)tmp, sz); + return BDecode(&buf); + } + + bool + SecretKey::SaveToFile(const char* fname) const + { + byte_t tmp[128]; + auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); + if(!BEncode(&buf)) + return false; + + std::ofstream f; + f.open(fname, std::ios::binary); + if(!f.is_open()) + return false; + f.write((char*)buf.base, buf.cur - buf.base); + return true; + } + } // namespace llarp diff --git a/llarp/crypto.h b/llarp/crypto.h index b50b34b20..bea89e531 100644 --- a/llarp/crypto.h +++ b/llarp/crypto.h @@ -1,118 +1,6 @@ #ifndef LLARP_CRYPTO_H_ #define LLARP_CRYPTO_H_ -#include -#include - -#include -#include -#include - -/** - * crypto.h - * - * libsodium abstraction layer - * potentially allow libssl support in the future - */ - -static constexpr uint32_t PUBKEYSIZE = 32; -static constexpr uint32_t SECKEYSIZE = 64; -static constexpr uint32_t NONCESIZE = 24; -static constexpr uint32_t SHAREDKEYSIZE = 32; -static constexpr uint32_t HASHSIZE = 64; -static constexpr uint32_t SHORTHASHSIZE = 32; -static constexpr uint32_t HMACSECSIZE = 32; -static constexpr uint32_t SIGSIZE = 64; -static constexpr uint32_t TUNNONCESIZE = 32; -static constexpr uint32_t HMACSIZE = 32; -static constexpr uint32_t PATHIDSIZE = 16; - -#include - -#define PQ_CIPHERTEXTSIZE crypto_kem_CIPHERTEXTBYTES -#define PQ_PUBKEYSIZE crypto_kem_PUBLICKEYBYTES -#define PQ_SECRETKEYSIZE crypto_kem_SECRETKEYBYTES -#define PQ_KEYPAIRSIZE (PQ_SECRETKEYSIZE + PQ_PUBKEYSIZE) - -namespace llarp -{ -/// label functors - -/// PKE(result, publickey, secretkey, nonce) -using path_dh_func = std::function; - -/// TKE(result, publickey, secretkey, nonce) -using transport_dh_func = std::function; - -/// SD/SE(buffer, key, nonce) -using sym_cipher_func = std::function; - -/// H(result, body) -using hash_func = std::function; - -/// SH(result, body) -using shorthash_func = std::function; - -/// MDS(result, body, shared_secret) -using hmac_func = std::function; - -/// S(sig, secretkey, body) -using sign_func = std::function; - -/// V(pubkey, body, sig) -using verify_func = std::function; - -/// library crypto configuration -struct Crypto -{ - /// xchacha symettric cipher - sym_cipher_func xchacha20; - /// path dh creator's side - path_dh_func dh_client; - /// path dh relay side - path_dh_func dh_server; - /// transport dh client side - transport_dh_func transport_dh_client; - /// transport dh server side - transport_dh_func transport_dh_server; - /// blake2b 512 bit - hash_func hash; - /// blake2b 256 bit - shorthash_func shorthash; - /// blake2s 256 bit hmac - hmac_func hmac; - /// ed25519 sign - sign_func sign; - /// ed25519 verify - verify_func verify; - /// randomize buffer - std::function randomize; - /// randomizer memory - std::function randbytes; - /// generate signing keypair - std::function identity_keygen; - /// generate encryption keypair - std::function encryption_keygen; - /// generate post quantum encrytion key - std::function pqe_keygen; - /// post quantum decrypt (buffer, sharedkey_dst, sec) - std::function pqe_decrypt; - /// post quantum encrypt (buffer, sharedkey_dst, pub) - std::function pqe_encrypt; - - // Give a basic type tag for the constructor to pick libsodium - struct sodium {}; - - Crypto(Crypto::sodium tag); -}; - -/// return random 64bit unsigned interger -uint64_t -randint(); - -} - +#ifdef __cplusplus +#include "crypto.hpp" +#endif #endif diff --git a/llarp/crypto.hpp b/llarp/crypto.hpp index eb813f95c..a3c2b034a 100644 --- a/llarp/crypto.hpp +++ b/llarp/crypto.hpp @@ -2,21 +2,134 @@ #define LLARP_CRYPTO_HPP #include -#include #include #include #include +#include +#include + +#include +#include +#include + +/** + * crypto.h + * + * libsodium abstraction layer + * potentially allow libssl support in the future + */ + +static constexpr uint32_t PUBKEYSIZE = 32; +static constexpr uint32_t SECKEYSIZE = 64; +static constexpr uint32_t NONCESIZE = 24; +static constexpr uint32_t SHAREDKEYSIZE = 32; +static constexpr uint32_t HASHSIZE = 64; +static constexpr uint32_t SHORTHASHSIZE = 32; +static constexpr uint32_t HMACSECSIZE = 32; +static constexpr uint32_t SIGSIZE = 64; +static constexpr uint32_t TUNNONCESIZE = 32; +static constexpr uint32_t HMACSIZE = 32; +static constexpr uint32_t PATHIDSIZE = 16; + +#include + +#define PQ_CIPHERTEXTSIZE crypto_kem_CIPHERTEXTBYTES +#define PQ_PUBKEYSIZE crypto_kem_PUBLICKEYBYTES +#define PQ_SECRETKEYSIZE crypto_kem_SECRETKEYBYTES +#define PQ_KEYPAIRSIZE (PQ_SECRETKEYSIZE + PQ_PUBKEYSIZE) namespace llarp { - const byte_t* - seckey_topublic(const byte_t* secret); + /// label functors - const byte_t* - pq_keypair_to_public(const byte_t* keypair); + /// PKE(result, publickey, secretkey, nonce) + using path_dh_func = std::function< bool(byte_t *, const byte_t *, + const byte_t *, const byte_t *) >; - const byte_t* - pq_keypair_to_secret(const byte_t* keypair); + /// TKE(result, publickey, secretkey, nonce) + using transport_dh_func = std::function< bool( + byte_t *, const byte_t *, const byte_t *, const byte_t *) >; + + /// SD/SE(buffer, key, nonce) + using sym_cipher_func = + std::function< bool(llarp_buffer_t, const byte_t *, const byte_t *) >; + + /// H(result, body) + using hash_func = std::function< bool(byte_t *, llarp_buffer_t) >; + + /// SH(result, body) + using shorthash_func = std::function< bool(byte_t *, llarp_buffer_t) >; + + /// MDS(result, body, shared_secret) + using hmac_func = + std::function< bool(byte_t *, llarp_buffer_t, const byte_t *) >; + + /// S(sig, secretkey, body) + using sign_func = + std::function< bool(byte_t *, const byte_t *, llarp_buffer_t) >; + + /// V(pubkey, body, sig) + using verify_func = + std::function< bool(const byte_t *, llarp_buffer_t, const byte_t *) >; + + /// library crypto configuration + struct Crypto + { + /// xchacha symettric cipher + sym_cipher_func xchacha20; + /// path dh creator's side + path_dh_func dh_client; + /// path dh relay side + path_dh_func dh_server; + /// transport dh client side + transport_dh_func transport_dh_client; + /// transport dh server side + transport_dh_func transport_dh_server; + /// blake2b 512 bit + hash_func hash; + /// blake2b 256 bit + shorthash_func shorthash; + /// blake2s 256 bit hmac + hmac_func hmac; + /// ed25519 sign + sign_func sign; + /// ed25519 verify + verify_func verify; + /// randomize buffer + std::function< void(llarp_buffer_t) > randomize; + /// randomizer memory + std::function< void(void *, size_t) > randbytes; + /// generate signing keypair + std::function< void(byte_t *) > identity_keygen; + /// generate encryption keypair + std::function< void(byte_t *) > encryption_keygen; + /// generate post quantum encrytion key + std::function< void(byte_t *) > pqe_keygen; + /// post quantum decrypt (buffer, sharedkey_dst, sec) + std::function< bool(const byte_t *, byte_t *, const byte_t *) > pqe_decrypt; + /// post quantum encrypt (buffer, sharedkey_dst, pub) + std::function< bool(byte_t *, byte_t *, const byte_t *) > pqe_encrypt; + + // Give a basic type tag for the constructor to pick libsodium + struct sodium + { + }; + + Crypto(Crypto::sodium tag); + }; + + /// return random 64bit unsigned interger + uint64_t + randint(); + + const byte_t * + seckey_topublic(const byte_t *secret); + + const byte_t * + pq_keypair_to_public(const byte_t *keypair); + + const byte_t * + pq_keypair_to_secret(const byte_t *keypair); using SharedSecret = AlignedBuffer< SHAREDKEYSIZE >; using KeyExchangeNonce = AlignedBuffer< 32 >; @@ -24,16 +137,16 @@ namespace llarp struct PubKey final : public AlignedBuffer< PUBKEYSIZE > { PubKey() : AlignedBuffer< PUBKEYSIZE >(){}; - PubKey(const byte_t* ptr) : AlignedBuffer< PUBKEYSIZE >(ptr){}; + PubKey(const byte_t *ptr) : AlignedBuffer< PUBKEYSIZE >(ptr){}; std::string ToString() const; bool - FromString(const std::string& str); + FromString(const std::string &str); - friend std::ostream& - operator<<(std::ostream& out, const PubKey& k) + friend std::ostream & + operator<<(std::ostream &out, const PubKey &k) { return out << k.ToString(); } @@ -43,8 +156,8 @@ namespace llarp return RouterID(data()); } - PubKey& - operator=(const byte_t* ptr) + PubKey & + operator=(const byte_t *ptr) { memcpy(data(), ptr, size()); return *this; @@ -53,15 +166,21 @@ namespace llarp struct SecretKey final : public AlignedBuffer< SECKEYSIZE > { - friend std::ostream& - operator<<(std::ostream& out, const SecretKey&) + friend std::ostream & + operator<<(std::ostream &out, const SecretKey &) { // make sure we never print out secret keys return out << "[secretkey]"; } - SecretKey& - operator=(const byte_t* ptr) + bool + LoadFromFile(const char *fname); + + bool + SaveToFile(const char *fname) const; + + SecretKey & + operator=(const byte_t *ptr) { memcpy(data(), ptr, size()); return *this; diff --git a/llarp/crypto_libsodium.cpp b/llarp/crypto_libsodium.cpp index 48b8648db..43d1c3df5 100644 --- a/llarp/crypto_libsodium.cpp +++ b/llarp/crypto_libsodium.cpp @@ -174,43 +174,42 @@ namespace llarp } Crypto::Crypto(Crypto::sodium tag) -{ - (void)tag; - assert(sodium_init() != -1); - char *avx2 = std::getenv("AVX2_FORCE_DISABLE"); - if(avx2 && std::string(avx2) == "1") - ntru_init(1); - else - ntru_init(0); - this->xchacha20 = llarp::sodium::xchacha20; - this->dh_client = llarp::sodium::dh_client; - this->dh_server = llarp::sodium::dh_server; - this->transport_dh_client = llarp::sodium::dh_client; - this->transport_dh_server = llarp::sodium::dh_server; - this->hash = llarp::sodium::hash; - this->shorthash = llarp::sodium::shorthash; - this->hmac = llarp::sodium::hmac; - this->sign = llarp::sodium::sign; - this->verify = llarp::sodium::verify; - this->randomize = llarp::sodium::randomize; - this->randbytes = llarp::sodium::randbytes; - this->identity_keygen = llarp::sodium::sigkeygen; - this->encryption_keygen = llarp::sodium::enckeygen; - this->pqe_encrypt = llarp::pq::encrypt; - this->pqe_decrypt = llarp::pq::decrypt; - this->pqe_keygen = llarp::pq::keygen; - int seed = 0; - this->randbytes(&seed, sizeof(seed)); - srand(seed); -} - -uint64_t -randint() -{ - uint64_t i; - randombytes((byte_t *)&i, sizeof(i)); - return i; -} + { + (void)tag; + assert(sodium_init() != -1); + char *avx2 = std::getenv("AVX2_FORCE_DISABLE"); + if(avx2 && std::string(avx2) == "1") + ntru_init(1); + else + ntru_init(0); + this->xchacha20 = llarp::sodium::xchacha20; + this->dh_client = llarp::sodium::dh_client; + this->dh_server = llarp::sodium::dh_server; + this->transport_dh_client = llarp::sodium::dh_client; + this->transport_dh_server = llarp::sodium::dh_server; + this->hash = llarp::sodium::hash; + this->shorthash = llarp::sodium::shorthash; + this->hmac = llarp::sodium::hmac; + this->sign = llarp::sodium::sign; + this->verify = llarp::sodium::verify; + this->randomize = llarp::sodium::randomize; + this->randbytes = llarp::sodium::randbytes; + this->identity_keygen = llarp::sodium::sigkeygen; + this->encryption_keygen = llarp::sodium::enckeygen; + this->pqe_encrypt = llarp::pq::encrypt; + this->pqe_decrypt = llarp::pq::decrypt; + this->pqe_keygen = llarp::pq::keygen; + int seed = 0; + this->randbytes(&seed, sizeof(seed)); + srand(seed); + } + uint64_t + randint() + { + uint64_t i; + randombytes((byte_t *)&i, sizeof(i)); + return i; + } } // namespace llarp diff --git a/llarp/dht.h b/llarp/dht.h index b3b5c90b3..86966812a 100644 --- a/llarp/dht.h +++ b/llarp/dht.h @@ -13,7 +13,10 @@ struct llarp_dht_context; -namespace llarp { struct Router; } +namespace llarp +{ + struct Router; +} /// allocator struct llarp_dht_context* diff --git a/llarp/dht/context.hpp b/llarp/dht/context.hpp index 1f8163925..fd23223ba 100644 --- a/llarp/dht/context.hpp +++ b/llarp/dht/context.hpp @@ -235,7 +235,8 @@ namespace llarp /// initialize dht context and explore every exploreInterval milliseconds void - Init(const Key_t& us, llarp::Router* router, llarp_time_t exploreInterval); + Init(const Key_t& us, llarp::Router* router, + llarp_time_t exploreInterval); /// get localally stored introset by service address const llarp::service::IntroSet* diff --git a/llarp/dns/dns.hpp b/llarp/dns/dns.hpp index 33059aacd..52c837eb0 100644 --- a/llarp/dns/dns.hpp +++ b/llarp/dns/dns.hpp @@ -3,3 +3,18 @@ #include #include #include + +namespace llarp +{ + namespace dns + { + constexpr uint16_t qTypeTXT = 16; + constexpr uint16_t qTypeMX = 15; + constexpr uint16_t qTypePTR = 12; + constexpr uint16_t qTypeCNAME = 5; + constexpr uint16_t qTypeNS = 2; + constexpr uint16_t qTypeA = 1; + + constexpr uint16_t qClassIN = 1; + } // namespace dns +} // namespace llarp \ No newline at end of file diff --git a/llarp/dns/message.cpp b/llarp/dns/message.cpp index d6a0e9879..cc2b39918 100644 --- a/llarp/dns/message.cpp +++ b/llarp/dns/message.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -148,7 +148,7 @@ namespace llarp } void - Message::AddINReply(llarp::huint32_t ip) + Message::AddINReply(llarp::huint32_t ip, RR_TTL_t ttl) { if(questions.size()) { @@ -156,9 +156,9 @@ namespace llarp const auto& question = questions[0]; ResourceRecord rec; rec.rr_name = question.qname; - rec.rr_type = 1; - rec.rr_class = 1; - rec.ttl = 1; + rec.rr_type = qTypeA; + rec.rr_class = qClassIN; + rec.ttl = ttl; rec.rData.resize(4); htobe32buf(rec.rData.data(), ip.h); answers.emplace_back(std::move(rec)); @@ -166,7 +166,7 @@ namespace llarp } void - Message::AddAReply(std::string name) + Message::AddAReply(std::string name, RR_TTL_t ttl) { if(questions.size()) { @@ -176,8 +176,8 @@ namespace llarp auto& rec = answers.back(); rec.rr_name = question.qname; rec.rr_type = question.qtype; - rec.rr_class = 1; - rec.ttl = 1; + rec.rr_class = qClassIN; + rec.ttl = ttl; byte_t tmp[512] = {0}; auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); if(EncodeName(&buf, name)) @@ -190,7 +190,7 @@ namespace llarp } void - Message::AddCNAMEReply(std::string name, uint32_t ttl) + Message::AddCNAMEReply(std::string name, RR_TTL_t ttl) { if(questions.size()) { @@ -199,8 +199,8 @@ namespace llarp answers.emplace_back(); auto& rec = answers.back(); rec.rr_name = question.qname; - rec.rr_type = 5; - rec.rr_class = 1; + rec.rr_type = qTypeCNAME; + rec.rr_class = qClassIN; rec.ttl = ttl; byte_t tmp[512] = {0}; auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); @@ -214,7 +214,7 @@ namespace llarp } void - Message::AddMXReply(std::string name, uint16_t priority) + Message::AddMXReply(std::string name, uint16_t priority, RR_TTL_t ttl) { if(questions.size()) { @@ -223,9 +223,9 @@ namespace llarp answers.emplace_back(); auto& rec = answers.back(); rec.rr_name = question.qname; - rec.rr_type = question.qtype; - rec.rr_class = 1; - rec.ttl = 1; + rec.rr_type = qTypeMX; + rec.rr_class = qClassIN; + rec.ttl = ttl; byte_t tmp[512] = {0}; auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); llarp_buffer_put_uint16(&buf, priority); @@ -239,7 +239,7 @@ namespace llarp } void - Message::AddNXReply() + Message::AddNXReply(RR_TTL_t ttl) { if(questions.size()) { @@ -250,7 +250,7 @@ namespace llarp nx.rr_name = question.qname; nx.rr_type = question.qtype; nx.rr_class = question.qclass; - nx.ttl = 1; + nx.ttl = ttl; nx.rData.resize(1); nx.rData.data()[0] = 0; } diff --git a/llarp/dns/message.hpp b/llarp/dns/message.hpp index ccf70f3ee..c0ca2c331 100644 --- a/llarp/dns/message.hpp +++ b/llarp/dns/message.hpp @@ -51,19 +51,19 @@ namespace llarp UpdateHeader(); void - AddNXReply(); + AddNXReply(RR_TTL_t ttl = 1); void - AddMXReply(std::string name, uint16_t priority); + AddMXReply(std::string name, uint16_t priority, RR_TTL_t ttl = 1); void - AddCNAMEReply(std::string name, uint32_t ttl); + AddCNAMEReply(std::string name, RR_TTL_t ttl = 1); void - AddINReply(llarp::huint32_t addr); + AddINReply(llarp::huint32_t addr, RR_TTL_t ttl = 1); void - AddAReply(std::string name); + AddAReply(std::string name, RR_TTL_t ttl = 1); bool Encode(llarp_buffer_t* buf) const override; diff --git a/llarp/dns_dotlokilookup.hpp b/llarp/dns_dotlokilookup.hpp index 8b93a8027..73a6fc012 100644 --- a/llarp/dns_dotlokilookup.hpp +++ b/llarp/dns_dotlokilookup.hpp @@ -4,7 +4,6 @@ #include #include - using map_address_hook_func = std::function< bool(const byte_t *addr, bool isSNode, uint32_t ip) >; diff --git a/llarp/dnsc.cpp b/llarp/dnsc.cpp index 9d58de371..88fbb4526 100644 --- a/llarp/dnsc.cpp +++ b/llarp/dnsc.cpp @@ -14,8 +14,8 @@ #include #include /* close */ -#include // for std::find_if -#include // sprintf +#include // for std::find_if +#include // sprintf #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) diff --git a/llarp/dnsd.hpp b/llarp/dnsd.hpp index 1667c65a0..81f1b080e 100644 --- a/llarp/dnsd.hpp +++ b/llarp/dnsd.hpp @@ -1,7 +1,7 @@ #ifndef LIBLLARP_DNSD_HPP #define LIBLLARP_DNSD_HPP -#include // for sockaadr +#include // for sockaadr #include // question and dnsc #include diff --git a/llarp/ev.cpp b/llarp/ev.cpp index 8b23a03b1..7786c5de2 100644 --- a/llarp/ev.cpp +++ b/llarp/ev.cpp @@ -5,7 +5,6 @@ #include - #define EV_TICK_INTERVAL 100 // apparently current Solaris will emulate epoll. diff --git a/llarp/ev_kqueue.hpp b/llarp/ev_kqueue.hpp index 8801dd3a0..8ab35e263 100644 --- a/llarp/ev_kqueue.hpp +++ b/llarp/ev_kqueue.hpp @@ -267,7 +267,7 @@ namespace llarp { // all BSD UNIX has pktinfo by default const ssize_t offset = 4; - ssize_t ret = tuntap_read(tunif, buf, sz); + ssize_t ret = tuntap_read(tunif, buf, sz); if(ret > offset && t->recvpkt) { buf += offset; diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index e7324de09..98228f740 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -22,6 +22,12 @@ namespace llarp { } + bool + BaseSession::LoadIdentityFromFile(const char* fname) + { + return m_ExitIdentity.LoadFromFile(fname); + } + bool BaseSession::ShouldBuildMore(llarp_time_t now) const { @@ -173,5 +179,16 @@ namespace llarp return true; } + SNodeSession::SNodeSession(const llarp::RouterID& snodeRouter, + std::function< bool(llarp_buffer_t) > writepkt, + llarp::Router* r, size_t numpaths, size_t hoplen, + bool useRouterSNodeKey) + : BaseSession(snodeRouter, writepkt, r, numpaths, hoplen) + { + if(useRouterSNodeKey) + { + m_ExitIdentity = r->identity; + } + } } // namespace exit } // namespace llarp diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index c2ca86a8a..720e468c5 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -52,8 +52,12 @@ namespace llarp bool IsExpired(llarp_time_t now) const; + bool + LoadIdentityFromFile(const char* fname); + protected: llarp::RouterID m_ExitRouter; + llarp::SecretKey m_ExitIdentity; std::function< bool(llarp_buffer_t) > m_WritePacket; virtual void @@ -75,7 +79,6 @@ namespace llarp using TieredQueue_t = std::map< uint8_t, UpstreamTrafficQueue_t >; TieredQueue_t m_Upstream; uint64_t m_Counter; - llarp::SecretKey m_ExitIdentity; llarp_time_t m_LastUse; }; @@ -102,8 +105,8 @@ namespace llarp { SNodeSession(const llarp::RouterID& snodeRouter, std::function< bool(llarp_buffer_t) > writepkt, - llarp::Router* r, size_t numpaths, size_t hoplen) - : BaseSession(snodeRouter, writepkt, r, numpaths, hoplen){}; + llarp::Router* r, size_t numpaths, size_t hoplen, + bool useRouterSNodeKey = false); ~SNodeSession(){}; diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 6df3705bd..0d13b0e60 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -2,7 +2,7 @@ #include #include #include - +#include #include namespace llarp @@ -14,6 +14,7 @@ namespace llarp { static_cast< ExitEndpoint * >(tun->user)->OnInetPacket(buf); } + static void ExitHandlerFlush(llarp_tun_io *tun) { @@ -22,8 +23,10 @@ namespace llarp ExitEndpoint::ExitEndpoint(const std::string &name, llarp::Router *r) : m_Router(r) + , m_Resolver(r->netloop, this) , m_Name(name) , m_Tun{{0}, 0, {0}, 0, 0, 0, 0, 0, 0, 0} + , m_LocalResolverAddr("127.0.0.1", 53) , m_InetToNetwork(name + "_exit_rx", r->netloop, r->netloop) { @@ -37,6 +40,89 @@ namespace llarp { } + bool + ExitEndpoint::ShouldHookDNSMessage(const llarp::dns::Message &msg) const + { + if(msg.questions.size() == 0) + return false; + if(msg.questions[0].qtype == llarp::dns::qTypePTR) + { + llarp::huint32_t ip; + if(!llarp::dns::DecodePTR(msg.questions[0].qname, ip)) + return false; + return m_OurRange.Contains(ip); + } + else if(msg.questions[0].qtype == llarp::dns::qTypeA) + { + return msg.questions[0].qname.find(".snode.") + == (msg.questions[0].qname.size() - 7); + } + else + return false; + } + + bool + ExitEndpoint::HandleHookedDNSMessage( + llarp::dns::Message msg, + std::function< void(llarp::dns::Message) > reply) + { + if(msg.questions[0].qtype == llarp::dns::qTypePTR) + { + llarp::huint32_t ip; + if(!llarp::dns::DecodePTR(msg.questions[0].qname, ip)) + return false; + if(ip == m_IfAddr) + { + RouterID us = Router()->pubkey(); + msg.AddAReply(us.ToString(), 300); + } + else + { + auto itr = m_IPToKey.find(ip); + if(itr != m_IPToKey.end() + && m_SNodeKeys.find(itr->second) != m_SNodeKeys.end()) + { + RouterID them = itr->second; + msg.AddAReply(them.ToString()); + } + else + msg.AddNXReply(); + } + } + else if(msg.questions[0].qtype == llarp::dns::qTypeA) + { + // forward dns for snode + RouterID r; + if(r.FromString(msg.questions[0].qname)) + { + huint32_t ip; + if(m_SNodeKeys.find(r.data()) == m_SNodeKeys.end()) + { + // we do not have it mapped + // map it + ip = ObtainServiceNodeIP(r); + msg.AddINReply(ip); + } + else + { + // we have it mapped already as a service node + auto itr = m_KeyToIP.find(r.data()); + if(itr != m_KeyToIP.end()) + { + ip = itr->second; + msg.AddINReply(ip); + } + else // fallback case that should never happen (probably) + msg.AddNXReply(); + } + } + else + msg.AddNXReply(); + } + reply(msg); + return true; + } + llarp_time_t ExitEndpoint::Now() const { @@ -60,6 +146,20 @@ namespace llarp } pk = itr->second; } + // check if this key is a service node + if(m_SNodeKeys.find(pk) != m_SNodeKeys.end()) + { + // check if it's a service node session we made and queue it via our + // snode session that we made otherwise use an inbound session that + // was made by the other service node + auto itr = m_SNodeSessions.find(pk); + if(itr != m_SNodeSessions.end()) + { + if(itr->second->QueueUpstreamTraffic(pkt, + llarp::routing::ExitPadSize)) + return; + } + } llarp::exit::Endpoint *ep = nullptr; auto range = m_ActiveExits.equal_range(pk); auto itr = range.first; @@ -90,14 +190,29 @@ namespace llarp } } }); - auto itr = m_ActiveExits.begin(); - while(itr != m_ActiveExits.end()) { - if(!itr->second->Flush()) + auto itr = m_ActiveExits.begin(); + while(itr != m_ActiveExits.end()) { - llarp::LogWarn("exit session with ", itr->first, " dropped packets"); + if(!itr->second->Flush()) + { + llarp::LogWarn("exit session with ", itr->first, + " dropped packets"); + } + ++itr; + } + } + { + auto itr = m_SNodeSessions.begin(); + while(itr != m_SNodeSessions.end()) + { + if(!itr->second->FlushUpstreamTraffic()) + { + llarp::LogWarn("failed to flushsnode traffic to ", itr->first, + " via outbound session"); + } + ++itr; } - ++itr; } } @@ -105,7 +220,13 @@ namespace llarp ExitEndpoint::Start() { if(m_ShouldInitTun) - return llarp_ev_add_tun(Router()->netloop, &m_Tun); + { + if(!llarp_ev_add_tun(Router()->netloop, &m_Tun)) + return false; + if(m_UpstreamResolvers.size() == 0) + m_UpstreamResolvers.emplace_back("8.8.8.8", 53); + return m_Resolver.Start(m_LocalResolverAddr, m_UpstreamResolvers); + } return true; } @@ -224,6 +345,17 @@ namespace llarp [buf](Pkt_t &pkt) -> bool { return pkt.Load(buf); }); } + bool + ExitEndpoint::QueueSNodePacket(llarp_buffer_t buf, llarp::huint32_t from) + { + llarp::net::IPv4Packet pkt; + if(!pkt.Load(buf)) + return false; + // rewrite ip + pkt.UpdateIPv4PacketOnDst(from, m_IfAddr); + return llarp_ev_tun_async_write(&m_Tun, pkt.Buffer()); + } + llarp::exit::Endpoint * ExitEndpoint::FindEndpointByPath(const llarp::PathID_t &path) { @@ -271,6 +403,33 @@ namespace llarp m_PermitExit = IsTrueValue(v.c_str()); return true; } + if(k == "local-dns") + { + std::string resolverAddr = v; + uint16_t dnsport = 53; + auto pos = v.find(":"); + if(pos != std::string::npos) + { + resolverAddr = v.substr(0, pos); + dnsport = std::atoi(v.substr(pos + 1).c_str()); + } + m_LocalResolverAddr = llarp::Addr(resolverAddr, dnsport); + llarp::LogInfo(Name(), " local dns set to ", m_LocalResolverAddr); + } + if(k == "upstream-dns") + { + std::string resolverAddr = v; + uint16_t dnsport = 53; + auto pos = v.find(":"); + if(pos != std::string::npos) + { + resolverAddr = v.substr(0, pos); + dnsport = std::atoi(v.substr(pos + 1).c_str()); + } + m_UpstreamResolvers.emplace_back(resolverAddr, dnsport); + llarp::LogInfo(Name(), "adding upstream dns set to ", resolverAddr, ":", + dnsport); + } if(k == "ifaddr") { auto pos = v.find("/"); @@ -286,9 +445,11 @@ namespace llarp m_Tun.netmask = std::atoi(nmask_str.c_str()); llarp::Addr ifaddr(host_str); - m_IfAddr = ifaddr.xtohl(); - m_NextAddr = m_IfAddr; - m_HigestAddr = m_IfAddr ^ (~llarp::netmask_ipv4_bits(m_Tun.netmask)); + m_IfAddr = ifaddr.xtohl(); + m_OurRange.netmask_bits = netmask_ipv4_bits(m_Tun.netmask); + m_OurRange.addr = m_IfAddr; + m_NextAddr = m_IfAddr; + m_HigestAddr = m_IfAddr | (~m_OurRange.netmask_bits); llarp::LogInfo(Name(), " set ifaddr range to ", m_Tun.ifaddr, "/", m_Tun.netmask, " lo=", m_IfAddr, " hi=", m_HigestAddr); } @@ -313,6 +474,25 @@ namespace llarp return true; } + huint32_t + ExitEndpoint::ObtainServiceNodeIP(const llarp::RouterID &other) + { + huint32_t ip = GetIPForIdent(other.data()); + if(m_SNodeKeys.insert(other.data()).second) + { + // this is a new service node make an outbound session to them + m_SNodeSessions.insert( + std::make_pair(other, + std::unique_ptr< llarp::exit::SNodeSession >( + new llarp::exit::SNodeSession( + other, + std::bind(&ExitEndpoint::QueueSNodePacket, + this, std::placeholders::_1, ip), + Router(), 2, 1, true)))); + } + return ip; + } + bool ExitEndpoint::AllocateNewExit(const llarp::PubKey pk, const llarp::PathID_t &path, @@ -321,10 +501,17 @@ namespace llarp if(wantInternet && !m_PermitExit) return false; huint32_t ip = GetIPForIdent(pk); + if(Router()->paths.TransitHopPreviousIsRouter(path, pk.data())) + { + // we think this path belongs to a service node + // mark it as such so we don't make an outbound session to them + m_SNodeKeys.insert(pk.data()); + } m_ActiveExits.insert( std::make_pair(pk, std::make_unique< llarp::exit::Endpoint >( pk, path, !wantInternet, ip, this))); + m_Paths[path] = pk; return HasLocalMappedAddrFor(pk); } @@ -361,17 +548,29 @@ namespace llarp void ExitEndpoint::Tick(llarp_time_t now) { - auto itr = m_ActiveExits.begin(); - while(itr != m_ActiveExits.end()) { - if(itr->second->IsExpired(now)) + auto itr = m_SNodeSessions.begin(); + while(itr != m_SNodeSessions.end()) { - itr = m_ActiveExits.erase(itr); + if(itr->second->IsExpired(now)) + itr = m_SNodeSessions.erase(itr); + else + ++itr; } - else + } + { + auto itr = m_ActiveExits.begin(); + while(itr != m_ActiveExits.end()) { - itr->second->Tick(now); - ++itr; + if(itr->second->IsExpired(now)) + { + itr = m_ActiveExits.erase(itr); + } + else + { + itr->second->Tick(now); + ++itr; + } } } } diff --git a/llarp/handlers/exit.hpp b/llarp/handlers/exit.hpp index 6101c79be..e0ae142c5 100644 --- a/llarp/handlers/exit.hpp +++ b/llarp/handlers/exit.hpp @@ -3,14 +3,14 @@ #include #include - +#include #include namespace llarp { namespace handlers { - struct ExitEndpoint + struct ExitEndpoint : public llarp::dns::IQueryHandler { ExitEndpoint(const std::string& name, llarp::Router* r); ~ExitEndpoint(); @@ -24,6 +24,14 @@ namespace llarp std::string Name() const; + bool + ShouldHookDNSMessage(const llarp::dns::Message& msg) const override; + + bool + HandleHookedDNSMessage( + llarp::dns::Message, + std::function< void(llarp::dns::Message) >) override; + bool AllocateNewExit(const llarp::PubKey pk, const llarp::PathID_t& path, bool permitInternet); @@ -95,6 +103,14 @@ namespace llarp huint32_t AllocateNewAddress(); + /// obtain ip for service node session, creates a new session if one does + /// not existing already + huint32_t + ObtainServiceNodeIP(const llarp::RouterID& router); + + bool + QueueSNodePacket(llarp_buffer_t buf, llarp::huint32_t from); + void MarkIPActive(llarp::huint32_t ip); @@ -102,6 +118,7 @@ namespace llarp KickIdentOffExit(const llarp::PubKey& pk); llarp::Router* m_Router; + llarp::dns::Proxy m_Resolver; bool m_ShouldInitTun; std::string m_Name; bool m_PermitExit; @@ -118,6 +135,17 @@ namespace llarp KeyMap_t m_KeyToIP; + using SNodes_t = std::set< llarp::PubKey >; + /// set of pubkeys we treat as snodes + SNodes_t m_SNodeKeys; + + using SNodeSessions_t = + std::unordered_map< llarp::RouterID, + std::unique_ptr< llarp::exit::SNodeSession >, + llarp::RouterID::Hash >; + /// snode sessions we are talking to directly + SNodeSessions_t m_SNodeSessions; + std::unordered_map< llarp::huint32_t, llarp::PubKey, llarp::huint32_t::Hash > m_IPToKey; @@ -125,6 +153,7 @@ namespace llarp huint32_t m_IfAddr; huint32_t m_HigestAddr; huint32_t m_NextAddr; + llarp::IPRange m_OurRange; std::unordered_map< llarp::huint32_t, llarp_time_t, llarp::huint32_t::Hash > @@ -132,6 +161,9 @@ namespace llarp llarp_tun_io m_Tun; + llarp::Addr m_LocalResolverAddr; + std::vector< llarp::Addr > m_UpstreamResolvers; + using Pkt_t = llarp::net::IPv4Packet; using PacketQueue_t = llarp::util::CoDelQueue< Pkt_t, Pkt_t::GetTime, Pkt_t::PutTime, diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 4c48fa7ef..17d68f828 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -10,6 +10,7 @@ #include #include +#include namespace llarp { @@ -279,7 +280,7 @@ namespace llarp if(msg.questions.size() == 1) { // always hook mx records - if(msg.questions[0].qtype == 15) + if(msg.questions[0].qtype == llarp::dns::qTypeMX) return true; if(msg.questions[0].qname == "random.snode" || msg.questions[0].qname == "random.snode.") @@ -290,7 +291,7 @@ namespace llarp // always hook .snode if(addr.FromString(msg.questions[0].qname, ".snode")) return true; - if(msg.questions[0].qtype == 12) + if(msg.questions[0].qtype == llarp::dns::qTypePTR) { huint32_t ip = {0}; if(!dns::DecodePTR(msg.questions[0].qname, ip)) diff --git a/llarp/iwp.hpp b/llarp/iwp.hpp index a95189fd2..155715f8e 100644 --- a/llarp/iwp.hpp +++ b/llarp/iwp.hpp @@ -5,10 +5,11 @@ #include -namespace llarp { - class Logic; - struct Router; -} +namespace llarp +{ + class Logic; + struct Router; +} // namespace llarp struct llarp_iwp_args { diff --git a/llarp/link/utp.cpp b/llarp/link/utp.cpp index 57cf67a60..6fc6c4a74 100644 --- a/llarp/link/utp.cpp +++ b/llarp/link/utp.cpp @@ -11,7 +11,6 @@ #include #include - #ifdef __linux__ #include #include @@ -326,7 +325,7 @@ namespace llarp struct LinkLayer : public ILinkLayer { utp_context* _utp_ctx = nullptr; - llarp::Router* router = nullptr; + llarp::Router* router = nullptr; static uint64 OnRead(utp_callback_arguments* arg); diff --git a/llarp/link_message.cpp b/llarp/link_message.cpp index 0f7ff3de9..4531d1afc 100644 --- a/llarp/link_message.cpp +++ b/llarp/link_message.cpp @@ -5,8 +5,7 @@ namespace llarp { - InboundMessageParser::InboundMessageParser(Router* _router) - : router(_router) + InboundMessageParser::InboundMessageParser(Router* _router) : router(_router) { } diff --git a/llarp/path.cpp b/llarp/path.cpp index 07546d08e..1a98b0e04 100644 --- a/llarp/path.cpp +++ b/llarp/path.cpp @@ -174,6 +174,17 @@ namespace llarp }); } + bool + PathContext::TransitHopPreviousIsRouter(const PathID_t& path, + const RouterID& otherRouter) + { + util::Lock lock(m_TransitPaths.first); + auto itr = m_TransitPaths.second.find(path); + if(itr == m_TransitPaths.second.end()) + return false; + return itr->second->info.downstream == otherRouter; + } + IHopHandler* PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id) { diff --git a/llarp/path.hpp b/llarp/path.hpp index a26bc425d..d769c50b3 100644 --- a/llarp/path.hpp +++ b/llarp/path.hpp @@ -581,6 +581,9 @@ namespace llarp IHopHandler* GetByUpstream(const RouterID& id, const PathID_t& path); + bool + TransitHopPreviousIsRouter(const PathID_t& path, const RouterID& r); + IHopHandler* GetPathForTransfer(const PathID_t& topath); diff --git a/llarp/pathbuilder.cpp b/llarp/pathbuilder.cpp index 2b083b22a..941ed907e 100644 --- a/llarp/pathbuilder.cpp +++ b/llarp/pathbuilder.cpp @@ -23,7 +23,7 @@ namespace llarp llarp::Router* router = nullptr; llarp_threadpool* worker = nullptr; llarp::Logic* logic = nullptr; - llarp::Crypto* crypto = nullptr; + llarp::Crypto* crypto = nullptr; LR_CommitMessage LRCM; static void diff --git a/llarp/routing/path_confirm.cpp b/llarp/routing/path_confirm.cpp index 4a790955b..033f32841 100644 --- a/llarp/routing/path_confirm.cpp +++ b/llarp/routing/path_confirm.cpp @@ -50,7 +50,8 @@ namespace llarp } bool - PathConfirmMessage::HandleMessage(IMessageHandler* h, llarp::Router* r) const + PathConfirmMessage::HandleMessage(IMessageHandler* h, + llarp::Router* r) const { return h && h->HandlePathConfirmMessage(this, r); } diff --git a/llarp/routing/path_latency.cpp b/llarp/routing/path_latency.cpp index f6329c3eb..2f4dafde3 100644 --- a/llarp/routing/path_latency.cpp +++ b/llarp/routing/path_latency.cpp @@ -45,7 +45,8 @@ namespace llarp } bool - PathLatencyMessage::HandleMessage(IMessageHandler* h, llarp::Router* r) const + PathLatencyMessage::HandleMessage(IMessageHandler* h, + llarp::Router* r) const { return h && h->HandlePathLatencyMessage(this, r); } diff --git a/llarp/service/lookup.cpp b/llarp/service/lookup.cpp index 32a64a0c3..73d617120 100644 --- a/llarp/service/lookup.cpp +++ b/llarp/service/lookup.cpp @@ -16,7 +16,8 @@ namespace llarp } bool - IServiceLookup::SendRequestViaPath(llarp::path::Path *path, llarp::Router *r) + IServiceLookup::SendRequestViaPath(llarp::path::Path *path, + llarp::Router *r) { auto msg = BuildRequestMessage(); if(!msg) diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index 1f5991b5c..c5032caa4 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -208,7 +208,7 @@ namespace llarp struct AsyncFrameDecrypt { - llarp::Crypto* crypto; + llarp::Crypto* crypto; llarp::Logic* logic; ProtocolMessage* msg; const Identity& m_LocalIdentity; diff --git a/test/alignedbuffer_unittest.cpp b/test/alignedbuffer_unittest.cpp index 632f1e9e8..91d034d88 100644 --- a/test/alignedbuffer_unittest.cpp +++ b/test/alignedbuffer_unittest.cpp @@ -1,14 +1,13 @@ #include -#include +#include using Buffer_t = llarp::AlignedBuffer< 32 >; using Map_t = std::unordered_map< Buffer_t, int, Buffer_t::Hash >; struct AlignedBufferTest : public ::testing::Test { - AlignedBufferTest() - : crypto(llarp::Crypto::sodium{}) + AlignedBufferTest() : crypto(llarp::Crypto::sodium{}) { } diff --git a/test/base32_unittest.cpp b/test/base32_unittest.cpp index f674340fc..a8a84b9ee 100644 --- a/test/base32_unittest.cpp +++ b/test/base32_unittest.cpp @@ -1,13 +1,12 @@ #include -#include +#include #include #include struct Base32Test : public ::testing::Test { - Base32Test() - : crypto(llarp::Crypto::sodium{}) + Base32Test() : crypto(llarp::Crypto::sodium{}) { }