diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/attach.cpp | 12 | ||||
-rw-r--r-- | src/identity.cpp | 101 | ||||
-rw-r--r-- | src/identity.h | 15 | ||||
-rw-r--r-- | src/main.cpp | 7 | ||||
-rw-r--r-- | src/message.cpp | 4 | ||||
-rw-r--r-- | src/network.cpp | 2 | ||||
-rw-r--r-- | src/network/protocol.cpp | 2 | ||||
-rw-r--r-- | src/state.cpp | 2 |
8 files changed, 116 insertions, 29 deletions
diff --git a/src/attach.cpp b/src/attach.cpp index 3d351f8..887de38 100644 --- a/src/attach.cpp +++ b/src/attach.cpp @@ -75,11 +75,19 @@ void AttachService::handlePairingResult(Context & ctx, Stored<AttachIdentity> at if (!key) throw runtime_error("failed to load secret key"); - auto id = Identity::load(key->signAdd(att->identity).ref()); + vector<StoredIdentityPart> parts = ctx.local()->identity()->extData(); + parts.emplace_back(key->signAdd(att->identity)); + filterAncestors(parts); + + auto id = Identity::load(parts); if (!id) printf("New identity validation failed\n"); - auto rid = ctx.local().ref().storage().copy(*id->ref()); + optional<Ref> tmpref = id->extRef(); + if (not tmpref) + tmpref = id->modify().commit().extRef(); + + auto rid = ctx.local().ref().storage().copy(*tmpref); id = Identity::load(rid); auto owner = id->owner(); diff --git a/src/identity.cpp b/src/identity.cpp index ae20b3b..8b6ee2a 100644 --- a/src/identity.cpp +++ b/src/identity.cpp @@ -9,7 +9,7 @@ using namespace erebos; using std::async; -using std::get_if; +using std::holds_alternative; using std::nullopt; using std::runtime_error; using std::set; @@ -89,6 +89,7 @@ vector<Stored<Signed<IdentityData>>> Identity::data() const for (const auto & d : p->data) base.push_back(d.base()); + filterAncestors(base); return base; } @@ -149,8 +150,26 @@ optional<Ref> Identity::ref() const return nullopt; } +optional<Ref> Identity::extRef() const +{ + if (p->data.size() == 1) + return p->data[0].ref(); + return nullopt; +} + vector<Ref> Identity::refs() const { + auto base = data(); + vector<Ref> res; + res.reserve(base.size()); + + for (const auto & d : base) + res.push_back(d.ref()); + return res; +} + +vector<Ref> Identity::extRefs() const +{ vector<Ref> res; res.reserve(p->data.size()); for (const auto & idata : p->data) @@ -178,9 +197,22 @@ Identity::Builder Identity::create(const Storage & st) Identity::Builder Identity::modify() const { + vector<Stored<Signed<IdentityData>>> prevBase; + vector<StoredIdentityPart> prevExt; + + prevBase.reserve(p->data.size()); + for (const auto & d : p->data) { + prevBase.push_back(d.base()); + if (holds_alternative<Stored<Signed<IdentityExtension>>>(d.part)) + prevExt.push_back(d); + } + + filterAncestors(prevBase); + return Builder (new Builder::Priv { .storage = p->data[0].ref().storage(), - .prev = data(), + .prevBase = move(prevBase), + .prevExt = move(prevExt), .keyIdentity = p->data[0].base()->data->keyIdentity, .keyMessage = p->data[0].base()->data->keyMessage, }); @@ -247,11 +279,18 @@ Identity::Builder::Builder(Priv * p): p(p) {} Identity Identity::Builder::commit() const { - auto idata = p->storage.store(IdentityData { - .prev = p->prev, - .name = p->name, - .owner = p->owner && p->owner->p->data.size() == 1 ? - optional(p->owner->p->data[0].base()) : nullopt, + optional<Stored<Signed<IdentityData>>> ownerBaseData; + optional<StoredIdentityPart> ownerExtData; + if (p->owner && p->owner->p->data.size() == 1) { + ownerExtData = p->owner->p->data[0]; + ownerBaseData = ownerExtData->base(); + if (holds_alternative<Stored<Signed<IdentityData>>>(ownerExtData->part)) + ownerExtData.reset(); + } + + auto base = p->storage.store(IdentityData { + .prev = p->prevBase, + .owner = ownerBaseData, .keyIdentity = p->keyIdentity, .keyMessage = p->keyMessage, }); @@ -260,15 +299,38 @@ Identity Identity::Builder::commit() const if (!key) throw runtime_error("failed to load secret key"); - auto sdata = key->sign(idata); - if (idata->owner) { - if (auto okey = SecretKey::load((*idata->owner)->data->keyIdentity)) - sdata = okey->signAdd(sdata); + auto sbase = key->sign(base); + if (base->owner) { + if (auto okey = SecretKey::load((*base->owner)->data->keyIdentity)) + sbase = okey->signAdd(sbase); else throw runtime_error("failed to load secret key"); } - auto p = Identity::Priv::validate({ StoredIdentityPart(sdata) }); + optional<StoredIdentityPart> spart; + + if (not p->prevExt.empty() || p->name || ownerExtData) { + auto ext = p->storage.store(IdentityExtension { + .base = sbase, + .prev = p->prevExt, + .name = p->name, + .owner = ownerExtData, + }); + + auto sext = key->sign(ext); + if (ext->owner) { + if (auto okey = SecretKey::load(p->owner->keyIdentity())) + sext = okey->signAdd(sext); + else + throw runtime_error("failed to load secret key"); + } + + spart.emplace(sext); + } else { + spart.emplace(sbase); + } + + auto p = Identity::Priv::validate({ *spart }); if (!p) throw runtime_error("failed to validate committed identity"); @@ -350,6 +412,21 @@ IdentityExtension IdentityExtension::load(const Ref & ref) }; } +Ref IdentityExtension::store(const Storage & st) const +{ + vector<Record::Item> items; + + items.emplace_back("SBASE", base); + for (const auto & p : prev) + items.emplace_back("SPREV", p.ref()); + if (name) + items.emplace_back("name", *name); + if (owner) + items.emplace_back("owner", owner->ref()); + + return st.storeObject(Record(std::move(items))); +} + StoredIdentityPart StoredIdentityPart::load(const Ref & ref) { if (auto srec = ref->asRecord()) { diff --git a/src/identity.h b/src/identity.h index 1653f51..bfa5932 100644 --- a/src/identity.h +++ b/src/identity.h @@ -20,9 +20,9 @@ struct IdentityData static IdentityData load(const Ref &); Ref store(const Storage & st) const; - const vector<Stored<Signed<IdentityData>>> prev; - const optional<string> name; - const optional<Stored<Signed<IdentityData>>> owner; + const vector<Stored<Signed<IdentityData>>> prev {}; + const optional<string> name {}; + const optional<Stored<Signed<IdentityData>>> owner {}; const Stored<PublicKey> keyIdentity; const optional<Stored<PublicKey>> keyMessage; }; @@ -33,9 +33,9 @@ struct IdentityExtension Ref store(const Storage & st) const; const Stored<Signed<IdentityData>> base; - const vector<StoredIdentityPart> prev; - const optional<string> name; - const optional<StoredIdentityPart> owner; + const vector<StoredIdentityPart> prev {}; + const optional<string> name {}; + const optional<StoredIdentityPart> owner {}; }; struct Identity::Priv @@ -56,7 +56,8 @@ struct Identity::Priv struct Identity::Builder::Priv { Storage storage; - vector<Stored<Signed<IdentityData>>> prev = {}; + vector<Stored<Signed<IdentityData>>> prevBase = {}; + vector<StoredIdentityPart> prevExt = {}; optional<string> name = nullopt; optional<Identity> owner = nullopt; Stored<PublicKey> keyIdentity; diff --git a/src/main.cpp b/src/main.cpp index 0eb379b..3100695 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -289,14 +289,15 @@ void startServer(const vector<string> &) config.service<DirectMessageService>() .onUpdate([](const DirectMessageThread & thread, ssize_t, ssize_t) { - if (thread.at(0).from()->sameAs(server->identity())) + if (thread.at(0).from()->sameAs(server->identity().finalOwner())) return; ostringstream ss; string name = "<unnamed>"; - if (auto opt = thread.peer().name()) - name = *opt; + if (auto from = thread.at(0).from()) + if (auto fname = from->name()) + name = *fname; ss << "dm-received" << " from " << name diff --git a/src/message.cpp b/src/message.cpp index 8ae1601..a9d6139 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -69,7 +69,7 @@ Ref DirectMessageData::store(const Storage & st) const for (const auto & prev : prev) items.emplace_back("PREV", prev.ref()); if (from) - items.emplace_back("from", from->ref().value()); + items.emplace_back("from", from->extRef().value()); if (time) items.emplace_back("time", *time); if (text) @@ -373,7 +373,7 @@ DirectMessage DirectMessageService::send(const Identity & to, const string & tex auto threads = loc->shared<DirectMessageThreads>(); msg = st.store(DirectMessageData { .prev = threads.thread(to).p->head, - .from = server.identity().finalOwner(), + .from = loc->identity()->finalOwner(), .time = ZonedTime::now(), .text = text, }); diff --git a/src/network.cpp b/src/network.cpp index c1c9c0f..7f37cf7 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -736,7 +736,7 @@ void Server::Peer::finalizeChannel(ReplyBuilder & reply, unique_ptr<Channel> ch) connection.channel().emplace<unique_ptr<Channel>>(move(ch)); vector<NetworkProtocol::Header::Item> hitems; - for (const auto & r : server.self.refs()) + for (const auto & r : server.self.extRefs()) reply.header(NetworkProtocol::Header::AnnounceUpdate { r.digest() }); for (const auto & r : server.self.updates()) reply.header(NetworkProtocol::Header::AnnounceUpdate { r.digest() }); diff --git a/src/network/protocol.cpp b/src/network/protocol.cpp index 02c3dae..b781693 100644 --- a/src/network/protocol.cpp +++ b/src/network/protocol.cpp @@ -150,7 +150,7 @@ void NetworkProtocol::updateIdentity(Identity id) self = move(id); vector<Header::Item> hitems; - for (const auto & r : self->refs()) + for (const auto & r : self->extRefs()) hitems.push_back(Header::AnnounceUpdate { r.digest() }); for (const auto & r : self->updates()) hitems.push_back(Header::AnnounceUpdate { r.digest() }); diff --git a/src/state.cpp b/src/state.cpp index 40d4eec..31171d7 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -38,7 +38,7 @@ Ref LocalState::store(const Storage & st) const vector<Record::Item> items; if (p->identity) - items.emplace_back("id", *p->identity->ref()); + items.emplace_back("id", *p->identity->extRef()); for (const auto & x : p->shared.tip) items.emplace_back("shared", x); |