diff options
| author | Roman Smrž <roman.smrz@seznam.cz> | 2023-09-16 11:33:40 +0200 | 
|---|---|---|
| committer | Roman Smrž <roman.smrz@seznam.cz> | 2023-09-16 20:45:26 +0200 | 
| commit | 512e20fa063e4a4525e47e048f26cc68668e7fac (patch) | |
| tree | 8e2e4907cfcf2729db0b2554fe201f1c1be16b8c | |
| parent | eefc444714b51db99f18e92634d961465fa78e11 (diff) | |
Protocol: use cookies during whole plaintext phase
| -rw-r--r-- | src/network.cpp | 3 | ||||
| -rw-r--r-- | src/network/protocol.cpp | 58 | ||||
| -rw-r--r-- | src/network/protocol.h | 7 | 
3 files changed, 46 insertions, 22 deletions
| diff --git a/src/network.cpp b/src/network.cpp index da480c3..6840f43 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -698,8 +698,7 @@ void Server::Peer::updateChannel(ReplyBuilder & reply)  	if (!holds_alternative<Identity>(identity))  		return; -	if (holds_alternative<monostate>(connection.channel()) || -			holds_alternative<NetworkProtocol::Cookie>(connection.channel())) { +	if (holds_alternative<monostate>(connection.channel())) {  		auto req = Channel::generateRequest(tempStorage,  				server.self, std::get<Identity>(identity));  		connection.channel().emplace<Stored<ChannelRequest>>(req); diff --git a/src/network/protocol.cpp b/src/network/protocol.cpp index 79c023d..93d171a 100644 --- a/src/network/protocol.cpp +++ b/src/network/protocol.cpp @@ -32,6 +32,8 @@ struct NetworkProtocol::ConnectionPriv  	mutex cmutex {};  	vector<uint8_t> buffer {}; +	optional<Cookie> receivedCookie = nullopt; +	bool confirmedCookie = false;  	ChannelState channel = monostate();  	vector<vector<uint8_t>> secureOutQueue {};  }; @@ -88,7 +90,8 @@ NetworkProtocol::PollResult NetworkProtocol::poll()  		}  		auto pst = self->ref()->storage().deriveEphemeralStorage(); -		if (auto header = Connection::receive(buffer, nullptr, pst)) { +		bool secure = false; +		if (auto header = Connection::parsePacket(buffer, nullptr, pst, secure)) {  			if (auto conn = verifyNewConnection(*header, addr))  				return NewConnection { move(*conn) }; @@ -113,6 +116,7 @@ NetworkProtocol::Connection NetworkProtocol::connect(sockaddr_in6 addr)  		vector<Header::Item> header {  			Header::Initiation { Digest(array<uint8_t, Digest::size> {}) }, +			Header::AnnounceSelf { self->ref()->digest() },  			Header::Version { defaultVersion },  		};  		conn->send(self->ref()->storage(), move(header), {}, false); @@ -311,32 +315,50 @@ optional<NetworkProtocol::Header> NetworkProtocol::Connection::receive(const Par  		}  	} -	if (auto header = receive(buf, channel, partStorage)) { +	bool secure = false; +	if (auto header = parsePacket(buf, channel, partStorage, secure)) {  		scoped_lock lock(p->cmutex); +		if (secure) +			return header; + +		if (const auto * cookieEcho = header->lookupFirst<Header::CookieEcho>()) { +			if (!p->protocol->verifyCookie(p->peerAddress, cookieEcho->value)) +				return nullopt; + +			p->confirmedCookie = true; + +			if (const auto * cookieSet = header->lookupFirst<Header::CookieSet>()) +				p->receivedCookie = cookieSet->value; + +			return header; +		} + +		if (holds_alternative<monostate>(p->channel)) { +			if (const auto * cookieSet = header->lookupFirst<Header::CookieSet>()) { +				p->receivedCookie = cookieSet->value; +				return header; +			} +		} +  		if (header->lookupFirst<Header::Initiation>()) {  			p->protocol->sendCookie(p->peerAddress);  			return nullopt;  		} - -		if (holds_alternative<monostate>(p->channel) || -				holds_alternative<Cookie>(p->channel)) -			if (const auto * cookie = header->lookupFirst<Header::CookieSet>()) -				p->channel = cookie->value; - -		return header;  	}  	return nullopt;  } -optional<NetworkProtocol::Header> NetworkProtocol::Connection::receive(vector<uint8_t> & buf, -		Channel * channel, -		const PartialStorage & partStorage) +optional<NetworkProtocol::Header> NetworkProtocol::Connection::parsePacket(vector<uint8_t> & buf, +		Channel * channel, const PartialStorage & partStorage, +		bool & secure)  {  	vector<uint8_t> decrypted;  	auto plainBegin = buf.cbegin();  	auto plainEnd = buf.cbegin(); +	secure = false; +  	if ((buf[0] & 0xE0) == 0x80) {  		if (not channel) {  			std::cerr << "unexpected encrypted packet\n"; @@ -356,6 +378,8 @@ optional<NetworkProtocol::Header> NetworkProtocol::Connection::receive(vector<ui  				return nullopt;  			}  		} + +		secure = true;  	}  	else if ((buf[0] & 0xE0) == 0x60) {  		plainBegin = buf.begin(); @@ -398,11 +422,13 @@ bool NetworkProtocol::ConnectionPriv::send(const PartialStorage & partStorage,  		if (auto uptr = get_if<unique_ptr<Channel>>(&this->channel))  			channel = uptr->get(); -		if (channel || secure) +		if (channel || secure) {  			data.push_back(0x00); -		else if (const auto * ptr = get_if<Cookie>(&this->channel)) { -			header.items.push_back(Header::CookieEcho { ptr->value }); -			header.items.push_back(Header::Version { defaultVersion }); +		} else { +			if (receivedCookie) +				header.items.push_back(Header::CookieEcho { receivedCookie->value }); +			if (!confirmedCookie) +				header.items.push_back(Header::CookieSet { protocol->generateCookie(peerAddress) });  		}  		part = header.toObject(partStorage).encode(); diff --git a/src/network/protocol.h b/src/network/protocol.h index dda2ffb..3d7c073 100644 --- a/src/network/protocol.h +++ b/src/network/protocol.h @@ -54,7 +54,6 @@ public:  	struct Cookie { vector<uint8_t> value; };  	using ChannelState = variant<monostate, -		Cookie,  		Stored<ChannelRequest>,  		shared_ptr<struct WaitingRef>,  		Stored<ChannelAccept>, @@ -115,9 +114,9 @@ public:  	void trySendOutQueue();  private: -	static optional<Header> receive(vector<uint8_t> & buf, -			Channel * channel, -			const PartialStorage & st); +	static optional<Header> parsePacket(vector<uint8_t> & buf, +			Channel * channel, const PartialStorage & st, +			bool & secure);  	unique_ptr<ConnectionPriv> p;  }; |