aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-09-02 08:26:50 -0400
committerJack Lloyd <[email protected]>2017-09-02 08:26:50 -0400
commite2036b0dba7084728b209fc3901398e8d46b72b9 (patch)
treefe3abd50be827c3ebd7d885f15f5f4359dc5eea8 /src
parent6cea745e6408ac4cf266086681b5d65209b33d84 (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.cpp103
-rw-r--r--src/cli/cli.h28
-rw-r--r--src/cli/credentials.h1
-rw-r--r--src/cli/encryption.cpp36
-rw-r--r--src/cli/tls_client.cpp4
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";
}
}
}