diff options
author | Jack Lloyd <[email protected]> | 2017-09-02 08:26:50 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-09-02 08:26:50 -0400 |
commit | e2036b0dba7084728b209fc3901398e8d46b72b9 (patch) | |
tree | fe3abd50be827c3ebd7d885f15f5f4359dc5eea8 /src | |
parent | 6cea745e6408ac4cf266086681b5d65209b33d84 (diff) |
Avoid using std::cout and std::cerr within cli code
Prevents redirection using --output and --error-output
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/asn1.cpp | 103 | ||||
-rw-r--r-- | src/cli/cli.h | 28 | ||||
-rw-r--r-- | src/cli/credentials.h | 1 | ||||
-rw-r--r-- | src/cli/encryption.cpp | 36 | ||||
-rw-r--r-- | src/cli/tls_client.cpp | 4 |
5 files changed, 87 insertions, 85 deletions
diff --git a/src/cli/asn1.cpp b/src/cli/asn1.cpp index 1ed60258f..5c90a3c5b 100644 --- a/src/cli/asn1.cpp +++ b/src/cli/asn1.cpp @@ -18,7 +18,6 @@ #include <botan/pem.h> #include <botan/charset.h> -#include <iostream> #include <iomanip> #include <sstream> #include <ctype.h> @@ -26,13 +25,6 @@ // Set this if your terminal understands UTF-8; otherwise output is in Latin-1 #define UTF8_TERMINAL 1 -/* - What level the outermost layer of stuff is at. Probably 0 or 1; asn1parse - uses 0 as the outermost, while 1 makes more sense to me. 2+ doesn't make - much sense at all. -*/ -#define INITIAL_LEVEL 0 - namespace Botan_CLI { namespace { @@ -65,17 +57,21 @@ std::string url_encode(const std::vector<uint8_t>& in) return out.str(); } -void emit(const std::string& type, size_t level, size_t length, const std::string& value = "") +void emit(std::ostream& out, + const std::string& type, + size_t level, size_t length, + const std::string& value = "") { + // TODO make these configurable const size_t LIMIT = 4 * 1024; const size_t BIN_LIMIT = 1024; - std::ostringstream out; + std::streampos starting_pos = out.tellp(); out << " d=" << std::setw(2) << level << ", l=" << std::setw(4) << length << ": "; - for(size_t i = INITIAL_LEVEL; i != level; ++i) + for(size_t i = 0; i != level; ++i) { out << ' '; } @@ -96,12 +92,7 @@ void emit(const std::string& type, size_t level, size_t length, const std::strin if(value != "" && !should_skip) { - if(out.tellp() % 2 == 0) - { - out << ' '; - } - - while(out.tellp() < 50) + while(out.tellp() - starting_pos < 50) { out << ' '; } @@ -109,7 +100,7 @@ void emit(const std::string& type, size_t level, size_t length, const std::strin out << value; } - std::cout << out.str() << std::endl; + out << "\n"; } std::string type_name(Botan::ASN1_Tag type) @@ -169,7 +160,9 @@ std::string type_name(Botan::ASN1_Tag type) } } -void decode(Botan::BER_Decoder& decoder, size_t level) +void decode(std::ostream& output, + Botan::BER_Decoder& decoder, + size_t level) { Botan::BER_Object obj = decoder.get_next_object(); @@ -192,13 +185,13 @@ void decode(Botan::BER_Decoder& decoder, size_t level) Botan::BER_Decoder cons_info(obj.value); if(type_tag == Botan::SEQUENCE) { - emit("SEQUENCE", level, length); - decode(cons_info, level + 1); + emit(output, "SEQUENCE", level, length); + decode(output, cons_info, level + 1); // recurse } else if(type_tag == Botan::SET) { - emit("SET", level, length); - decode(cons_info, level + 1); + emit(output, "SET", level, length); + decode(output, cons_info, level + 1); // recurse } else { @@ -222,27 +215,27 @@ void decode(Botan::BER_Decoder& decoder, size_t level) name = type_name(type_tag) + " (cons)"; } - emit(name, level, length); - decode(cons_info, level + 1); + emit(output, name, level, length); + decode(output, cons_info, level + 1); // recurse } } else if((class_tag & Botan::APPLICATION) || (class_tag & Botan::CONTEXT_SPECIFIC)) { #if 0 std::vector<uint8_t> bits; - data.decode(bits, type_tag); + data.decode(out, bits, type_tag); try { Botan::BER_Decoder inner(bits); - decode(inner, level + 1); + decode(output, inner, level + 1); // recurse } catch(...) { - emit("[" + std::to_string(type_tag) + "]", level, length, url_encode(bits)); + emit(output, "[" + std::to_string(type_tag) + "]", level, length, url_encode(bits)); } #else - emit("[" + std::to_string(type_tag) + "]", level, length, url_encode(bits)); + emit(output, "[" + std::to_string(type_tag) + "]", level, length, url_encode(bits)); #endif } else if(type_tag == Botan::OBJECT_ID) @@ -256,7 +249,7 @@ void decode(Botan::BER_Decoder& decoder, size_t level) out += " [" + oid.as_string() + "]"; } - emit(type_name(type_tag), level, length, out); + emit(output, type_name(type_tag), level, length, out); } else if(type_tag == Botan::INTEGER || type_tag == Botan::ENUMERATED) { @@ -289,17 +282,17 @@ void decode(Botan::BER_Decoder& decoder, size_t level) str += static_cast<char>(rep[i]); } - emit(type_name(type_tag), level, length, str); + emit(output, type_name(type_tag), level, length, str); } else if(type_tag == Botan::BOOLEAN) { bool boolean; data.decode(boolean); - emit(type_name(type_tag), level, length, (boolean ? "true" : "false")); + emit(output, type_name(type_tag), level, length, (boolean ? "true" : "false")); } else if(type_tag == Botan::NULL_TAG) { - emit(type_name(type_tag), level, length); + emit(output, type_name(type_tag), level, length); } else if(type_tag == Botan::OCTET_STRING) { @@ -309,11 +302,11 @@ void decode(Botan::BER_Decoder& decoder, size_t level) try { Botan::BER_Decoder inner(decoded_bits); - decode(inner, level + 1); + decode(output, inner, level + 1); } catch(...) { - emit(type_name(type_tag), level, length, url_encode(decoded_bits)); + emit(output, type_name(type_tag), level, length, url_encode(decoded_bits)); } } else if(type_tag == Botan::BIT_STRING) @@ -344,7 +337,7 @@ void decode(Botan::BER_Decoder& decoder, size_t level) bit_str += (the_bit ? "1" : "0"); } - emit(type_name(type_tag), level, length, bit_str); + emit(output, type_name(type_tag), level, length, bit_str); } else if(type_tag == Botan::PRINTABLE_STRING || type_tag == Botan::NUMERIC_STRING || @@ -358,56 +351,64 @@ void decode(Botan::BER_Decoder& decoder, size_t level) data.decode(str); if(UTF8_TERMINAL) { - emit(type_name(type_tag), level, length, + emit(output, type_name(type_tag), level, length, Botan::Charset::transcode(str.iso_8859(), Botan::UTF8_CHARSET, Botan::LATIN1_CHARSET)); } else { - emit(type_name(type_tag), level, length, str.iso_8859()); + emit(output, type_name(type_tag), level, length, str.iso_8859()); } } else if(type_tag == Botan::UTC_TIME || type_tag == Botan::GENERALIZED_TIME) { Botan::X509_Time time; data.decode(time); - emit(type_name(type_tag), level, length, time.readable_string()); + emit(output, type_name(type_tag), level, length, time.readable_string()); } else { - std::cout << "Unknown ASN.1 tag class=" - << static_cast<int>(class_tag) - << " type=" - << static_cast<int>(type_tag) << std::endl; + output << "Unknown ASN.1 tag class=" << static_cast<int>(class_tag) + << " type=" << static_cast<int>(type_tag) << "\n";; } obj = decoder.get_next_object(); } } +std::string format_asn1(const uint8_t in[], size_t len) + { + std::ostringstream out; + Botan::BER_Decoder dec(in, len); + decode(out, dec, 0); + return out.str(); + } + } class ASN1_Printer final : public Command { public: - ASN1_Printer() : Command("asn1print file") {} + ASN1_Printer() : Command("asn1print --pem file") {} void go() override { - Botan::DataSource_Stream in(get_arg("file")); + const std::string input = get_arg("file"); + + std::vector<uint8_t> contents; - if(!Botan::PEM_Code::matches(in)) + if(flag_set("pem")) { - Botan::BER_Decoder decoder(in); - decode(decoder, INITIAL_LEVEL); + std::string pem_label; + contents = unlock(Botan::PEM_Code::decode(slurp_file_as_str(input), pem_label)); } else { - std::string label; // ignored - Botan::BER_Decoder decoder(Botan::PEM_Code::decode(in, label)); - decode(decoder, INITIAL_LEVEL); + contents = slurp_file(input); } + + output() << format_asn1(contents.data(), contents.size()); } }; diff --git a/src/cli/cli.h b/src/cli/cli.h index 5955dfe19..249c87722 100644 --- a/src/cli/cli.h +++ b/src/cli/cli.h @@ -417,25 +417,42 @@ class Command /* * Read an entire file into memory and return the contents */ - std::vector<uint8_t> slurp_file(const std::string& input_file) const + std::vector<uint8_t> slurp_file(const std::string& input_file, + size_t buf_size = 0) const { std::vector<uint8_t> buf; auto insert_fn = [&](const uint8_t b[], size_t l) { buf.insert(buf.end(), b, b + l); }; - this->read_file(input_file, insert_fn); + this->read_file(input_file, insert_fn, buf_size); return buf; } - std::string slurp_file_as_str(const std::string& input_file) + /* + * Read an entire file into memory and return the contents + */ + Botan::secure_vector<uint8_t> slurp_file_locked(const std::string& input_file, + size_t buf_size = 0) const + { + Botan::secure_vector<uint8_t> buf; + auto insert_fn = [&](const uint8_t b[], size_t l) + { + buf.insert(buf.end(), b, b + l); + }; + this->read_file(input_file, insert_fn, buf_size); + return buf; + } + + std::string slurp_file_as_str(const std::string& input_file, + size_t buf_size = 0) const { std::string str; auto insert_fn = [&](const uint8_t b[], size_t l) { str.append(reinterpret_cast<const char*>(b), l); }; - this->read_file(input_file, insert_fn); + this->read_file(input_file, insert_fn, buf_size); return str; } @@ -471,7 +488,8 @@ class Command while(in.good()) { in.read(reinterpret_cast<char*>(buf.data()), buf.size()); - consumer_fn(buf.data(), static_cast<size_t>(in.gcount())); + const size_t got = static_cast<size_t>(in.gcount()); + consumer_fn(buf.data(), got); } } diff --git a/src/cli/credentials.h b/src/cli/credentials.h index 3b7a177fc..da83e73e9 100644 --- a/src/cli/credentials.h +++ b/src/cli/credentials.h @@ -10,7 +10,6 @@ #include <botan/pkcs8.h> #include <botan/credentials_manager.h> #include <botan/x509self.h> -#include <iostream> #include <fstream> #include <memory> diff --git a/src/cli/encryption.cpp b/src/cli/encryption.cpp index d3dfdd466..a09101fe5 100644 --- a/src/cli/encryption.cpp +++ b/src/cli/encryption.cpp @@ -11,7 +11,6 @@ #include <botan/aes.h> #include <botan/aead.h> -#include <iostream> #include <iterator> #include <sstream> @@ -75,29 +74,12 @@ secure_vector<byte> do_crypt(const std::string &cipher, return buf; } -secure_vector<byte> get_stdin() - { - secure_vector<byte> out; - std::streamsize reserved_size = 1048576; // 1 MiB - out.reserve(reserved_size); - - std::istreambuf_iterator<char> iterator(std::cin.rdbuf()); // stdin iterator - std::istreambuf_iterator<char> EOS; // end-of-range iterator - std::copy(iterator, EOS, std::back_inserter(out)); - return out; - } - -void to_stdout(const secure_vector<byte> &data) - { - std::copy(data.begin(), data.end(), std::ostreambuf_iterator<char>(std::cout)); - } - } class Encryption : public Command { public: - Encryption() : Command("encryption --decrypt --mode= --key= --iv= --ad=") {} + Encryption() : Command("encryption --buf-size=4096 --decrypt --mode= --key= --iv= --ad=") {} void go() override { @@ -112,14 +94,16 @@ class Encryption : public Command throw CLI_Usage_Error(error.str()); } - std::string key_hex = get_arg("key"); - std::string iv_hex = get_arg("iv"); - std::string ad_hex = get_arg_or("ad", ""); + const std::string key_hex = get_arg("key"); + const std::string iv_hex = get_arg("iv"); + const std::string ad_hex = get_arg_or("ad", ""); + const size_t buf_size = get_arg_sz("buf-size"); + + Botan::secure_vector<uint8_t> input = this->slurp_file_locked("-", buf_size); - auto input = get_stdin(); if (verbose()) { - std::cerr << "Got " << input.size() << " bytes of input data." << std::endl; + error_output() << "Got " << input.size() << " bytes of input data.\n"; } auto key = SymmetricKey(key_hex); @@ -127,8 +111,8 @@ class Encryption : public Command auto ad = OctetString(ad_hex); auto direction = flag_set("decrypt") ? Cipher_Dir::DECRYPTION : Cipher_Dir::ENCRYPTION; - auto out = do_crypt(VALID_MODES[mode], input, key, iv, ad, direction); - to_stdout(out); + auto data = do_crypt(VALID_MODES[mode], input, key, iv, ad, direction); + std::copy(data.begin(), data.end(), std::ostreambuf_iterator<char>(output())); } }; diff --git a/src/cli/tls_client.cpp b/src/cli/tls_client.cpp index 4625ca3f1..2e690feab 100644 --- a/src/cli/tls_client.cpp +++ b/src/cli/tls_client.cpp @@ -347,14 +347,14 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks ocsp_timeout, ocsp); - std::cout << "Certificate validation status: " << result.result_string() << "\n"; + output() << "Certificate validation status: " << result.result_string() << "\n"; if(result.successful_validation()) { auto status = result.all_statuses(); if(status.size() > 0 && status[0].count(Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD)) { - std::cout << "Valid OCSP response for this server\n"; + output() << "Valid OCSP response for this server\n"; } } } |