From d17162f5c6f7d002bf68fac48bcadd2db0c033e7 Mon Sep 17 00:00:00 2001 From: Timo Weingärtner Date: Sun, 18 Apr 2021 00:02:42 +0200 Subject: use C++17 std::optional for dissectors, refactor --- ssh-agent-filter.C | 63 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/ssh-agent-filter.C b/ssh-agent-filter.C index e98123c..c513804 100644 --- a/ssh-agent-filter.C +++ b/ssh-agent-filter.C @@ -64,6 +64,8 @@ using std::pair; using std::mutex; using std::lock_guard; +#include + #include #include @@ -326,9 +328,10 @@ bool confirm (string const & question) { } } -bool dissect_auth_data_ssh_cert (rfc4251::string const & data, string & request_description) try { +std::optional dissect_auth_data_ssh_cert (rfc4251::string const & data) try { io::stream datastream{data.data(), data.size()}; arm(datastream); + string request_description{}; // Format specified in https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=1.13 rfc4251::string keytype{datastream}; @@ -337,10 +340,10 @@ bool dissect_auth_data_ssh_cert (rfc4251::string const & data, string & request_ // check for and remove suffix to get the base keytype std::string const suffix{"-cert-v01@openssh.com"}; if (keytype_str.length() <= suffix.length()) - return false; + return {}; auto suffix_start = keytype_str.end() - suffix.length(); if (!std::equal(suffix.begin(), suffix.end(), suffix_start)) - return false; + return {}; keytype_str.erase(suffix_start, keytype_str.end()); } rfc4251::string nonce{datastream}; @@ -365,7 +368,7 @@ bool dissect_auth_data_ssh_cert (rfc4251::string const & data, string & request_ rfc4251::string pk{datastream}; key_to_be_signed << rfc4251::string{keytype_str} << pk; } else { - return false; + return {}; } rfc4251::uint64 serial{datastream}; rfc4251::uint32 type{datastream}; @@ -380,14 +383,15 @@ bool dissect_auth_data_ssh_cert (rfc4251::string const & data, string & request_ request_description = "The request is for a certificate signature on key " + base64_encode(key_to_be_signed.str()) + "."; - return true; + return request_description; } catch (...) { - return false; + return {}; } -bool dissect_auth_data_ssh (rfc4251::string const & data, string & request_description) try { +std::optional dissect_auth_data_ssh (rfc4251::string const & data) try { io::stream datastream{data.data(), data.size()}; arm(datastream); + string request_description{}; // Format specified in RFC 4252 Section 7 rfc4251::string session_identifier{datastream}; @@ -450,11 +454,25 @@ bool dissect_auth_data_ssh (rfc4251::string const & data, string & request_descr } } catch (...) {} - return true; + return request_description; } catch (...) { - return false; + return {}; +} + +string describe_sign_request (rfc4251::string const & data_to_be_signed) { + auto const dissectors = { + dissect_auth_data_ssh_cert, + dissect_auth_data_ssh, + }; + std::optional request_description; + for (auto const dissector : dissectors) + if (request_description = dissector(data_to_be_signed); request_description) + break; + + return request_description.value_or("The request format is unknown."); } + rfc4251::string handle_request (rfc4251::string const & r) { io::stream request{r.data(), r.size()}; rfc4251::string ret; @@ -492,30 +510,19 @@ rfc4251::string handle_request (rfc4251::string const & r) { case SSH2_AGENTC_SIGN_REQUEST: { rfc4251::string key{request}; - rfc4251::string data{request}; + rfc4251::string data_to_be_signed{request}; rfc4251::uint32 flags{request}; bool allow{false}; if (allowed_pubkeys.count(key)) allow = true; - else { - if (auto it = confirmed_pubkeys.find(key); it != confirmed_pubkeys.end()) { - string request_description; - bool dissect_ok{false}; - if (!dissect_ok) - dissect_ok = dissect_auth_data_ssh_cert(data, request_description); - if (!dissect_ok) - dissect_ok = dissect_auth_data_ssh(data, request_description); - if (!dissect_ok) - request_description = "The request format is unknown."; - - string question = "Something behind the ssh-agent-filter"; - if (saf_name.length()) - question += " named '" + saf_name + "'"; - question += " requested use of the key named '" + it->second + "'.\n"; - question += request_description; - allow = confirm(question); - } + else if (auto it = confirmed_pubkeys.find(key); it != confirmed_pubkeys.end()) { + string question = "Something behind the ssh-agent-filter"; + if (saf_name.length()) + question += " named '" + saf_name + "'"; + question += " requested use of the key named '" + it->second + "'.\n"; + question += describe_sign_request(data_to_be_signed); + allow = confirm(question); } if (allow) { -- cgit v1.2.3