diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp index cf16cb28076a2284ac777a5bcfbbc4192f7666bc..6d4acf3e66908703a0220bd7f7a228351621107d 100644 --- a/src/ringdht/ringaccount.cpp +++ b/src/ringdht/ringaccount.cpp @@ -214,7 +214,7 @@ RingAccount::newOutgoingCall(const std::string& toUrl) call->setIPToIP(true); call->setSecure(isTlsEnabled()); - auto shared_this = std::static_pointer_cast<RingAccount>(shared_from_this()); + auto sthis = std::static_pointer_cast<RingAccount>(shared_from_this()); // TODO: for now, we automatically trust all explicitly called peers setCertificateStatus(toUri, tls::TrustStore::PermissionStatus::ALLOWED); @@ -222,30 +222,30 @@ RingAccount::newOutgoingCall(const std::string& toUrl) const auto toH = dht::InfoHash(toUri); call->setState(Call::ConnectionState::TRYING); - std::weak_ptr<SIPCall> weak_call = call; + std::weak_ptr<SIPCall> wCall = call; - auto treatedDevices_ = std::make_shared<std::set<dht::InfoHash>>(); + auto treatedDevices = std::make_shared<std::set<dht::InfoHash>>(); // Find listening Ring devices for this account - shared_this->dht_.get<DeviceAnnouncement>(toH, [=](DeviceAnnouncement&& dev) { + dht_.get<DeviceAnnouncement>(toH, [sthis,treatedDevices,wCall,toH, toUri](DeviceAnnouncement&& dev) { if (dev.from != toH) return true; - if (not treatedDevices_->emplace(dev.dev).second) + if (not treatedDevices->emplace(dev.dev).second) return true; RING_WARN("Found device to place call %s", dev.dev.toString().c_str()); runOnMainThread([=](){ - if (auto call = weak_call.lock()) { + if (auto call = wCall.lock()) { RING_WARN("[call %s] Found device %s", call->getCallId().c_str(), dev.dev.toString().c_str()); auto& manager = Manager::instance(); - auto dev_call = manager.callFactory.newCall<SIPCall, RingAccount>(*this, manager.getNewCallID(), + auto dev_call = manager.callFactory.newCall<SIPCall, RingAccount>(*sthis, manager.getNewCallID(), Call::CallType::OUTGOING); std::weak_ptr<SIPCall> weak_dev_call = dev_call; dev_call->setIPToIP(true); - dev_call->setSecure(isTlsEnabled()); - auto ice = createIceTransport(("sip:" + dev_call->getCallId()).c_str(), - ICE_COMPONENTS, true, getIceOptions()); + dev_call->setSecure(sthis->isTlsEnabled()); + auto ice = sthis->createIceTransport(("sip:" + dev_call->getCallId()).c_str(), + ICE_COMPONENTS, true, sthis->getIceOptions()); if (not ice) { RING_WARN("Can't create ICE"); dev_call->removeCall(); @@ -256,7 +256,7 @@ RingAccount::newOutgoingCall(const std::string& toUrl) auto iceInitTimeout = std::chrono::steady_clock::now() + std::chrono::seconds {ICE_INIT_TIMEOUT}; - manager.addTask([shared_this, weak_dev_call, ice, iceInitTimeout, toUri, dev] { + manager.addTask([sthis, weak_dev_call, ice, iceInitTimeout, toUri, dev] { auto call = weak_dev_call.lock(); if (not call) @@ -274,14 +274,14 @@ RingAccount::newOutgoingCall(const std::string& toUrl) RING_WARN("ICE initialised"); // Next step: sent the ICE data to peer through DHT - const dht::Value::Id callvid = udist(shared_this->rand_); - const dht::Value::Id vid = udist(shared_this->rand_); + const dht::Value::Id callvid = udist(sthis->rand_); + const dht::Value::Id vid = udist(sthis->rand_); const auto callkey = dht::InfoHash::get("callto:" + dev.dev.toString()); dht::Value val { dht::IceCandidates(callvid, ice->getLocalAttributesAndCandidates()) }; val.id = vid; //RING_WARN("ICE initialised"); - shared_this->dht_.putEncrypted( + sthis->dht_.putEncrypted( callkey, dev.dev, std::move(val), [=](bool ok) { // Put complete callback @@ -294,7 +294,7 @@ RingAccount::newOutgoingCall(const std::string& toUrl) } ); - auto listenKey = shared_this->dht_.listen<dht::IceCandidates>( + auto listenKey = sthis->dht_.listen<dht::IceCandidates>( callkey, [=] (dht::IceCandidates&& msg) { if (msg.id != callvid or msg.from != dev.dev) @@ -311,7 +311,7 @@ RingAccount::newOutgoingCall(const std::string& toUrl) } ); - shared_this->pendingCalls_.emplace_back(PendingCall{ + sthis->pendingCalls_.emplace_back(PendingCall{ std::chrono::steady_clock::now(), ice, weak_dev_call, std::move(listenKey), @@ -323,9 +323,9 @@ RingAccount::newOutgoingCall(const std::string& toUrl) }); return true; }, [=](bool ok){ - RING_WARN("newOutgoingCall: found %lu devices", treatedDevices_->size()); - if (treatedDevices_->empty()) { - if (auto call = weak_call.lock()) { + RING_WARN("newOutgoingCall: found %lu devices", treatedDevices->size()); + if (treatedDevices->empty()) { + if (auto call = wCall.lock()) { call->onFailure(); } } @@ -1633,15 +1633,47 @@ RingAccount::doRegister_() return true; this_.saveTreatedMessages(); - auto from = v.from.toString(); - auto now = system_clock::to_time_t(system_clock::now()); - std::map<std::string, std::string> payloads = {{"text/plain", - utf8_make_valid(v.msg)}}; - shared->onTextMessage(from, payloads); - RING_DBG("Sending message confirmation %" PRIu64, v.id); - this_.dht_.putEncrypted(inboxDeviceKey, - v.from, - dht::ImMessage(v.id, std::string(), now)); + // quick check in case we already explicilty banned this public key + auto trustStatus = this_.trust_.getCertificateStatus(v.from.toString()); + if (trustStatus == tls::TrustStore::PermissionStatus::BANNED) { + RING_WARN("Discarding incoming DHT message from banned peer %s", v.from.toString().c_str()); + return true; + } + + RING_WARN("findCertificate %s", v.from.toString().c_str()); + this_.findCertificate( v.from, + [shared, v, trustStatus, inboxDeviceKey](const std::shared_ptr<dht::crypto::Certificate> cert) mutable { + RING_WARN("findCertificate: found %p", cert.get()); + auto& this_ = *shared; + if (not this_.dhtPublicInCalls_ and trustStatus != tls::TrustStore::PermissionStatus::ALLOWED) { + if (!cert or cert->getId() != v.from) { + RING_WARN("Can't find certificate of %s for incoming message.", v.from.toString().c_str()); + return; + } + + tls::CertificateStore::instance().pinCertificate(cert); + + auto& this_ = *shared; + if (!this_.trust_.isAllowed(*cert)) { + RING_WARN("Discarding incoming DHT message from untrusted peer %s.", v.from.toString().c_str()); + return; + } + } else if (not this_.dhtPublicInCalls_ or trustStatus == tls::TrustStore::PermissionStatus::BANNED) { + RING_WARN("Discarding incoming DHT message from untrusted or banned peer %s.", v.from.toString().c_str()); + return; + } + + auto from_acc_id = cert ? (cert->issuer ? cert->issuer->getId().toString() : cert->getId().toString()) : v.from.toString(); + + auto now = system_clock::to_time_t(system_clock::now()); + std::map<std::string, std::string> payloads = {{"text/plain", + utf8_make_valid(v.msg)}}; + shared->onTextMessage(from_acc_id, payloads); + RING_DBG("Sending message confirmation %" PRIu64, v.id); + this_.dht_.putEncrypted(inboxDeviceKey, + v.from, + dht::ImMessage(v.id, std::string(), now)); + }); return true; } ); @@ -2132,11 +2164,11 @@ RingAccount::sendTextMessage(const std::string& to, const std::map<std::string, return; } - std::weak_ptr<RingAccount> wshared = std::static_pointer_cast<RingAccount>(shared_from_this()); + auto shared = std::static_pointer_cast<RingAccount>(shared_from_this()); auto toUri = parseRingUri(to); auto toH = dht::InfoHash(toUri); auto now = system_clock::to_time_t(system_clock::now()); - auto treatedDevices_ = std::make_shared<std::set<dht::InfoHash>>(); + auto treatedDevices = std::make_shared<std::set<dht::InfoHash>>(); struct PendingConfirmation { bool replied {false}; @@ -2145,19 +2177,20 @@ RingAccount::sendTextMessage(const std::string& to, const std::map<std::string, auto confirm = std::make_shared<PendingConfirmation>(); // Find listening Ring devices for this account - dht_.get<DeviceAnnouncement>(toH, [=](DeviceAnnouncement&& dev) { + dht_.get<DeviceAnnouncement>(toH, [confirm,shared,treatedDevices,toH,token,payloads,now](DeviceAnnouncement&& dev) { if (dev.from != toH) return true; - if (not treatedDevices_->emplace(dev.dev).second) + if (not treatedDevices->emplace(dev.dev).second) return true; - auto e = sentMessages_.emplace(token, PendingMessage {}); + auto e = shared->sentMessages_.emplace(token, PendingMessage {}); e.first->second.to = dev.dev; auto h = dht::InfoHash::get("inbox:"+dev.dev.toString()); RING_DBG("Found device to send message %s -> %s", dev.dev.toString().c_str(), h.toString().c_str()); - auto list_token = dht_.listen<dht::ImMessage>(h, [h,wshared,token,confirm](dht::ImMessage&& msg) { + std::weak_ptr<RingAccount> wshared = shared; + auto list_token = shared->dht_.listen<dht::ImMessage>(h, [h,wshared,token,confirm](dht::ImMessage&& msg) { if (auto this_ = wshared.lock()) { // check expected message confirmation if (msg.id != token) @@ -2194,9 +2227,11 @@ RingAccount::sendTextMessage(const std::string& to, const std::map<std::string, } return false; }); + RING_DBG("Adding listen token at %s", h.toString().c_str()); confirm->listenTokens.emplace(h, std::move(list_token)); + RING_DBG("Added listen token at %s", h.toString().c_str()); - dht_.putEncrypted(h, + shared->dht_.putEncrypted(h, dev.dev, dht::ImMessage(token, std::string(payloads.begin()->second), now), [wshared,token,confirm,h](bool ok) { @@ -2208,6 +2243,10 @@ RingAccount::sendTextMessage(const std::string& to, const std::map<std::string, } } }); + RING_DBG("Put encrypted message at %s for %s", h.toString().c_str(), dev.dev.toString().c_str()); + return true; + }, [=](bool ok){ + RING_WARN("sendTextMessage: found %lu devices", treatedDevices->size()); }); }