diff --git a/include/opendht/sockaddr.h b/include/opendht/sockaddr.h index 995579e46..3c09606c6 100644 --- a/include/opendht/sockaddr.h +++ b/include/opendht/sockaddr.h @@ -67,7 +67,7 @@ class OPENDHT_PUBLIC SockAddr { */ SockAddr(const sockaddr* sa, socklen_t length) { if (length > sizeof(sockaddr_storage)) - throw std::runtime_error("Socket address length is too large"); + throw std::invalid_argument("Socket address length is too large"); set(sa, length); } SockAddr(const sockaddr* sa) { @@ -78,7 +78,7 @@ class OPENDHT_PUBLIC SockAddr { else if(sa->sa_family == AF_INET6) len = sizeof(sockaddr_in6); else - throw std::runtime_error("Unknown address family"); + throw std::invalid_argument("Unknown address family"); } set(sa, len); } diff --git a/include/opendht/value.h b/include/opendht/value.h index a4a3348a1..ba7a893cc 100644 --- a/include/opendht/value.h +++ b/include/opendht/value.h @@ -591,8 +591,10 @@ struct OPENDHT_PUBLIC Value */ Blob cypher {}; + bool checkSignature(); + Sp decrypt(const crypto::PrivateKey& key); + private: - friend class SecureDht; /* Cache for crypto ops */ bool signatureChecked {false}; bool signatureValid {false}; diff --git a/src/securedht.cpp b/src/securedht.cpp index 472eead7a..c085de6ae 100644 --- a/src/securedht.cpp +++ b/src/securedht.cpp @@ -68,33 +68,19 @@ ValueType SecureDht::secureType(ValueType&& type) { type.storePolicy = [this,type](InfoHash id, Sp& v, const InfoHash& nid, const SockAddr& a) { - if (v->isSigned()) { - if (!v->signatureChecked) { - v->signatureChecked = true; - v->signatureValid = v->owner and v->owner->checkSignature(v->getToSign(), v->signature); - } - if (!v->signatureValid) { - DHT_LOG.WARN("Signature verification failed"); - return false; - } - } + if (v->isSigned()) + return v->checkSignature(); return type.storePolicy(id, v, nid, a); }; type.editPolicy = [this,type](InfoHash id, const Sp& o, Sp& n, const InfoHash& nid, const SockAddr& a) { - if (!o->isSigned()) + if (not o->isSigned()) return type.editPolicy(id, o, n, nid, a); - if (o->owner != n->owner) { + if (o->owner != n->owner or not n->isSigned()) { DHT_LOG.WARN("Edition forbidden: owner changed."); return false; } - if (!n->signatureChecked) { - n->signatureChecked = true; - n->signatureValid = o->owner and o->owner->checkSignature(n->getToSign(), n->signature); - } - if (!n->signatureValid) { - DHT_LOG.WARN("Edition forbidden: signature verification failed."); + if (not n->checkSignature()) return false; - } if (o->seq == n->seq) { // If the data is exactly the same, // it can be reannounced, possibly by someone else. @@ -241,35 +227,23 @@ SecureDht::checkValue(const Sp& v) #endif return {}; } - if (v->decrypted) { - return v->decryptedValue; - } - v->decrypted = true; try { - Value decrypted_val (decrypt(*v)); - if (decrypted_val.recipient == getId()) { - if (decrypted_val.owner) - nodesPubKeys_[decrypted_val.owner->getId()] = decrypted_val.owner; - v->decryptedValue = std::make_shared(std::move(decrypted_val)); - return v->decryptedValue; + if (auto decrypted_val = v->decrypt(*key_)) { + if (decrypted_val->owner) + nodesPubKeys_[decrypted_val->owner->getId()] = decrypted_val->owner; + return decrypted_val; } - // Ignore values belonging to other people } catch (const std::exception& e) { DHT_LOG.WARN("Could not decrypt value %s : %s", v->toString().c_str(), e.what()); } } // Check signed values else if (v->isSigned()) { - if (v->signatureChecked) { - return v->signatureValid ? v : Sp{}; - } - v->signatureChecked = true; - if (v->owner and v->owner->checkSignature(v->getToSign(), v->signature)) { - v->signatureValid = true; - nodesPubKeys_[v->owner->getId()] = v->owner; + if (v->checkSignature()) { + if (v->owner) + nodesPubKeys_[v->owner->getId()] = v->owner; return v; - } - else + } else DHT_LOG.WARN("Signature verification failed for %s", v->toString().c_str()); } // Forward normal values diff --git a/src/value.cpp b/src/value.cpp index ed17f0902..ec59a40c2 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -233,6 +233,41 @@ Value::toJson() const return val; } +bool +Value::checkSignature() +{ + if (!signatureChecked) { + signatureChecked = true; + if (isSigned()) { + signatureValid = owner and owner->checkSignature(getToSign(), signature); + } else { + signatureValid = true; + } + } + return signatureValid; +} + +Sp +Value::decrypt(const crypto::PrivateKey& key) +{ + if (not decrypted) { + decrypted = true; + if (isEncrypted()) { + auto decryptedBlob = key.decrypt(cypher); + std::unique_ptr v {new Value(id)}; + auto msg = msgpack::unpack((const char*)decryptedBlob.data(), decryptedBlob.size()); + v->msgpack_unpack_body(msg.get()); + if (v->recipient != key.getPublicKey().getId()) + throw crypto::DecryptError("Recipient mismatch"); + // Ignore values belonging to other people + if (not v->owner or not v->owner->checkSignature(v->getToSign(), v->signature)) + throw crypto::DecryptError("Signature mismatch"); + decryptedValue = std::move(v); + } + } + return decryptedValue; +} + uint64_t unpackId(const Json::Value& json, const std::string& key) { uint64_t ret = 0;