Commit 9817268c authored by Asad's avatar Asad Committed by Adrien Béraud

nameservice: daemon now POSTs publickey and signed name

When reigstering a name, the daemon now signs the requested name
and POSTs it along public-key
Also added error handling for response from server with appropriate codes

Also added ability to register name from restdring (setNameRegistration)

Change-Id: Id973cb9a2fa4d4410e0266287192ce452d08249b
parent d4c9b3e3
......@@ -101,6 +101,11 @@ RestConfigurationManager::populateResources()
resources_.back()->set_method_handler("POST",
std::bind(&RestConfigurationManager::setAccountDetails, this, std::placeholders::_1));
resources_.push_back(std::make_shared<restbed::Resource>());
resources_.back()->set_path("/registerName/{accountID: [a-z0-9]*}");
resources_.back()->set_method_handler("POST",
std::bind(&RestConfigurationManager::registerName, this, std::placeholders::_1));
resources_.push_back(std::make_shared<restbed::Resource>());
resources_.back()->set_path("/setAccountActive/{accountID: [a-z0-9]*}/{status: (true|false)}");
resources_.back()->set_method_handler("GET",
......@@ -401,10 +406,11 @@ RestConfigurationManager::defaultRoute(const std::shared_ptr<restbed::Session> s
body += "GET /accountDetails/{accountID: [a-z0-9]*}\r\n";
body += "GET /volatileAccountDetails/{accountID: [a-z0-9]*}\r\n";
body += "POST /setAccountDetails/{accountID: [a-z0-9]*}\r\n";
body += "POST /registerName/{accountID: [a-z0-9]*}\r\n";
body += "GET /setAccountActive/{accountID: [a-z0-9]*}/{status: (true|false)}\r\n";
body += "GET /accountTemplate/{type: [a-zA-Z]*}\r\n";
body += "POST /addAccount\r\n";
body += "GET /removeAccount/{accountID: [a-z0-9]*}\r\n";
body += "GET /removeAccount/{accountID: 3a-z0-9]*}\r\n";
body += "GET /accountList\r\n";
body += "GET /sendRegister/{accountID: [a-z0-9]*}/{status: (true|false)}\r\n";
body += "GET /registerAllAccounts\r\n";
......@@ -557,6 +563,43 @@ RestConfigurationManager::setAccountDetails(const std::shared_ptr<restbed::Sessi
});
}
void
RestConfigurationManager::registerName(const std::shared_ptr<restbed::Session> session)
{
const auto request = session->get_request();
const std::string accountID = request->get_path_parameter("accountID");
size_t content_length = request->get_header("Content-Length", 0);
RING_INFO("[%s] POST /registerName/%s", session->get_origin().c_str(), accountID.c_str());
if(content_length > 0){
session->fetch(content_length, [this, request, accountID](const std::shared_ptr<restbed::Session> session, const restbed::Bytes & body)
{
std::string data(std::begin(body), std::end(body));
std::map<std::string, std::string> details = parsePost(data);
RING_DBG("Details received");
for(auto& it : details)
RING_DBG("%s : %s", it.first.c_str(), it.second.c_str());
if (details.find("password") == details.end() ){
session->close(400, "password parameter required");
return;
}
if (details.find("name") == details.end() ){
session->close(400, "name parameter required");
return;
}
auto response = DRing::registerName(accountID, details["password"], details["name"]);
session->close(restbed::OK, (response ? "TRUE" : "FALSE"));
});
}
else {
session->close(400, "empty request");
}
}
void
RestConfigurationManager::setAccountActive(const std::shared_ptr<restbed::Session> session)
{
......
......@@ -66,6 +66,7 @@ class RestConfigurationManager
void getAccountDetails(const std::shared_ptr<restbed::Session> session);
void getVolatileAccountDetails(const std::shared_ptr<restbed::Session> session);
void setAccountDetails(const std::shared_ptr<restbed::Session> session);
void registerName(const std::shared_ptr<restbed::Session> session);
void setAccountActive(const std::shared_ptr<restbed::Session> session);
void getAccountTemplate(const std::shared_ptr<restbed::Session> session);
void addAccount(const std::shared_ptr<restbed::Session> session);
......
......@@ -15,13 +15,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "namedirectory.h"
#include "logger.h"
#include "string_utils.h"
#include "thread_pool.h"
#include "fileutils.h"
#include "config.h"
#include "base64.h"
#include <msgpack.hpp>
#include <json/json.h>
......@@ -249,8 +250,8 @@ bool NameDirectory::validateName(const std::string& name) const
{
return std::regex_match(name, NAME_VALIDATOR);
}
void NameDirectory::registerName(const std::string& addr, const std::string& n, const std::string& owner, RegistrationCallback cb)
using Blob = std::vector<uint8_t>;
void NameDirectory::registerName(const std::string& addr, const std::string& n, const std::string& owner, RegistrationCallback cb, const std::string& signedname, const std::string& publickey)
{
try {
std::string name {n};
......@@ -259,7 +260,6 @@ void NameDirectory::registerName(const std::string& addr, const std::string& n,
return;
}
toLower(name);
auto cacheResult = addrCache(name);
if (not cacheResult.empty()) {
if (cacheResult == addr)
......@@ -277,7 +277,9 @@ void NameDirectory::registerName(const std::string& addr, const std::string& n,
std::string body;
{
std::stringstream ss;
ss << "{\"addr\":\"" << addr << "\",\"owner\":\"" << owner << "\"}";
ss << "{\"addr\":\"" << addr << "\",\"owner\":\"" << owner <<
"\",\"signature\":\"" << signedname << "\",\"publickey\":\"" << base64::encode(ring::Blob(publickey.begin(), publickey.end())) << "\"}";
body = ss.str();
}
request->set_body(body);
......@@ -288,9 +290,9 @@ void NameDirectory::registerName(const std::string& addr, const std::string& n,
RING_WARN("registerName: sending request %s %s", addr.c_str(), name.c_str());
auto ret = restbed::Http::async(request,
[this,cb,addr,name](const std::shared_ptr<restbed::Request>&,
const std::shared_ptr<restbed::Response>& reply)
{
[this,cb,addr,name](const std::shared_ptr<restbed::Request>&,
const std::shared_ptr<restbed::Response>& reply)
{
auto code = reply->get_status_code();
RING_DBG("Got reply for registration of %s -> %s: code %d", name.c_str(), addr.c_str(), code);
if (code >= 200 && code < 300) {
......@@ -318,14 +320,28 @@ void NameDirectory::registerName(const std::string& addr, const std::string& n,
nameCache_.emplace(addr, name);
}
cb(success ? RegistrationResponse::success : RegistrationResponse::error);
} else if (code >= 400 && code < 500) {
} else if(code == 400){
cb(RegistrationResponse::incompleteRequest);
RING_ERR("RegistrationResponse::incompleteRequest");
} else if(code == 401){
cb(RegistrationResponse::signatureVerificationFailed);
RING_ERR("RegistrationResponse::signatureVerificationFailed");
} else if (code == 403) {
cb(RegistrationResponse::alreadyTaken);
RING_ERR("RegistrationResponse::alreadyTaken");
} else if (code == 409) {
cb(RegistrationResponse::alreadyTaken);
RING_ERR("RegistrationResponse::alreadyTaken");
} else if (code > 400 && code < 500) {
cb(RegistrationResponse::alreadyTaken);
RING_ERR("RegistrationResponse::alreadyTaken");
} else {
cb(RegistrationResponse::error);
RING_ERR("RegistrationResponse::error");
}
}, params).share();
// avoid blocking on future destruction
// avoid blocking on future destruction
ThreadPool::instance().run([ret](){ ret.get(); });
} catch (const std::exception& e) {
RING_ERR("Error when performing name registration: %s", e.what());
......
......@@ -30,7 +30,13 @@ class NameDirectory
{
public:
enum class Response : int { found = 0, invalidName, notFound, error };
enum class RegistrationResponse : int { success = 0, invalidName, alreadyTaken, error };
enum class RegistrationResponse : int { success = 0,
invalidName,
alreadyTaken,
error,
incompleteRequest,
signatureVerificationFailed
};
using LookupCallback = std::function<void(const std::string& result, Response response)>;
using RegistrationCallback = std::function<void(RegistrationResponse response)>;
......@@ -47,7 +53,7 @@ public:
void lookupAddress(const std::string& addr, LookupCallback cb);
void lookupName(const std::string& name, LookupCallback cb);
void registerName(const std::string& addr, const std::string& name, const std::string& owner, RegistrationCallback cb);
void registerName(const std::string& addr, const std::string& name, const std::string& owner, RegistrationCallback cb, const std::string& signedname, const std::string& publickey);
const std::string& getServer() const {
return serverHost_;
......@@ -82,5 +88,4 @@ private:
void saveCache();
void loadCache();
};
}
}
\ No newline at end of file
......@@ -32,7 +32,6 @@
#include "accountarchive.h"
#include "ringcontact.h"
#include "configkeys.h"
#include "thread_pool.h"
#include "sip/sdp.h"
......@@ -1642,11 +1641,16 @@ RingAccount::lookupAddress(const std::string& addr)
emitSignal<DRing::ConfigurationSignal::RegisteredNameFound>(acc, (int)response, addr, result);
});
}
using Blob = std::vector<uint8_t>;
void
RingAccount::registerName(const std::string& /*password*/, const std::string& name)
RingAccount::registerName(const std::string& password, const std::string& name)
{
auto privateKey = readArchive(password).id.first;
std::string signedName = base64::encode(privateKey->sign(Blob(name.begin(), name.end())));
auto publickey = privateKey->getPublicKey().toString();
auto acc = getAccountID();
nameDir_.get().registerName(ringAccountId_, name, ethAccount_, [acc,name,w=weak()](NameDirectory::RegistrationResponse response){
int res = (response == NameDirectory::RegistrationResponse::success) ? 0 : (
(response == NameDirectory::RegistrationResponse::invalidName) ? 2 : (
......@@ -1656,7 +1660,7 @@ RingAccount::registerName(const std::string& /*password*/, const std::string& na
this_->registeredName_ = name;
}
emitSignal<DRing::ConfigurationSignal::NameRegistrationEnded>(acc, res, name);
});
}, signedName, publickey);
}
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment