-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ssh/Connection: support multiple host keys
- Loading branch information
1 parent
79c33de
commit 9557241
Showing
10 changed files
with
145 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// SPDX-License-Identifier: BSD-2-Clause | ||
// Copyright CM4all GmbH | ||
// author: Max Kellermann <[email protected]> | ||
|
||
#include "List.hxx" | ||
#include "Key.hxx" | ||
#include "util/IterableSplitString.hxx" | ||
|
||
KeyList::KeyList() noexcept = default; | ||
KeyList::~KeyList() noexcept = default; | ||
|
||
void | ||
KeyList::Add(std::unique_ptr<Key> key) noexcept | ||
{ | ||
auto [it, inserted] = keys.try_emplace(key->GetAlgorithm(), std::move(key)); | ||
if (inserted) { | ||
if (!algorithms.empty()) | ||
algorithms.push_back(','); | ||
algorithms.append(it->first); | ||
} | ||
} | ||
|
||
const Key * | ||
KeyList::Choose(std::string_view peer_algorithms) const noexcept | ||
{ | ||
for (const std::string_view a : IterableSplitString(peer_algorithms, ',')) { | ||
if (a.empty()) | ||
continue; | ||
|
||
const auto i = keys.find(a); | ||
if (i != keys.end()) | ||
return i->second.get(); | ||
} | ||
|
||
return nullptr; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// SPDX-License-Identifier: BSD-2-Clause | ||
// Copyright CM4all GmbH | ||
// author: Max Kellermann <[email protected]> | ||
|
||
#pragma once | ||
|
||
#include <map> | ||
#include <memory> | ||
#include <string> | ||
|
||
class Key; | ||
|
||
class KeyList { | ||
std::map<std::string_view, std::unique_ptr<Key>> keys; | ||
|
||
std::string algorithms; | ||
|
||
public: | ||
KeyList() noexcept; | ||
~KeyList() noexcept; | ||
|
||
KeyList(KeyList &&) noexcept = default; | ||
KeyList &operator=(KeyList &&) noexcept = default; | ||
|
||
bool empty() const noexcept { | ||
return keys.empty(); | ||
} | ||
|
||
void Add(std::unique_ptr<Key> key) noexcept; | ||
|
||
/** | ||
* @return a comma-separated list of available server host key | ||
* algorithms | ||
*/ | ||
std::string_view GetAlgorithms() const noexcept { | ||
return algorithms; | ||
} | ||
|
||
/** | ||
* Choose a host key based on the list of algorithms received | ||
* in KEXINIT from the peer. | ||
* | ||
* @param peer_algorithms the "server_host_key_algorithms" | ||
* string from the peer's KEXINIT packet, i.e. a | ||
* comma-separated list of acceptable server host key | ||
* algorithms | ||
*/ | ||
[[gnu::pure]] | ||
const Key *Choose(std::string_view peer_algorithms) const noexcept; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
#include "ssh/MakePacket.hxx" | ||
#include "ssh/Deserializer.hxx" | ||
#include "key/Key.hxx" | ||
#include "key/List.hxx" | ||
#include "system/Error.hxx" | ||
#include "system/Urandom.hxx" | ||
#include "net/UniqueSocketDescriptor.hxx" | ||
|
@@ -36,8 +37,8 @@ SerializeKex(Serializer &s, std::span<const std::byte, KEX_COOKIE_SIZE> cookie, | |
} | ||
|
||
Connection::Connection(EventLoop &event_loop, UniqueSocketDescriptor _fd, | ||
const Key &_host_key) | ||
:host_key(_host_key), | ||
const KeyList &_host_keys) | ||
:host_keys(_host_keys), | ||
socket(event_loop) | ||
{ | ||
socket.Init(_fd.Release(), FD_TCP, | ||
|
@@ -96,7 +97,7 @@ Connection::SendKexInit() | |
|
||
const KexProposal proposal{ | ||
.kex_algorithms = "curve25519-sha256"sv, | ||
.server_host_key_algorithms = host_key.GetAlgorithm(), | ||
.server_host_key_algorithms = host_keys.GetAlgorithms(), | ||
.encryption_algorithms_client_to_server = "[email protected]"sv, | ||
.encryption_algorithms_server_to_client = "[email protected]"sv, | ||
.mac_algorithms_client_to_server = "hmac-sha2-256,hmac-sha2-512"sv, | ||
|
@@ -124,7 +125,7 @@ Connection::SendECDHKexInitReply(std::span<const std::byte> client_ephemeral_pub | |
|
||
const auto kex_host_key_length = s.PrepareLength(); | ||
const auto kex_host_key_mark = s.Mark(); | ||
host_key.SerializeKex(s); | ||
host_key->SerializeKex(s); | ||
s.CommitLength(kex_host_key_length); | ||
const auto server_host_key_blob = s.Since(kex_host_key_mark); | ||
|
||
|
@@ -159,7 +160,7 @@ Connection::SendECDHKexInitReply(std::span<const std::byte> client_ephemeral_pub | |
const auto hash = std::span{hash_buffer}.first(hashlen); | ||
|
||
const auto signature_length = s.PrepareLength(); | ||
host_key.Sign(s, hash); | ||
host_key->Sign(s, hash); | ||
s.CommitLength(signature_length); | ||
|
||
SendPacket(std::move(s)); | ||
|
@@ -180,6 +181,28 @@ Connection::HandleKexInit(std::span<const std::byte> payload) | |
{ | ||
client_kexinit = payload; | ||
|
||
Deserializer d{payload}; | ||
d.ReadN(16); // cookie | ||
d.ReadString(); // kex_algorithms | ||
const auto server_host_key_algorithms = d.ReadString(); // server_host_key_algorithms | ||
d.ReadString(); // encryption_algorithms_client_to_server | ||
d.ReadString(); // encryption_algorithms_server_to_client | ||
d.ReadString(); // mac_algorithms_client_to_server | ||
d.ReadString(); // mac_algorithms_server_to_client | ||
d.ReadString(); // compression_algorithms_client_to_server | ||
d.ReadString(); // compression_algorithms_server_to_client | ||
d.ReadString(); // languages_client_to_server | ||
d.ReadString(); // languages_server_to_client | ||
d.ReadBool(); // first_kex_packet_follows | ||
d.ReadU32(); // reserved | ||
|
||
host_key = host_keys.Choose(server_host_key_algorithms); | ||
if (host_key == nullptr) | ||
throw Disconnect{ | ||
DisconnectReasonCode::KEY_EXCHANGE_FAILED, | ||
"No supported host key"sv, | ||
}; | ||
|
||
SendKexInit(); | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters