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); |