Commit 35c220d1 authored by johan's avatar johan

Improve the peer device status management

- improve the set_peerDeviceStatus
- add a delete_peerDevice function
parent 867e55f4
......@@ -248,9 +248,25 @@ namespace lime {
* @param[in] status value of flag to set: accepted values are trusted, untrusted, unsafe
*
* throw an exception if given key doesn't match the one present in local storage
* throw an exception if the status flag value is unexpected (not one of trusted, untrusted, unsafe)
* if the status flag value is unexpected (not one of trusted, untrusted, unsafe), ignore the call
* if the status flag is unsafe or untrusted, ignore the value of Ik and call the version of this function without it
*
* if peer Device is not present in local storage and status is trusted or unsafe, it is added, if status is untrusted, it is just ignored
*
* General algorithm followed by the set_peerDeviceStatus functions
* - Status is valid? (not one of trusted, untrusted, unsafe)? No: return
* - status is trusted
* - We have Ik? -> No: return
* - Device is already in storage but Ik differs from the given one : exception
* - Insert/update in local storage
* - status is untrusted
* - Ik is ignored
* - Device already in storage? No: return
* - Device already in storage but current status is unsafe? Yes: return
* - update in local storage
* -status is unsafe
* - ignore Ik
* - insert/update the status. If inserted, insert an invalid Ik
*/
void set_peerDeviceStatus(const std::string &peerDeviceId, const std::vector<uint8_t> &Ik, lime::PeerDeviceStatus status);
......@@ -261,9 +277,11 @@ namespace lime {
* @param[in] peerDeviceId The device Id of peer, shall be its GRUU
* @param[in] status value of flag to set: accepted values are untrusted or unsafe
*
* throw an exception if the status flag value is unexpected (not one of untrusted, unsafe)
* if the status flag value is unexpected (not one of untrusted, unsafe), ignore the call
*
* if peer Device is not present in local storage, it is just ignored
* if peer Device is not present in local storage, it is inserted if status is unsafe and call is ignored if status is untrusted
* if the status is untrusted but the current status in local storage is unsafe, ignore the call
* Any call to the other form of the function with a status to unsafe or untrusted is rerouted to this function
*/
void set_peerDeviceStatus(const std::string &peerDeviceId, lime::PeerDeviceStatus status);
......@@ -276,6 +294,15 @@ namespace lime {
*/
lime::PeerDeviceStatus get_peerDeviceStatus(const std::string &peerDeviceId);
/**
* @delete a peerDevice from local storage
*
* @param[in] peerDeviceId The device Id to be removed from local storage, shall be its GRUU
*
* Call is silently ignored if the device is not found in local storage
*/
void delete_peerDevice(const std::string &peerDeviceId);
LimeManager() = delete; // no manager without Database and http provider
LimeManager(const LimeManager&) = delete; // no copy constructor
LimeManager operator=(const LimeManager &) = delete; // nor copy operator
......
......@@ -117,6 +117,11 @@ namespace lime {
postToX3DHServer(userData, X3DHmessage);
}
template <typename Curve>
void Lime<Curve>::delete_peerDevice(const std::string &peerDeviceId) {
m_DR_sessions_cache.erase(peerDeviceId); // remove session from cache if any
}
template <typename Curve>
void Lime<Curve>::update_SPk(const limeCallback &callback) {
// Do we need to update the SPk
......
......@@ -106,6 +106,7 @@ namespace lime {
void publish_user(const limeCallback &callback, const uint16_t OPkInitialBatchSize) override;
void delete_user(const limeCallback &callback) override;
void delete_peerDevice(const std::string &peerDeviceId) override;
/**
* @brief Check if the current SPk needs to be updated, if yes, generate a new one and publish it on server
......
......@@ -97,6 +97,13 @@ namespace lime {
*/
virtual void delete_user(const limeCallback &callback) = 0;
/**
* @brief Purge cached sessions for a given peer Device (used when a peer device is being deleted)
*
* @param[in] peerDeviceId The peer device to remove from cache
*/
virtual void delete_peerDevice(const std::string &peerDeviceId) = 0;
// User keys management
......
......@@ -163,6 +163,10 @@ Db::Db(std::string filename) : sql{sqlite3, filename}{
* The mapping is done in lime.hpp by the PeerDeviceStatus enum class definition
*
* Note: peer device information is shared by all local device, hence they are not linked to particular local devices from lime_LocalUsers table
*
* Note2: The Ik field should be able to be NULL but it is not for historical reason.
* When a peer device is inserted without Ik(through the set_peerDeviceStatus with a unsafe status is the only way to do that)
* it will be given an Ik set to invalid_Ik (one byte at 0x00) with the purpose of being unable to match a real Ik as NULL would have done
*/
sql<<"CREATE TABLE lime_PeerDevices( \
Did INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \
......@@ -289,16 +293,37 @@ void Db::get_allLocalDevices(std::vector<std::string> &deviceIds) {
* @param[in] status value of flag to set: accepted values are trusted, untrusted, unsafe
*
* throw an exception if given key doesn't match the one present in local storage
* throw an exception if the status flag value is unexpected (not one of trusted, untrusted, unsafe)
* if the status flag value is unexpected (not one of trusted, untrusted, unsafe), ignore the call
* if the status flag is unsafe or untrusted, ignore the value of Ik and call the version of this function without it
*
* if peer Device is not present in local storage and status is trusted or unsafe, it is added, if status is untrusted, it is just ignored
*
* General algorithm followed by the set_peerDeviceStatus functions
* - Status is valid? (not one of trusted, untrusted, unsafe)? No: return
* - status is trusted
* - We have Ik? -> No: return
* - Device is already in storage but Ik differs from the given one : exception
* - Insert/update in local storage
* - status is untrusted
* - Ik is ignored
* - Device already in storage? No: return
* - Device already in storage but current status is unsafe? Yes: return
* - update in local storage
* -status is unsafe
* - ignore Ik
* - insert/update the status. If inserted, insert an invalid Ik
*/
void Db::set_peerDeviceStatus(const std::string &peerDeviceId, const std::vector<uint8_t> &Ik, lime::PeerDeviceStatus status) {
// Check the status flag value, accepted values are: trusted, untrusted, unsafe
if (status != lime::PeerDeviceStatus::unsafe
&& status != lime::PeerDeviceStatus::untrusted
&& status != lime::PeerDeviceStatus::trusted) {
throw BCTBX_EXCEPTION << "Trying to set a status for peer device "<<peerDeviceId<<" which is not acceptable (differs from unsafe, untrusted or trusted)";
// if status is unsafe or untrusted, call the variant without Ik
if (status == lime::PeerDeviceStatus::unsafe || status == lime::PeerDeviceStatus::untrusted) {
this->set_peerDeviceStatus(peerDeviceId, status);
return;
}
// Check the status flag value, accepted values are: trusted (unsafe and untrusted are already managed)
if (status != lime::PeerDeviceStatus::trusted) {
LIME_LOGE<< "Trying to set a status for peer device "<<peerDeviceId<<" which is not acceptable (differs from unsafe, untrusted or trusted), ignore that";
return;
}
uint8_t statusInteger = static_cast<uint8_t>(status);
......@@ -334,24 +359,52 @@ void Db::set_peerDeviceStatus(const std::string &peerDeviceId, const std::vector
* @param[in] peerDeviceId The device Id of peer, shall be its GRUU
* @param[in] status value of flag to set: accepted values are untrusted or unsafe
*
* throw an exception if the status flag value is unexpected (not one of untrusted, unsafe)
* if the status flag value is unexpected (not one of untrusted, unsafe), ignore the call
*
* if peer Device is not present in local storage, it is just ignored
* if peer Device is not present in local storage, it is inserted if status is unsafe and call is ignored if status is untrusted
* if the status is untrusted but the current status in local storage is unsafe, ignore the call
* Any call to the other form of the function with a status to unsafe or untrusted is rerouted to this function
*/
void Db::set_peerDeviceStatus(const std::string &peerDeviceId, lime::PeerDeviceStatus status) {
// Check the status flag value, accepted values are: untrusted, unsafe
if (status != lime::PeerDeviceStatus::unsafe
&& status != lime::PeerDeviceStatus::untrusted) {
throw BCTBX_EXCEPTION << "Trying to set a status for peer device "<<peerDeviceId<<" without providing a Ik which is not acceptable (differs from unsafe or untrusted)";
LIME_LOGE << "Trying to set a status for peer device "<<peerDeviceId<<" without providing a Ik which is not acceptable (differs from unsafe or untrusted)";
return;
}
uint8_t statusInteger = static_cast<uint8_t>(status);
// Do we have this peerDevice in lime_PeerDevices
// is this peerDevice already in local storage?
bool inLocalStorage = false;
long long id;
sql<<"SELECT Did FROM Lime_PeerDevices WHERE DeviceId = :peerDeviceId;", into(id), use(peerDeviceId);
if (sql.got_data()) { // Found it
int currentStatus;
sql<<"SELECT Did, Status FROM Lime_PeerDevices WHERE DeviceId = :peerDeviceId;", into(id), into(currentStatus), use(peerDeviceId);
inLocalStorage = sql.got_data();
// if status is untrusted
if (status == lime::PeerDeviceStatus::untrusted) {
// and we do not already have that device in local storage -> log it and ignore the call
if (!inLocalStorage) {
LIME_LOGW << "Trying to set a status untrusted for peer device "<<peerDeviceId<<" not present in local storage, ignore that call)";
return;
}
// and the current status in local storage is unsafe, keep unsafe
if (currentStatus == static_cast<uint8_t>(lime::PeerDeviceStatus::unsafe)) {
LIME_LOGW << "Trying to set a status untrusted for peer device "<<peerDeviceId<<" but its current status is unsafe, ignore that call)";
return;
}
}
// update or insert
if (inLocalStorage) {
sql<<"UPDATE Lime_PeerDevices SET Status = :Status WHERE Did = :id;", use(statusInteger), use(id);
} else {
// this constant is set into lime_peerDevices table, Ik field when it is not provided by set_peerDeviceStatus as this field can't be set to NULL in older version of the database
constexpr uint8_t invalid_Ik = 0x00;
blob Ik_insert_blob(sql);
Ik_insert_blob.write(0, (char *)(&invalid_Ik), sizeof(invalid_Ik));
sql<<"INSERT INTO Lime_PeerDevices(DeviceId, Ik, Status) VALUES(:peerDeviceId, :Ik, :Status);", use(peerDeviceId), use(Ik_insert_blob), use(statusInteger);
}
}
......@@ -382,6 +435,17 @@ lime::PeerDeviceStatus Db::get_peerDeviceStatus(const std::string &peerDeviceId)
return lime::PeerDeviceStatus::unknown;
}
/**
* @delete a peerDevice from local storage
*
* @param[in] peerDeviceId The device Id to be removed from local storage, shall be its GRUU
*
* Call is silently ignored if the device is not found in local storage
*/
void Db::delete_peerDevice(const std::string &peerDeviceId) {
sql<<"DELETE FROM lime_peerDevices WHERE DeviceId = :peerDeviceId;", use(peerDeviceId);
}
/**
* @brief Check peer device information(DeviceId - GRUU -, public Ik, Uid to link it to a user) in local storage
*
......
......@@ -95,9 +95,25 @@ namespace lime {
* @param[in] status value of flag to set: accepted values are trusted, untrusted, unsafe
*
* throw an exception if given key doesn't match the one present in local storage
* throw an exception if the status flag value is unexpected (not one of trusted, untrusted, unsafe)
* if the status flag value is unexpected (not one of trusted, untrusted, unsafe), ignore the call
* if the status flag is unsafe or untrusted, ignore the value of Ik and call the version of this function without it
*
* if peer Device is not present in local storage and status is trusted or unsafe, it is added, if status is untrusted, it is just ignored
*
* General algorithm followed by the set_peerDeviceStatus functions
* - Status is valid? (not one of trusted, untrusted, unsafe)? No: return
* - status is trusted
* - We have Ik? -> No: return
* - Device is already in storage but Ik differs from the given one : exception
* - Insert/update in local storage
* - status is untrusted
* - Ik is ignored
* - Device already in storage? No: return
* - Device already in storage but current status is unsafe? Yes: return
* - update in local storage
* -status is unsafe
* - ignore Ik
* - insert/update the status. If inserted, insert an invalid Ik
*/
void set_peerDeviceStatus(const std::string &peerDeviceId, const std::vector<uint8_t> &Ik, lime::PeerDeviceStatus status);
......@@ -108,9 +124,11 @@ namespace lime {
* @param[in] peerDeviceId The device Id of peer, shall be its GRUU
* @param[in] status value of flag to set: accepted values are untrusted or unsafe
*
* throw an exception if the status flag value is unexpected (not one of untrusted, unsafe)
* if the status flag value is unexpected (not one of untrusted, unsafe), ignore the call
*
* if peer Device is not present in local storage, it is just ignored
* if peer Device is not present in local storage, it is inserted if status is unsafe and call is ignored if status is untrusted
* if the status is untrusted but the current status in local storage is unsafe, ignore the call
* Any call to the other form of the function with a status to unsafe or untrusted is rerouted to this function
*/
void set_peerDeviceStatus(const std::string &peerDeviceId, lime::PeerDeviceStatus status);
......@@ -124,6 +142,15 @@ namespace lime {
*/
lime::PeerDeviceStatus get_peerDeviceStatus(const std::string &peerDeviceId);
/**
* @delete a peerDevice from local storage
*
* @param[in] peerDeviceId The device Id to be removed from local storage, shall be its GRUU
*
* Call is silently ignored if the device is not found in local storage
*/
void delete_peerDevice(const std::string &peerDeviceId);
/**
* @brief check if the given peer Device information are in the local storage
* raise an exception if a different Ik is found for the given peer Device Id
......
......@@ -191,4 +191,17 @@ namespace lime {
return localStorage->get_peerDeviceStatus(peerDeviceId);
}
void LimeManager::delete_peerDevice(const std::string &peerDeviceId) {
// loop on all local users in cache to destroy any cached session linked to that user
for (auto userElem : m_users_cache) {
userElem.second->delete_peerDevice(peerDeviceId);
}
// open local DB
auto localStorage = std::unique_ptr<lime::Db>(new lime::Db(m_db_access));
localStorage->delete_peerDevice(peerDeviceId);
}
} // namespace lime
This diff is collapsed.
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