diff --git a/src/ringdht/namedirectory.cpp b/src/ringdht/namedirectory.cpp index 6152a71be94bb4aa7630ca7185eb7fcd6830385f..253030bf1aa8953ab111dbd85a37f8bd9fa03483 100644 --- a/src/ringdht/namedirectory.cpp +++ b/src/ringdht/namedirectory.cpp @@ -40,6 +40,7 @@ constexpr const char* const QUERY_NAME {"/name/"}; constexpr const char* const QUERY_ADDR {"/addr/"}; constexpr const char* const HTTPS_PROTO {"https://"}; constexpr const char* const CACHE_DIRECTORY {"namecache"}; +const std::string HEX_PREFIX = "0x"; /** Parser for URIs. ( protocol ) ( username ) ( hostname ) */ const std::regex URI_VALIDATOR {"^([a-zA-Z]+:(?://)?)?(?:([a-z0-9-_]{1,64})@)?([a-zA-Z0-9\\-._~%!$&'()*+,;=:\\[\\]]+)"}; @@ -66,7 +67,7 @@ NameDirectory::lookupUri(const std::string& uri, const std::string& default_serv } } RING_ERR("Can't parse URI: %s", uri.c_str()); - cb("", Response::invalidName); + cb("", Response::invalidResponse); } NameDirectory::NameDirectory(const std::string& s) @@ -168,14 +169,18 @@ void NameDirectory::lookupAddress(const std::string& addr, LookupCallback cb) } } -static const std::string HEX_PREFIX {"0x"}; +bool +NameDirectory::verify(const std::string& name, const dht::crypto::PublicKey& pk, const std::string& signature) +{ + return pk.checkSignature(std::vector<uint8_t>(name.begin(), name.end()), base64::decode(signature)); +} void NameDirectory::lookupName(const std::string& n, LookupCallback cb) { try { std::string name {n}; if (not validateName(name)) { - cb(name, Response::invalidName); + cb(name, Response::invalidResponse); return; } toLower(name); @@ -217,20 +222,37 @@ void NameDirectory::lookupName(const std::string& n, LookupCallback cb) return; } auto addr = json["addr"].asString(); + auto publickey = json["publickey"].asString(); + auto signature = json["signature"].asString(); + if (!addr.compare(0, HEX_PREFIX.size(), HEX_PREFIX)) addr = addr.substr(HEX_PREFIX.size()); - if (not addr.empty()) { - RING_DBG("Found address for %s: %s", name.c_str(), addr.c_str()); - { - std::lock_guard<std::mutex> l(lock_); - addrCache_.emplace(name, addr); - nameCache_.emplace(addr, name); - } - cb(addr, Response::found); - saveCache(); - } else { + if (addr.empty()) { cb("", Response::notFound); + return; + } + + if (not publickey.empty() and not signature.empty()) { + try { + auto pk = dht::crypto::PublicKey(base64::decode(publickey)); + if(pk.getId().toString() != addr or not verify(name, pk, signature)) { + cb("", Response::invalidResponse); + return; + } + } catch (const std::exception& e) { + cb("", Response::invalidResponse); + return; + } + } + + RING_DBG("Found address for %s: %s", name.c_str(), addr.c_str()); + { + std::lock_guard<std::mutex> l(lock_); + addrCache_.emplace(name, addr); + nameCache_.emplace(addr, name); } + cb(addr, Response::found); + saveCache(); } else if (code >= 400 && code < 500) { cb("", Response::notFound); } else { diff --git a/src/ringdht/namedirectory.h b/src/ringdht/namedirectory.h index 5929c18bd1644fedc0acf5d6c49c8a0afdeddc1e..f9ffca1c3bdb4d9991212f0add9647901df511ac 100644 --- a/src/ringdht/namedirectory.h +++ b/src/ringdht/namedirectory.h @@ -18,7 +18,7 @@ #pragma once #include "noncopyable.h" - +#include "opendht/crypto.h" #include <functional> #include <map> #include <string> @@ -29,7 +29,7 @@ namespace ring { class NameDirectory { public: - enum class Response : int { found = 0, invalidName, notFound, error }; + enum class Response : int { found = 0, invalidResponse, notFound, error }; enum class RegistrationResponse : int { success = 0, invalidName, alreadyTaken, @@ -84,6 +84,7 @@ private: } bool validateName(const std::string& name) const; + static bool verify(const std::string& name, const dht::crypto::PublicKey& publickey, const std::string& signature); void saveCache(); void loadCache();