aboutsummaryrefslogtreecommitdiff
path: root/ssh-agent-filter.C
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-agent-filter.C')
-rw-r--r--ssh-agent-filter.C74
1 files changed, 68 insertions, 6 deletions
diff --git a/ssh-agent-filter.C b/ssh-agent-filter.C
index 2878678..74b15ab 100644
--- a/ssh-agent-filter.C
+++ b/ssh-agent-filter.C
@@ -1,7 +1,7 @@
/*
* ssh-agent-filter.C -- filtering proxy for ssh-agent meant to be forwarded to untrusted servers
*
- * Copyright (C) 2013-2016 Timo Weingärtner <timo@tiwe.de>
+ * Copyright (C) 2013-2018 Timo Weingärtner <timo@tiwe.de>
*
* This file is part of ssh-agent-filter.
*
@@ -110,18 +110,18 @@ string md5_hex (string const & s) {
md5_update(&ctx, s.size(), reinterpret_cast<uint8_t const *>(s.data()));
uint8_t bin[MD5_DIGEST_SIZE];
md5_digest(&ctx, MD5_DIGEST_SIZE, bin);
- uint8_t hex[BASE16_ENCODE_LENGTH(MD5_DIGEST_SIZE)];
+ char hex[BASE16_ENCODE_LENGTH(MD5_DIGEST_SIZE)];
base16_encode_update(hex, MD5_DIGEST_SIZE, bin);
- return {reinterpret_cast<char const *>(hex), sizeof(hex)};
+ return {hex, sizeof(hex)};
}
string base64_encode (string const & s) {
struct base64_encode_ctx ctx;
base64_encode_init(&ctx);
- uint8_t b64[BASE64_ENCODE_LENGTH(s.size())];
+ char b64[BASE64_ENCODE_LENGTH(s.size())];
auto len = base64_encode_update(&ctx, b64, s.size(), reinterpret_cast<uint8_t const *>(s.data()));
len += base64_encode_final(&ctx, b64 + len);
- return {reinterpret_cast<char const *>(b64), len};
+ return {b64, len};
}
void cloexec (int fd) {
@@ -329,6 +329,65 @@ bool confirm (string const & question) {
}
}
+bool dissect_auth_data_ssh_cert (rfc4251::string const & data, string & request_description) try {
+ io::stream<io::array_source> datastream{data.data(), data.size()};
+ arm(datastream);
+
+ // Format specified in https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=1.13
+ rfc4251::string keytype{datastream};
+ std::string keytype_str{keytype};
+ {
+ // 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;
+ auto suffix_start = keytype_str.end() - suffix.length();
+ if (!std::equal(suffix.begin(), suffix.end(), suffix_start))
+ return false;
+ keytype_str.erase(suffix_start, keytype_str.end());
+ }
+ rfc4251::string nonce{datastream};
+ std::ostringstream key_to_be_signed{};
+ if (keytype_str == "ssh-rsa") {
+ rfc4251::string e{datastream};
+ rfc4251::string n{datastream};
+ key_to_be_signed << rfc4251::string{keytype_str} << e << n;
+ } else if (keytype_str == "ssh-dss") {
+ rfc4251::string p{datastream};
+ rfc4251::string q{datastream};
+ rfc4251::string g{datastream};
+ rfc4251::string y{datastream};
+ key_to_be_signed << rfc4251::string{keytype_str} << p << q << g << y;
+ } else if (keytype_str == "ecdsa-sha2-nistp256"
+ || keytype_str == "ecdsa-sha2-nistp384"
+ || keytype_str == "ecdsa-sha2-nistp521") {
+ rfc4251::string curve{datastream};
+ rfc4251::string public_key{datastream};
+ key_to_be_signed << rfc4251::string{keytype_str} << curve << public_key;
+ } else if (keytype_str == "ssh-ed25519") {
+ rfc4251::string pk{datastream};
+ key_to_be_signed << rfc4251::string{keytype_str} << pk;
+ } else {
+ return false;
+ }
+ rfc4251::uint64 serial{datastream};
+ rfc4251::uint32 type{datastream};
+ rfc4251::string key_id{datastream};
+ rfc4251::string valid_principals{datastream};
+ rfc4251::uint64 valid_after{datastream};
+ rfc4251::uint64 valid_before{datastream};
+ rfc4251::string critical_options{datastream};
+ rfc4251::string extensions{datastream};
+ rfc4251::string reserved{datastream};
+ rfc4251::string signature_key{datastream};
+
+ request_description = "The request is for a certificate signature on key " + base64_encode(key_to_be_signed.str()) + ".";
+
+ return true;
+} catch (...) {
+ return false;
+}
+
bool dissect_auth_data_ssh (rfc4251::string const & data, string & request_description) try {
io::stream<io::array_source> datastream{data.data(), data.size()};
arm(datastream);
@@ -448,6 +507,8 @@ rfc4251::string handle_request (rfc4251::string const & r) {
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.";
@@ -543,8 +604,9 @@ int main (int const argc, char const * const * const argv) {
exit(EX_OK);
}
+ // the following stuff is optional, so we don't do error checking
setsid();
- chdir("/");
+ static_cast<void>(chdir("/"));
int devnull = open("/dev/null", O_RDWR);
dup2(devnull, 0);
dup2(devnull, 1);